谈谈char ,nchar,varchar,nvarchar 和Uniqueidentifier
在SQL server数据库中这几个类型应该是比较常用的,这篇文章主要也是和大家一起讨论下这几个类型。
先重点看前面4个:char ,nchar,varchar,nvarchar
Msdn解释如下:
固定长度或可变长度的字符数据类型。
char [ ( n ) ]
固定长度,非 Unicode 字符数据,长度为 n 个字节。n 的取值范围为 1 至 8,000,存储大小是 n 个字节。char 的 ISO 同义词为 character。
varchar [ ( n | max ) ]
可变长度,非 Unicode 字符数据。n 的取值范围为 1 至 8,000。max 指示最大存储大小是 2^31-1 个字节。存储大小是输入数据的实际长度加 2 个字节。所输入数据的长度可以为 0 个字符。varchar 的 ISO 同义词为 char varying 或 character varying。
字符数据类型(nchar 长度固定,nvarchar 长度可变)和 Unicode 数据使用 UNICODE UCS-2 字符集。
nchar [ ( n ) ]
n 个字符的固定长度的 Unicode 字符数据。n 值必须在 1 到 4,000 之间(含)。存储大小为两倍 n 字节。nchar 的 ISO 同义词为 national char 和 national character。
nvarchar [ ( n | max ) ]
可变长度 Unicode 字符数据。n 值在 1 到 4,000 之间(含)。max 指示最大存储大小为 2^31-1 字节。存储大小是所输入字符个数的两倍 + 2 个字节。所输入数据的长度可以为 0 个字符。nvarchar 的 ISO 同义词为 national char varying 和 national character varying。
var->vary(变化),所以带有var 的类型都是可变长度的。
n->national(国际化),因为UTF8不足够表示中文,韩文,日文,所以为了支持国际化,有了Unicode的编码,所以以n开头的字段代表着这个类型是unicode编码。
实例演示:
创建表:
CREATE TABLE [dbo].[TestTable](
[char_Col] [char](5) NULL,
[nchar_Col] [nchar](5) NULL,
[nvarchar_Col] [nvarchar](5) NULL,
[varchar_Col] [varchar](5) NULL,
) ON [PRIMARY]
上面的n都是5,代表长度是5.
接着插入一行数据:
insert into TestTable select '1','1','1','1'
如果查看表可以看到:
仔细的数一数可以发现后面是4个空格,nchar_Col也是4个空格。这点说明对于定长类型char,nchar如果长度不足的话,在后面补充空格。
因为带有var,所以长度变了,后面不会有空格。
结论:使用长度固定的类型的时候,可能要做Trim操作,当然也可以选择RTrim,因为是在后面补充空格的。
2:执行下面的Sql语句:
insert into TestTable(char_Col,nchar_Col,nvarchar_Col,varchar_Col)
values('王王王王王','王王王王王','王王王王王','王王王王王')
结果如下:
char和varchar的长度是5,但是它们存储的是非Unicode字符,采用一个字节的形式来存储数据。
Nchar 和nvarchar 的长度也是5,但是存储的是Unicode字符,采用两个字节来存储数据,也就是是说对于任何字符,都采用两个字节来存储,不管是数字还是字母,或者是英文,总之任何字符都采用两个字节来储存。
在上面的例子中,”王”是中文,所有的中文都用两个字节表示,
所以上面的Sql语句就代表 select 10个字节,10个字节,10个字节,10个字节。
我们的表定义设置了所以的n为5,这里n是类型(n) 中的n。
char(5):存储5个字节,对于10个字节来说需要截断。
nchar(5):存储的是5*2个字节,对于10个字节来说,合适
varchar(5) :存储5个字节,对于10个字节来说需要截断。
nvarchar(5):存储的是5*2个字节,对于10个字节来说,合适
为了验证:执行下面的sql语句
insert into TestTable(char_Col,nchar_Col,nvarchar_Col,varchar_Col)
values('王王a','12345','王王王王王','12345')
结果:
一个中文2个字符,所以’王王a’ 一共5个字符。
修改代码为:
insert into TestTable(char_Col,nchar_Col,nvarchar_Col,varchar_Col)
values('王王a','123456','王王王王王','12345')
和上面的不同是将nchar_Col加了个6.
结果:
为什么?
nchar是存储Unicode字符的,所以不管任何字符,都采用两个字节来存储。”123456” 的长度是6,所以需要的字节是6*2=12个字节,对于nchar(5) 只能存储10个字节来说”123456” 会被截断。
这里就是要注意对于nchar,nvarchar 来说,这两个数据类型是用来存储Unicode的,所以任何字符都采用两个字节来存储,也就是nchar(n),nvarchar(n) 中的n代表的就是字符串的长度。
N=5,所以可以存储”12345”,’王王王王5”,” 王王王王王”,” 王ade1”,这些字符串的长度都是5
但是对于char(n),varchar(n) 来说,n代表的是字节。
例如
N=5,所以可以存储”12345”,”王王a”,”ab王d”.一个汉字两个字节,这些字符串的字节全部都是5
关于何时使用char,varchar,nchar,nvarchar,msdn给了一部分建议:
· 如果列数据项的大小一致,则使用 char。
· 如果列数据项的大小差异相当大,则使用 varchar。
· 如果列数据项大小相差很大,而且大小可能超过 8,000 字节,请使用 varchar(max)。
· 如果需要支持Unicode,使用nchar,nvarchar
在早期的Sql Server 版本中,如果要存储大量的字符串,可以采用ntext,text,image 数据类型,不过微软建议:
Uniqueidentifier:16字节GUID
如果应用程序要使用guid来作为表的id的话,你会选择什么数据类型?
char(36) ,nchar(36), varchar(36), nvarchar(36) 还是uniqueidentifier
假设guid为xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,长度是36.
很明显,你不会选择nchar(36),nvarchar(36).因为guid不会有中文,而且nchar(36),nvarchar(36)代表着72个字节。
其次你应该不会选择varchar(36),因为一个guid不做处理的话,长度是固定的。
剩下来就是char(36) 和uniqueidentifier之争了
Uniqueidentifier需要16字节GUID,char(36) 需要36个字节,你会选择什么数据类型?
为什么Uniqueidentifier 16个字节就可以存储guid?
msdn 解释:
通过从 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 形式的字符串常量进行转换,其中,每个 x 都是 0-9 或 a-f 范围内的十六进制数字。例如,6F9619FF-8B86-D011-B42D-00C04FC964FF 为有效的 uniqueidentifier 值。