SQLServer中VARCHAR(MAX)和NVARCHAR(MAX)使⽤时
要注意的问题(转载)
在Microsoft SQLServer2005及以上的版本中,对于varchar(n)、nvarchar(n)和varbinary(n)有了max的扩展。可以使⽤如:varchar(max)、nvarchar(max)和varbinary(max)的⼤值数据类型来存储最多2^30-1个字节的数据。
这⼏个数据类型在⾏为上和较⼩的数据类型 varchar、nvarchar 和 varbinary 相同。
微软的说法是⽤这个数据类型来代替之前的text、ntext 和 image 数据类型,它们之间的对应关系为:
varchar(max)-------text;
nvarchar(max)-----ntext;
varbinary(max)----image.
有了⼤值数据类型之后,在对⼤值数据操作的时候要⽐以前灵活的多了。⽐如:之前text是不能⽤‘like’的,有了varchar(max)之后就没有这些问题了,因为varchar(max)在⾏为上和varchar(n)上相同,所以,可以⽤在varchar的都可以⽤在varchar(max)上。
以varchar为例,varchar⽀持8000字符,Text⽀持2GB字符,但是,替换函数在编写出来的时候,就对TEXT数据类型不起作⽤。
Update TableName Set DocuMent=REPLACE(DocuMent,String1,String2) /*此⾏将报错*/
同样也对CHARINDEX或者SUBSTRING不起作⽤——或者⾄少是他们在超过8千个字符的情况下不起作⽤。更进⼀步地讲,如果开发⼈员忘了处理TEXT或者IMAGE类型的本地变量,则实际上不⽀持任何操作。即使是简单地更新⼀个⽂档中的⼀个⼦字符串都需要⽤到很多的东西,以及难以使⽤的类似READTEXT和WRITETEXT的函数。
SQL Server 2005引⼊了⼀系列新的被称为max的数据类型(或者说是参数类型)。这是varchar、nvarchar 和 varbinary类型的扩展,这⼏种类型以前被限制在8000字节以下。max可以容纳⾼达2GB的数据,与TEXT和IMAGE⼀样——并且完全兼容所有的SQL Server内置的字符串函数。
⽤max关键字定义⼀个某种max类型的变量与替代字符串的尺⼨(为varchar、nvarchar的时候)或者字节(为varbinary的时候)⼀样简单。DECLARE@BigString varchar(max)
SET@BigString='abc'
虽然这个变量可以⾃由地操纵,并且可以传递给任何的内置的字符串函数,兼容性仍然不是没有问题。
⾸先,开发⼈员不能期望指定了尺⼨的varchar和nvarchar变量在达到8000个字节的极限的时候可以⾃动“升级”到max版本。例如,如下的批处理:
DECLARE@String1varchar(4001)
DECLARE@String2varchar(4001)
SET@String1=REPLICATE('1', 4001)
SET@String2=REPLICATE('2', 4001)
SELECT LEN(@String1+@String2)
4001+4001=8002,但是指定了尺⼨的varchar(n)的极限是8000。因为这两个变量中没有⼀个是max类型,LEN函数的结果就是8000,不是8002。在将两个变量连接的时候,⼀种简单的修正⽅法就是声明这两个变量中的⼀个为varchar(max)或者将其中的⼀个变量进⾏转换。与⼀个规定了尺⼨的类型进⾏连接的时候,优先考虑max类型,最终结果是max类型。所以,以下批处理的结果是8002,正如我们期望的⼀样: DECLARE@String1varchar(4001)默认字符串是什么
DECLARE@String2varchar(4001)
SET@String1=REPLICATE('1', 4001)
SET@String2=REPLICATE('2', 4001)
SELECT LEN(CONVERT(varchar(max), @String1) +@String2)
在传递给字符串函数的时候,开发⼈员意识到字符串的原意在默认情况下是规定了尺⼨的,⽽不是max类型,也是⾄关重要的。例如,以下查询的结果就很令⼈惊奇:
SELECT LEN(REPLICATE('1', 8002))
因为字符串‘1’是被作为规定了尺⼨的varchar对待,⽽不是varchar(max),结果就是8000——但是在SQL Server 2005中,REPLICATE函数能够产⽣⾼达2GB的字符串。要修正这个问题,可以将字符串转换为varchar(max),这样函数就会输出同样的类型了:
SELECT LEN(REPLICATE(CONVERT(varchar(max), '1'), 8002))
这个查询现在将会返回期望的结果:8002。记住,总是要对采⽤了新特性编写的代码进⾏⾮常仔细的测试。隐藏的问题,例如上⾯描述的问题,可能并且毫⽆疑问地会在最坏的时间⾥造成灾难性的后果。
除了变量之外,max类型也可以⽤于定义表的字段:
CREATE TABLE BigStrings (BigString varchar(max))
当⽤于表的时候,意识到max类型具有与TEXT和IMAGE类型稍微不同的⾏溢出⾏为是⾮常重要的。在SQL Server中,最⼤的⾏尺⼨是8060字节。要超过这个限制,并且仍然管理每个都拥有⾼达2GB的存储,⽤TEXT和IMAGE类型存储的数据会被存储引擎⾃动地断⾏,在⾏⾥只留下⼀个16字节的指针。这意味着⾏的尺⼨是减少了,这对性能有好处。然⽽,检索⼤数据是昂贵的,因为它不是与同⼀⾏的数据存放在同
⼀个位置。
max数据类型在默认情况下,使⽤TEXT/IMAGE溢出⾏为和正常尺⼨的varchar/varbinary类型的⾏为的混合⽅式。如果⼀个字段的数据,加上表中所有其他字段的数据,总量少于8060字节,数据就存放在⾏内。如果数据超过8060字节,max字段的数据就会存放在⾏外。对于⼤字符串的表,以下的⾏将会与表中的其他数据存储在同⼀个数据页内:
INSERT BigStrings (BigString) VALUES (REPLICATE('1', 8000))
--But the following row will result in an overflow:
INSERT BigStrings (BigString) VALUES (REPLICATE(CONVERT(varchar(max), '1'), 100000))
你可以更改max数据类型在每个表的基础上的默认的⾏为,它们会表现得和TEXT和IMAGE类型⼀样。这是通过使⽤sp_tableoption 存储过程中的“⼤数值类型在⾏外”选项实现的。为了修改⼤字符串表以将max类型的处理⽅式变得与TEXT和IMAGE数据类型的处理⽅式相同,可以使⽤如下的T-SQL:
EXEC sp_tableoption
  'BigStrings', 
  'large value types out of row',
  '1'
扩展:
既然是以max有这么多灵活性,⼀些数据库设计师将会被引诱以下列的⽅式开始定义表:
CREATE TABLE Addresses(
  Name varchar(max),
  AddressLine1 varchar(max),
  AddressLine2 varchar(max),
  City varchar(max),
  State varchar(max),
  PostalCode varchar(max)
  )
我建议你最好不要这样做,⼀个企业应⽤中的数据模型既应该包含有具有实际限制的字段,还要给程序设计师提供有关字段尺⼨的指导⽂档。像这样的表⼜该创建什么样的⽂档呢?
总知,max标记的数据类型为SQL Server 2005及之后版本处理⼤数据增加了很⼤部分的灵活性,但在使⽤中需要⾃⼰根据需求选择字段类型。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。