详解SQL Server中的数据类型_MsSql

前言

前面几篇文章我们讲解了索引有关知识,这一节我们再继续我们下面内容讲解,简短的内容,深入的理解。

数据类型

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个字符的空间,而不管存储字符串的长度。

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

这里关于Unicode字符数据类型我们需要重点理解下。我们先创建一个表,如下:

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插入两个中文两个英文或者数字看看

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中的数据类型以及几个需要注意的地方,简短的内容,深入的理解,我们下节再会。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,同时也希望多多支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索sql
, server
数据类型
mssql和sqlserver、没有sql mssqlserver、mssql sqlserver、sql server mssql、sqlservermssqluser,以便于您获取更多的相关知识。

时间: 2024-10-06 10:47:24

详解SQL Server中的数据类型_MsSql的相关文章

详解SQL Server中的数据类型

前言 前面几篇文章我们讲解了索引有关知识,这一节我们再继续我们下面内容讲解,简短的内容,深入的理解. 数据类型 SQL Server支持两种字符数据类型,一种是常规,另外一种则是Unicode.常规数据类型包括CHAR和VARCHAR,Unicode数据类型包括NCAHR和NVARCHAR.常规字符的每个字符使用1个字节存储,而Unicode数据的每个字符要求2个字节.常规字符列限制为仅仅只针对于英语,而Unicode则是针对于多种语言.两种字符数据类型的文本表示方式也不相同,在表示常规字符文本

详解SQL Server数据库状态和文件状态

数据库状态 (database states) 查询数据库的当前状态 : 1.查询所有数据库的状态 ,通过sys.databases目录视图的state_desc列 user master go select state_desc ,[name] from sys.databases go 2.查询指定数据库的状态,通过DATABASEPROPERTYEX函数的Status属性 select DATABASEPROPERTYEX('demoData','status') go 状态: ONLIN

详解SQL Server数据库架构和对象、定义数据完整性_MsSql

前言 本节我们继续SQL之旅,本节我们如题来讲讲一些基本知识以及需要注意的地方,若有不妥之处,还望指出,简短的内容,深入的理解. 数据库架构和对象 数据库包含架构,而架构又包含对象,架构可以看做是表.视图.存储过程等对象的容器.架构是一个命名空间,它被用做对象名称的前缀,比如在Cnblogs的架构中有一个名称为Blogs的表,此时我们用架构式限定式名称(即两部分式对象名称)所以Blogs表示为Cnblogs.Blogs.如果我们引用对象时省略了架构名称,SQL Server将会检查对象是否存在用

详解SQL Server的差异备份还原

在SQL Server中还原差异备份,需要先还原在差异备份时间点之前的一个完整备份,在还原完整备份时要加上NORECOVERY参数,示例SQL语句如下: RESTORE DATABASE [数据库名称] FROM DISK = N'完整备份文件路径' WITH FILE = 1, NOUNLOAD, STATS = 10, NORECOVERY GO 在Management Studio中对应的选项是: Leave the database non-operational, and do not

详解SQL Server OS的任务调度机制

简介 SQL Server OS是在Windows之上,用于服务SQL Server的一个用户级别的操作系统层次.它将操作系统部分的功能从整个SQL Server引擎中抽象出来,单独形成一层,以便为存储引擎提供服务.SQL Server OS主要提供了任务调度.内存分配.死锁检测.资源检测.锁管理.Buffer Pool管理等多种功能.本篇文章主要是谈一谈SQL OS中所提供的任务调度机制. 抢占式(Preemptive)调度与非抢占式(non-Preemptive)调度 数据库层面的任务调度的

详解SQL Server数据库索引

一.理解索引的结构 索引在数据库中的作用类似于目录在书籍中的作用,用来提高查找信息的速度.使用索引查找数据,无需对整表进行扫描,可以快速找到所需数据.微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclustered index,也称非聚类索引.非簇集索引). SQL Server 中数据存储的基本单位是页(Page).数据库中的数据文件(.mdf 或 .ndf)分配的磁盘空间可以从逻辑上划分成页(从 0 到 n 连

SQL Server误区30日谈 第5天 AWE在64位SQL SERVER中必须开启_MsSql

误区 #5: AWE在64位SQL SERVER中必须开启 错误!     在坊间流传的有关AWE的设置的各种版本让人非常困惑.比如说如何设置起作用,如何设置不起作用,在32位和64位上是否需要AWE等.   好吧,我来概括一下:     在64位系统(SQL SERVER 2005+版本) AWE是不需要的(即使是ON状态,也毫无影响) 开启"锁定内存页"使得缓冲池中的内存页不会被置换到虚拟内存中(实际上所有的Single Page Allocator分配和Stolen的内存都不会被

详解SQL死锁检测的方法_MsSql

sql server中的死锁是指进程之间互相永久阻塞的状态,下文就将为您介绍如何检测sql server死锁,希望对您有所帮助. 死锁(deadlock)指进程之间互相永久阻塞的状态,SQL可以检测到死锁,并选择终止其中一个事务以干预sql server死锁状态. 第一步:首先创建两个测试表,表goods_sort和goods 表goods_sort:创建并写入测试数据 IF EXISTS(SELECT name FROM sysobjects WHERE name='goods_sort' A

详解SQL Server数据库架构和对象、定义数据完整性

前言 本节我们继续SQL之旅,本节我们如题来讲讲一些基本知识以及需要注意的地方,若有不妥之处,还望指出,简短的内容,深入的理解. 数据库架构和对象 数据库包含架构,而架构又包含对象,架构可以看做是表.视图.存储过程等对象的容器.架构是一个命名空间,它被用做对象名称的前缀,比如在Cnblogs的架构中有一个名称为Blogs的表,此时我们用架构式限定式名称(即两部分式对象名称)所以Blogs表示为Cnblogs.Blogs.如果我们引用对象时省略了架构名称,SQL Server将会检查对象是否存在用