MSSQL Server
char vs varchar vs nvarchar
MSSQL Server char(n) vs varchar(n) n为字节单位而非字符单位,这是有区别的,在单字节编码字符集存储时,n的大小即为字符长度,当所存储的字符无法使用单字节编码字符集表示时则会采用双字节字符集存储,n的大小则是字符的2倍char会存储固定字节长度的字符,如果定义char(4)则插入'ab'会被存储为'ab ',超出字节长度的字符串会被截断。实际存储大小总是4 bytes,另外插入'ab '后查询出的结果是会去除末尾空格为'ab'varchar存储可变字节长度的字符,如果定义varchar(4)则插入'ab'即存储为'ab'而不会向char一样使用空格填充,在检索时也不会去除末尾空格。然而使用varchar(n)存储的字符总是会比真实大小大2 bytes,因为varchar类型总是会使用2 bytes来存储字节长度,2 bytes最大可表示65535个字节长度,而varchar(n)最大为1~8000 bytes,所以2 bytes足够存储最大字节长度
插入值
char(4)
实际存储大小
varchar(4)
实际存储大小
''
' '
4 bytes
''
0+2 bytes
'ab'
'ab '
4 bytes
'ab'
2+2 bytes
'abcd'
'abcd'
4 bytes
'abcd'
4+2 bytes
'abcdefg'
'abcd'
4 bytes
'abcd'
4+2 bytes
[var]char(n) vs n[var]char(n) 很多人或许会对char/nchar和varchar/nvarchar之间的区别感到困惑,这不过是不同的编码方式带来的差异 带有n前缀的表示使用Unicode标准以及UTF-16 编码方式(适用于开启了补充字符(SC)的排序规的情况下,如果未开启,则使用UCS-2 编码方式),前者规定了每个字符对应的代码点(Code Point)是多少,后者表示如何对Unicode定义的代码点进行编码,由于UTF-16在BMP 区域使用2 bytes进行编码,超出BMP区域的则使用4 bytes编码,所以nvarchar实际存储大小需要根据具体的值来确定,例如存储'a'则占用大小为2 bytes,存储一个emoji表情则可能占用4 bytes 对于[var]char,则使用对应排序规则的代码页进行编码,这意味着不同区域无法通用存储的编码字符。不过从SQL Server 2019(15.x)开始,如果开启了UTF-8排序规则,则使用UTF-8进行编码,与UTF-16一样能够表示Unicode标准所定义的字符集。UTF-8对于字符的编码长度也是可变的,例如ASCII码表所定义的字符则只需要1 byte,对于一个非BMP区域的字符则可能需要最大4 bytes进行编码 下表所示的varchar使用UTF-8排序规则
插入值
varchar(50)
实际存储大小
nvarchar(50)
实际存储大小
''
''
0+2 bytes
''
0+2 bytes
'a'
'a'
1+2 bytes
'a'
2+2 bytes
'abcd'
'abcd'
4+2 bytes
'abcd'
8+2 bytes
'😀'
'😀'
4+2 bytes
'😀'
4+2 bytes
MySQL char(n) vs varchar(n) 相比较MSSQL Server,MySQL中的n则很好理解:无论采用哪种编码方式,它始终表示字符串的长度。在MySQL中,varchar类型也有一个长度值,然而与MSSQL Server所不同的是,它的存储长度值并不总是2 bytes,而是存储字节超过255 bytes时才使用两个字节存储
插入值
char(4)
实际存储大小
varchar(4)
实际存储大小
''
' '
4 bytes
''
0+1 bytes
'ab'
'ab '
4 bytes
'ab'
2+1 bytes
'abcd'
'abcd'
4 bytes
'abcd'
4+1 bytes
'abcdefg'
'abcd'
4 bytes
'abcd'
4+1 bytes
Reference