SQL中的数字、字母和汉字
知识点001
当变量的数据类型为VARCHAR时,变量赋值后,变量中的字符所占字节数,数字和字母是1个bytes,汉字是2个bytes;
当变量的数据类型为NVARCHAR时,变量赋值后,变量中的字符所占字节数,数字、字母和汉字,均为2个bytes。
原因:NVARCHAR采用的字符集是unicode,unicode字符集中,无论是数字、字母、汉字,每个字符用2个bytes表示;
VARCHAR采用的字符集为非unicode,数字和字母用1个byte表示,汉字用2个bytes表示。
学会了这点,就可以很好的去解答这个问题:SQL字符串长度计算。
知识点002
假定变量的数据类型是VARCHAR(N) ,含义是它能存储的变量空间长度是N个bytes(注意,不是bit)
Sample:
DECLARE @name VARCHAR(10),
指变量@name的空间长度是10个字节。
我们知道,一个汉字占2个bytes,假如我们设计一个驾校管理系统,设计数据库的时候,将数据表字段name的数据类型设为VARCHAR(10)
10个字节,最多只能保存5个汉字,如果系统需要保存的人名长度大于5个汉字(比如俄罗斯总统普京,全名【弗拉基米尔·弗拉基米罗维奇·普京】,14个汉字,2个·字符),数据库就会截取变量值,只保存10个字节的内容,即【弗拉基米尔】,导致信息缺失。但是如果将name的数据类型声明为VARHCAR(32),问题就解决了。
PS:【弗拉基米尔·弗拉基米罗维奇·普京】汉字中间这个·(点号)
如果用搜狗输入法的符号大全中的“标点符号”栏下的点号·,则占2个字节存储空间,上文普京全名中的点号,即为这个。
如果用搜狗输入法的符号大全中的“特殊符号”栏下的点号▪,则占1个字节存储空间。
SQL验证:
DECLARE @name1 VARCHAR(10) DECLARE @name2 VARCHAR(32) SET @name1 = '弗拉基米尔·弗拉基米罗维奇·普京' SET @name2 = '弗拉基米尔·弗拉基米罗维奇·普京' SELECT @name1 AS name1,@name2 AS name2
执行结果:
值得注意的是,下面这个数据类型的空间长度问题。
假定变量的数据类型为NVARCHAR(N),含义是它能存储的变量空间长度是(2*N)个bytes.
综上,统一概念描述为:
1.SQL中,当声明一个变量的数据类型是VARCHAR(N)时,含义是:该变量可以存储空间长度为N个字节(bytes)的数据;
2.SQL中,当声明一个变量的数据类型是NVARCHAR(N)时,含义是:该变量可以容纳空间长度为2*N个字节(bytes)的数据;因该数据类型保存的数据每个字符(无论是字母、数字还是汉字)均占2个字节,所以,声明一个变量的数据类型是NVARCHAR(N)时,根据这个声明,我们可以知道,该变量可以容纳字符长度为N个字符(characters)的数据。而当你声明一个变量数据类型是VARCHAR(N)时,你就无法根据这个声明,来计算出该变量可以容纳的数据的字符长度是多少,因为该变量保存的字母、数字和汉字,所占的空间长度不都是2个字节,而是字母1个字节,数字1个字节,汉字2个字节。
即,对声明为NVARCHAR(N)类型的变量来说,你既可以知道该变量可以容纳的数据的空间长度,也可以知道该变量的字符长度;
而对声明为VARCHAR(N)类型的变量来说,你只能知道该变量可以容纳的数据的空间长度,无法知道该变量的字符长度。
SQL代码验证。PS:SQL server 版本:Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (X64)
SQL版本查询语句:select @@VERSIONS
1 --汉字 2 CREATE TABLE dbo.Test1 (c1 NVARCHAR(4)); 3 INSERT dbo.Test1 VALUES ('美人她爹'); 4 SELECT DATALENGTH(c1) AS Bytes_of_Column_C1 FROM dbo.Test1; 5 6 CREATE TABLE dbo.Test2 (c2 VARCHAR(8)); 7 INSERT dbo.Test2 VALUES ('美人她爹'); 8 SELECT DATALENGTH(c2) AS Bytes_of_Column_C2 FROM dbo.Test2;
执行结果:
1 --数字 2 CREATE TABLE dbo.Test3 (c3 NVARCHAR(4)); 3 INSERT dbo.Test3 VALUES ('1234'); 4 SELECT DATALENGTH(c3) AS Bytes_of_Column_C3 FROM dbo.Test3; 5 6 CREATE TABLE dbo.Test4 (c4 VARCHAR(8)); 7 INSERT dbo.Test4 VALUES ('12345678'); 8 SELECT DATALENGTH(c4) AS Bytes_of_Column_C4 FROM dbo.Test4;
执行结果:
1 --字母 2 CREATE TABLE dbo.Test5 (c5 NVARCHAR(4)); 3 INSERT dbo.Test5 VALUES ('abcd'); 4 SELECT DATALENGTH(c5) AS Bytes_of_Column_C5 FROM dbo.Test5; 5 6 CREATE TABLE dbo.Test6 (c6 VARCHAR(8)); 7 INSERT dbo.Test6 VALUES ('abcdefgh'); 8 SELECT DATALENGTH(c6) AS Bytes_of_Column_C6 FROM dbo.Test6;
执行结果:
知识点003
上文提到两个笔者自定义的概念,空间长度和字符长度。借用这两个概念,说一下SQL中两个函数 LEN()和DATALENGTH()的区别。
区别1
LEN()函数返回值是字符串的字符数目(the number of characters of the specified string expression),即字符串的字符长度。
DATALENGTH()函数的返回值是字符串的字符所占空间,即字符串的空间长度。
区别2
LEN()函数计算字符串的字符长度时,不计算(包含)字符串末尾空格(trailing spaces);
DATALENGTH()函数计算字符串的空间长度时,计算(包含)字符串末尾空格。
上述两点区别,SQL验证如下:
1 DECLARE @sql_string_VARCHAR VARCHAR(100) 2 DECLARE @sql_string_NVARCHAR NVARCHAR(100) 3 4 SET @sql_string_VARCHAR = 'ab c ' 5 SET @sql_string_NVARCHAR = 'ab c ' 6 7 SELECT LEN(@sql_string_VARCHAR) AS characters_of_sql_string_varchar, 8 LEN(@sql_string_NVARCHAR) AS characters_of_sql_string_nvarchar 9 SELECT DATALENGTH(@sql_string_VARCHAR) AS Bytes_of_sql_string_varchar, 10 DATALENGTH(@sql_string_NVARCHAR) AS Bytes_of_sql_string_nvarchar
执行结果: