Compare commits

...

5 Commits

Author SHA1 Message Date
wu xiangkai
5691fa3bef 日常提交 2022-09-30 16:43:11 +08:00
wu xiangkai
76dd1b3014 日常提交 2022-09-29 15:46:37 +08:00
wu xiangkai
ef9dfbf96c 日常提交 2022-09-29 09:35:56 +08:00
wu xiangkai
835d8f9d72 日常提交 2022-09-29 09:29:51 +08:00
0bfb27923b 日常提交 2022-09-29 01:10:24 +08:00

View File

@@ -214,3 +214,218 @@ select current_timestamp(4);
'2011-12-31 12:00:00'
```
- 当time类型转化为date时逻辑和上面一样但是会舍弃得到datetime结果的time部分即结果为'2012-01-01'、'2012-01-02'或'2011-12-31'
#### 时间类型之间的显式转换
时间类型之间的显式转换可以覆盖隐式转换。例如在比较date类型和datetime类型时默认会将date类型转化为datetime类型之后再比较两个datetime类型。
如果想要再比较date类型和datetime类型时忽略datetime的time部分可以手动将datetime类型转化为date类型之后再进行比较。
```sql
# 将datetime类型手动通过cast函数转化为date类型之后再进行比较
date_col = CAST(datetime_col AS DATE)
```
#### 将时间类型转化为数值类型
如果想要将时间类型转化为数值类型,可以使用如下方式:
```sql
select datetime_col+0,date_col+0,time_col+0,timestamp_col+0;
```
当时间类型转化为数值类型时如果时间类型没有小数部分N为0则会转化为整型类型如果时间类型含有小数部分则会转化为decimal类型decimal类型具有n位小数。
## String Data Type
mysql中String类型可以分为如下
- CHAR
- VARCHAR
- BINARY
- VARBINARY
- BLOB
- TEXT
- ENUM
- SET
### mysql中String类型的长度单位
> 对于字符类型String的列例如CHAR,VARCHAR,TEXT)mysql将其长度规格指定为字符单元。
> 对于二进制类型的String列例如BLOB,BINARY,VARBINARY),mysql将长度规格指定为字节单元。
### 为字符类型String指定字符集和排序规则
对于字符类型的String字段CHAR,VARCHAR,TEXT,ENUM,SET)可以通过CHARACTER SET属性指定该String字段的字符集并且可以通过COLLATE属性指定该字段的排序规则。
> 为字符类型String指定character set和collate的规则
> 1. 如果charset和collate都被指定则指定的charset和collate被使用
> 2. 如果charset被指定而collate未被指定那么指定的charset和charset默认的collate会被使用
> 3. 如果collate被指定但是charset未被指定那么指定的collate和collate关联的charset会被使用
> 4. 如果charset和collate都没有被指定那么该字符类型String字段会使用该table表对应的charset和collate
#### BINARY属性
binary属性是用来指定二进制collate的快捷方式。当使用binary属性来修饰字符类型String字段后该字段的比较和排序都基于的是字符编码的数值而不是字符排序。
```sql
CREATE TABLE t
(
c1 VARCHAR(10) CHARACTER SET latin1 BINARY,
c2 TEXT BINARY
) CHARACTER SET utf8mb4;
```
### CHAR[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]
该String为固定长度为M的字符串存储时会再字符串的右边一直填充空格字符直到字符串长度为M。M代表
### VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name]
M代表该列字段最长支持的字符长度以字符为单位而不是字节。M的范围可以为 0到65,535。varchar类型的最长长度受mysql表数据的最大row size限制row size最大为65,535 bytes该上限由该行数据的所有字段之间进行共享。***除了rowsize限制之外varchar类型的最长长度也受到选用字符集的限制***如utf8mb3字符集每个字符最多需要3个字节故而对于utf8mb3字符集最多可以含21,844个字符。***每个字符需要的字节数也会影响该varchar类型含有的字符数M的上限。***
### BINARY[(M)]
BINARY类型和CHAR和VARCHAR类型类似但是BINARY类型存储的是二进制类型以字节为单位。M代表该列的长度以二进制字节为单位。***如果M省略则M默认为1***
### VARBINARY(M)
VARBINARY类型和VARCHAR类型类似但是存储的是以字节为单位的二进制数据。M代表该列字段以字节为单位的最长长度。
### tinyblob
tinyblob类型最多可以存储255个字节长度的二进制数据。每个tinyblob类型的数据存储都需要用一个字节的前缀来记录该tinyblob值的长度以字节为单位
### tinytext [CHARACTER SET charset_name] [COLLATE collation_name]
text类型的数据但是最多存储255个字节长度的字符串。如果字符串中包含的字符占用多个字节那么字符的最大个数小于255.每个tinytext类型值采用一个字节来记录该tinytext类型值的长度以字节为单位
### blob[(M)]
一个blob列最多含有65535(2^16-1)个字节。blob类型会使用两个字节的前缀来记录该blob类型的最大长度以字节为单位
> 可以为blob类型指定一个M如果M被指定那么mysql在创建该列时会使用可以包含M个字节数据的最小的blob类型。
### text[(M)]
一个text列最多可以含有65535个字符的数据。如果text类型的值含有多字节字符那么最大字符数量将小于65535.每个text列都会采用2字节的前缀用来记录该text值长度以字节为单位
> 可以为text类型指定一个M如果M被指定那么mysql在创建该列时会采用可以包含M个***字符***的最小类型的text。
### mediumblob
一个blob列最多可以存储16,777,2152^24-1约16MB)个字节的二进制数据该类型会使用3字节的前缀来记录长度。
### mediumtext [CHARACTER SET charset_name] [COLLATE collation_name]
一个text列最多可以存储16,777,2152^24-1约16MB)个字符的文数据如果该text列的值含有多字节字符那么该列存储字符的最大数量少于该上限。每个mediumtext类型使用3字节的前缀来记录长度。
### longblob
一个blob列最多可以存储4,294,967,295 2^32-1约4GB)字节的二进制数据。每个longblob类型都使用4字节前缀来记录该longblob列的长度以字节为单位
### longtext [CHARACTER SET charset_name] [COLLATE collation_name]
一个text列最多可以存储4,294,967,295个字符的文本。如果含有多字节字符那么存储的最大字符数量会小于该上限。每个longtext类型会使用4字节的前缀来存储该值长度以字节为单位
### ENUM('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]
枚举类型一个字段可以含有value1value2……中的一个值或者null。enum类型在内部是通过整数类型来表示的value1从1开始可以通过select enum_col+0的形式来查看整数值。
> enum类型最多可以含有 65,535 个不同的enum元素。
> 对于每个enum元素其最大支持长度需要满足如下条件
> - M<=255
> - M * w<=1020
>
> 其中M是字符串文本的字符长度而w则是该文本字符所属字符集中单个字符所需要的最大字节数
### SET('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]
string集合每个string对象可以0个或多个值每个值都必须属于value1value2……。set类型在内部通过int表示。
> set类型最多可以含有64个不同的值。
> 对于每个set元素其最大支持长度需要满足如下条件
> - M<=255
> - M * w<=1020
>
> 其中M是字符串文本的字符长度而w则是该文本字符所属字符集中单个字符所需要的最大字节数
> 对于set类型字段插入时如果包含set类型中多个值多个值之间可以通过逗号','分隔
> 对于包含多个set元素的值其值中元素的顺序和出现次数并不重要'b,b,a,c'和'c,b,b,c,a'在插入后都会变为'a,b,c'
> 可以通过find_in_set('value',set_col)来查询某个值是否在set_col中
### char和varchar类型
对于char类型其长度是固定的并且长度需要在创建表字段时指定长度位于0到255之间。当char类型的值在存储时***会右填充空格直到长度到达指定长度M***。当char类型的值在获取时***会删除尾随填充的空格除非PAD_CHAR_TO_FULL_LENGTH的sql mode被启用***。
> 如果字段类型被设置为char类型并且pad_char_to_full_length关闭那么如果向char类型字段中存入字符串***在取出存入字符串时,存入字符串末尾若存在空格,那么在取出字符串时会删除尾随空格,即使尾随空格不是存入时填充的而是字符串本身就含有的尾随空格***
> ```sql
> char_col char(30)
>
> # 插入字符串值存在尾随空格
> insert into string_tb(char_col) values (' a ');
> # 获取时,字符串本身含有的尾随空格也会被删除
> # 返回值并不是' a 1'而是' a1'
> select concat(char_col,'1') from string_tb;
> ```
#### varchar类型的存储
相较于char类型varchar类型在存储时会额外存储1到2个字节长度的前缀用来记录该varchar类型的长度以字节为单位。***当该varchar类型值存储不超过255字节时使用一个字节来记录长度否则使用两个字节来记录长度***。
#### varchar和char类型的赋值
如果对一个varchar或char类型的字段进行赋值操作且赋值超过该类型的最大长度
- 如果strict_mode没有开启那么赋的值会被截断并且产生一个warning。
- 如果strict_mode已经被启用那么在截断非空格字符时会产生一个异常并且阻止插入操作。
- 对于varchar类型在插入时超过该列长度限制的尾随空格将会被截断并且会生成一个warning不论strict_mode是否开启。
- 对于char类型在插入时超过该列长度限制的尾随空格也会被截断并且截断操作是静默的并不会生成warning。
#### 在比较varchar类型和char类型时对后缀空格的处理
mysql的collate具有一个pad attribute可以有两个值
- pad space绝大多数的mysql collate都具有pad space属性
- no pad
pad space和no pad的区别
- pad space在比较时尾随空格并不会参加比较尾随空格并不重要
- no pad在比较时尾随空格参与比较尾随空格在比较时重要
> 默认情况下mysql默认字符集为utf8mb4该字符集默认collate为utf8mb4_0900_ai_ci其pad attribute为no pad。故而在默认情况下mysql对字符串进行比较时***忽略大小写并且尾随空格参与比较***。
> 如果某字符串列其collate的pad attribute为pad space且该列拥有unique约束那么在插入值时'a'和'a '同时插入会对该列产生duplicate-key错误。
### binary和varbinary类型
binary,varbinary类型和char,varchar类型相似不同的是binary、varbinary类型存储二进制形式的字符串。
> 当插入字符串超过binary或varbinary的最长限制长度时若***strict mode未启用则字符串会被截断来适应该二进制列的最大长度并且会产生一个warning***;若***strcit mode已启用那么会抛出异常并且插入失败***
#### binary存储值时的逻辑
当binary类型的值被存储时该插入的值会右填充0x00的值直到到达指定长度。并且在对binary值进行获取时***并不会删除尾随0x00。***
在对binary类型值进行比较时所有字节都重要比较时并不会忽略尾随0x00字节。
> 对于binary类型其和char类型不同并不删除尾随字符其意味着如果a同时插入binary(3)的col_3列和binary(6)的col_6列从col_3和col_6中取出存储的值进行比较时col_3和col_6取出的值并不相同col_3为0x610000col_6为0x610000000000。
#### varbinary存储时的逻辑
对于varbinary类型存储时并不会插入尾随字符获取时也不会删除尾随字符。
### blob类型和text类型
blob类型可以看作一个存储大量二进制字符串数据的对象而text类型可以看作一个存储大量字符型字符串的对象。
> 如果strict mode没有开启那么在给blob类型字段分配超过其长度限制的值时会对分配的值进行截断并且抛出一个warning如果strict mode已经开启那么当截断非空格字符时会抛出异常并且插入失败。
> 对于text类型如果插入时对插入值的尾随空格进行截断那么会抛出警告无论strict mode是否开启。
对于blob类型和text类型在插入时并不会有向右的填充字符在获取时也不会删除尾随字符。类似于varchar和varbinary
#### 关于text类型作为索引的比较逻辑
如果将text类型的列作为索引必须要指定索引前缀长度当text值小于索引前缀长度时对索引列的text类型值进行比较时会向右填充空格。即如果该索引需要unique约束那么两个除了后缀空格数目外完全相同的text值将会产生duplicate-key异常。
#### blob/text类型与varchar/varbinary类型的区别
在大多数情况下blob/text类型和varchar/varbinary都相同但是在如下方面会有所区别
- 在对blob/text类型字段添加索引时必须要指定索引前缀长度M。(在对单列创建索引时必须要复制索引列的值到特定的数据结构如B+树中故而强制要求blob/text类型创建索引时指定索引前缀长度能够有效的减少复制索引值消耗的空间和比较索引的开销)
```sql
create table tb_blob_index (
blob_col blob,
index(blob_col(M))
);
```
- 对于blob类型和text类型的字段并不能为其指定default默认值
#### blob类型和text类型的排序
由于blob类型和text类型的值可能会很长故而在对blob类型和text类型的值进行排序时只会对列开头max_sort_length字节长度的内容进行排序。max_sort_length默认值为1024.
```sql
show variables like 'max_sort_length'; # default 1024
```
### enum类型
枚举类型是一个String对象该对象的值可以从允许的值范围中进行选取。允许的值范围在定义枚举字段时显式指定。
#### 枚举列的创建
```sql
create tb_enum (
id bigint auto_increment primary key,
size enum('x-small', 'small', 'medium', 'large', 'x-large')
);
```
当在插入枚举时可以有效降低空间的占用量。对于medium值的插入一百万条枚举类型值的插入只消耗一百万字节而将'medium类型作为字符串插入时一百万条数据的插入会消耗六百万字节的空间。
#### 枚举类型的值和序号
- mysql中对于每个枚举类型的值都有一个序号。对于在枚举类型列定义时在括号中指定的枚举类型值都对应了一个整数序号序号从1开始如"small","medium","large"对应123
- 对枚举空字符串代表error其对应的index是0.
- 对于枚举值NULL其index也为NULL
如果想要通过数值的形式获取枚举值可以通过select enum_col+0的形式获取枚举值时该枚举值对应的index被返回。
#### 枚举类型插入invalid值
如果对枚举类型插入invalid值插入值不位于enum定义时的可选值中
- strict mode没有开启时会插入一个''作为错误值,该''对应的index是0
- 若strict mode开启那么插入invalid值会直接导致异常
如果枚举列声明可为null那么null对于该枚举列则是有效值该枚举列的默认值为null如果枚举列声明为not null那么该枚举列的默认值是index为1对应的枚举值。
#### 枚举值的比较
枚举值的比较是通过比较枚举值的index来进行的。
```sql
create table tb_enum (enum_col enum('b','a'));
# 若enum_col_b对应的枚举值是b'enum_col_a对应的枚举值为enum_col_a
# 那么
enum_col_b < enum_col_a
```
#### 枚举值的定义
在定义枚举值时,不应该通过表达式来指定枚举值。
```sql
# 无法通过concat来指定枚举值为'medium'
CREATE TABLE sizes (
size ENUM('small', CONCAT('med','ium'), 'large')
);
# 无法将枚举值指定为变量
SET @mysize = 'medium';
CREATE TABLE sizes (
size ENUM('small', @mysize, 'large')
);
```