Compare commits
5 Commits
ebb148aaa5
...
5691fa3bef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5691fa3bef | ||
|
|
76dd1b3014 | ||
|
|
ef9dfbf96c | ||
|
|
835d8f9d72 | ||
| 0bfb27923b |
@@ -214,3 +214,218 @@ select current_timestamp(4);
|
|||||||
'2011-12-31 12:00:00'
|
'2011-12-31 12:00:00'
|
||||||
```
|
```
|
||||||
- 当time类型转化为date时,逻辑和上面一样,但是会舍弃得到datetime结果的time部分,即结果为'2012-01-01'、'2012-01-02'或'2011-12-31'
|
- 当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,215(2^24-1,约16MB)个字节的二进制数据,该类型会使用3字节的前缀来记录长度。
|
||||||
|
### mediumtext [CHARACTER SET charset_name] [COLLATE collation_name]
|
||||||
|
一个text列,最多可以存储16,777,215(2^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]
|
||||||
|
枚举类型,一个字段可以含有value1,value2,……中的一个值或者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个或多个值,每个值都必须属于value1,value2,……。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为0x610000,col_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"对应1,2,3)。
|
||||||
|
- 对枚举空字符串(代表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')
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user