SQL Server-数据类型(七)

前言

前面几篇文章咱们讲解了索引有关知识,这一节咱们再继续咱们下面内容讲解,简短的内容,深刻的理解,Always to review the basics。函数

数据类型

SQL Server支持两种字符数据类型,一种是常规,另一种则是Unicode。常规数据类型包括CHAR和VARCHAR,Unicode数据类型包括NCAHR和NVARCHAR。常规字符的每一个字符使用1个字节存储,而Unicode数据的每一个字符要求2个字节。常规字符列限制为仅仅只针对于英语,而Unicode则是针对于多种语言。两种字符数据类型的文本表示方式也不相同,在表示常规字符文本时,只须要使用单引号,好比'Hello,my name is JeffckyWang,I'm from cnblogs',而对于Unicode字符文本时,须要指定字符N做为前缀,即N‘Hello,my name is JeffckyWang,I'm from cnblogs’。测试

名称中没有VAR元素的任何数据类型(CHAR、NCHAR)具备固定长度,即SQL Server按照列定义大小保留行空间,而不是按照字符中的实际字符保留空间。好比某列定义大小为CHAR(25),则SQL Server在该行保留25个字符的空间,而无论存储字符串的长度。spa

名称中含有VAR元素的数据类型(VARCHAR、NVARCHAR)具备可变长度,即SQL Server根据存储须要,在行中使用尽量多的存储空间存储字符串,同时外加两个额外的字节偏移数据。例如,若是将某列定义为VARCHAR(25),此时支持的最大字符数为25,但实际上按照字符串中实际字符肯定存储量。-摘抄自SQL Server 2012 T-SQL基础教程。code

这里关于Unicode字符数据类型咱们须要重点理解下。咱们先建立一个表,以下:blog

CREATE TABLE UnicodeType
(
 firstname VARCHAR(5) NOT NULL,
 lastname NVARCHAR(5) NOT NULL
);

此时咱们手动插入数据,正常插入,以下:教程

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '11111', -- firstname - varchar(5)
          N'啊的发个好'  -- lastname - nvarchar(5)
          )

字符都彻底插入表中,以下:索引

此时咱们将firstname,插入五个中文试试以下:字符串

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '达获得让人', -- firstname - varchar(5)
          N'达获得让人'  -- lastname - nvarchar(5)
          )

此时出现以下结果:博客

也就是说在常规字符类型如上述VARVHAR中定义为五个字符,此时咱们插入五个中文字符则会被截取,固然也插入不进去。由于上述已经明确讲了1个非英语字符串至关于两个字节,此时中文所占用的是十个字节,而此时VARCHAR才五个字符,因此出现警告。咱们再来将firstname插入两个中文两个英文或者数字看看it

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '达得1', -- firstname - varchar(5)
          N'达获得让人'  -- lastname - nvarchar(5)
          )

此时插入进去为出现警告,由于此时两个中文字符即四个字节加上一个数字字节恰好五个字节,因此能正常插入,咱们再来看看lastname,由上知,既然英文或者数字被当作一个字节,那么咱们对lastname插入四个中文字符和两个英文字节恰好十个字节应该是好使的。咱们看看:

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '达得1', -- firstname - varchar(5)
          N'达获得让ab'  -- lastname - nvarchar(5)
          )

oh,shit,此时竟然出错了,以下:

咱们上述分析的不是有理有据么,难道这里英文不是占用一个字节么,咱们插入一个英文试试。

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '达得1', -- firstname - varchar(5)
          N'达获得让b'  -- lastname - nvarchar(5)
          )

结果正确了,实践是检验真理的惟一标准,从这里咱们能够看出:在常规字符中,一个中文会当作是两个字节来使用,一个英文会当作是一个字节使用,可是在Unicode中,一个中文会当作两个字节来使用,可是一个英文也会当作是两个字节来使用。至此咱们能够得出结论,我的一直觉得在Unicode中,将英文是做为一个字节存储,见识短啊。

常规字符和Unicode中一个中文字符用两个字节存储,而对英文,常规字符用一个字节存储,而Unicode依然是用两个字节存储。

字符串函数

对字符串操做的函数有SUBSTRING、LEFT、RIGHT、CHARINDEX、PATINDEX、REPLACE、REPICATE、STUFF、UPPER、LOWER、RTRIM、LTRIM、FORMAT。对于简单的函数咱们略过,下面咱们来说讲几个须要注意的地方。

LEN与DATALENGTH比较

咱们首先建立以下测试表

CREATE TABLE StringFun
(
    firststr VARCHAR(max) NOT NULL,
    secondstr TEXT NOT NULL
);

咱们插入测试数据

INSERT dbo.StringFun
        ( firststr, secondstr )
VALUES  ( '我是JeffckyWang,我来自于博客园,专一于.NET技术', -- firststr - varchar(max)
          '我是JeffckyWang,我来自于博客园,专一于.NET技术'  -- secondstr - text
          )

咱们首先利用LEN函数来返回firststr和secondstr的字符串长度大小

SELECT LEN(firststr) AS VARCAHRFieldSize 
FROM dbo.StringFun

SELECT LEN(secondstr) AS TEXTFieldSize 
FROM dbo.StringFun

好极了,出错了。LEN函数没法对TEXT进行操做。咱们接着往下看。

SELECT DATALENGTH(firststr) AS VARCAHRFieldSize 
FROM dbo.StringFun

SELECT DATALENGTH(secondstr) AS TEXTFieldSize 
FROM dbo.StringFun

此时未报错误,结果显示为47个字节大小。 既然LEN对文本无效,咱们不对文本操做就是。

SELECT LEN(firststr) AS VARCAHRFieldSize 
FROM dbo.StringFun

SELECT DATALENGTH(secondstr) AS TEXTFieldSize 
FROM dbo.StringFun

此时类型为VARCAHR的firststr字节大小却为31,为什么,看到这里咱们想必恍然大悟,在上述咱们讲到常规字符会对中文以一个字符两个字节大小存储,可是这里实际上返回的是实际字符大小,固然一个是存储,一个是检索,仍是有点不一样,同时咱们也不会将中文存储到VARCHAR中。到这里咱们能够得出结论。

结论:DATALENGTH函数是针对于TEXT,而LEN是针对于VARCHAR,对TEXT无效会报错。

到这里咱们还有一个特殊值未进行处理,那就是NULL。那么问题来了,LEN和DATALENGTH对NULL,它的长度大小是多少呢,是0仍是不是0尼?

是咱们来测试下:

DECLARE @MyVar VARCHAR(10)
SET @MyVar = NULL
IF (LEN(@MyVar) = 0)
PRINT 'LEN of NULL is 0'
ELSE
PRINT 'LEN of NULL is NULL'

咱们上述获得的结果是LEN of NULL is NULL,DATALENGTH就再也不演示了。

结论:LEN和DATALENGTH对于NULL计算的结果就是NULL。

咱们再来看看两者差别的一个小地方:

SELECT LEN('JeffckyWang  ') AS 'LEN'
SELECT DATALENGTH('JeffckyWang   ') AS 'DATALENGTH'

结论:LEN会删除尾随空格,而DATALENGTH不会

CHARINDEX与PATINDEX比较

CHARINDEX和PATINDEX字符串函数都是查询返回指定匹配字符串的开始位置。

咱们先查询一个字符串,此字符串在表中存在,以下:

USE AdventureWorks2012;
GO
SELECT CHARINDEX('Worn', DocumentSummary) AS 'CHARINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;
GO

SELECT PATINDEX('Worn', DocumentSummary) AS 'PATINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;

为什么CHARINDEX函数查找到了,而PATINDEX没有查询到呢?此时就说说两者的区别,两者都有两个参数,第二个参数都是要匹配的字符串,可是PATINDEX函数必须在须要匹配的字符串以前或者以后添加百分号即通配符,而CHARINDEX函数则不须要。以下便可:

USE AdventureWorks2012;
GO
SELECT CHARINDEX('Worn', DocumentSummary) AS 'CHARINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;
GO

SELECT PATINDEX('%Worn%', DocumentSummary) AS 'PATINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;

结论:PATINDEX匹配字符串必须在字符串前面或者后面或者先后添加通配符,而CHARINDEX无需添加。

总结

本节咱们主要讲解了SQL中的数据类型以及几个须要注意的地方,简短的内容,深刻的理解,咱们下节再会。

相关文章
相关标签/搜索