日期:2013-04-08 浏览次数:20486 次
事情开始得很简单。MegaWare公司市场部门想要一个新的网站来发布文档,开发团队觉得使用SQL Server 2000数据库作为文档存储仓库会使事情变得简单。Steve是MegaWare的数据库管理员,没有看出这有什么大问题;在数据库中存储文档,而不是使用文件系统,意味着服务器需求多做一些任务,但是它也会使得备份和管理容易得多。数据库与文件系统变得不同步也应该是不可能的。 市场部门想要存储的许多文档都超过了8000个字节,那么很明显VARCHAR不是适合这项任务的数据类型。作为替代,TEXT数据类型被用来定义存放数据的字段。由于每个TEXT都能容纳2GB的内容,TEXT要存放市场部门的同事们扔进数据库的最大的文件也是没有问题的。 数月过去了,市场用大量的无聊拷贝填满了整个数据库。但是这还不是Steve真正关怀的问题。数据库愉快地嗡嗡作响地运转着,每团体对项目的结果都很满意。 直到公司的标语改变的那个严重的日子。市场部的团队认为“MegaWare: It’s really cool!”要比原来的“It’s MegaWare’s Way or the Highway!” 听起来更好。由于市场部团队曾经将原来的标语嵌入了仓库中每个文档的页脚上,如今Steve的任务就是更改所有这些文档的页脚。 “没有问题,” Steve想,打开SQL Server 查询分析器工具,执行了如下的T-SQL批处理: UPDATE MarketingDocuments SET Document = REPLACE(Document, ’It’’s MegaWare’’s Way or the Highway!’, ’MegaWare: It’’s really cool!) 当他看到出现的错误音讯的时候,Steve的轻松的浅笑很快消逝了,“替换函数的参数1,text数据类型无效。” 替换函数在编写出来的时候,就对TEXT数据类型不起作用。同样也对CHARINDEX或者SUBSTRING不起作用——或者至少是他们在超过8千个字符的情况下不起作用。更进一步地讲,开发人员忘了处理TEXT或者IMAGE类型的本地变量;实际上不支持任何操作。即便是简单地更新一个文档中的一个子字符串都需求用到晦涩的东西,以及难以使用的类似READTEXT和WRITETEXT的函数。而不是开发人员或者忙碌的数据库管理员由于想要弄清如何正确使用而采用了不同类型的函数耗费了时间。 SQL Server的开发人员很侥幸,他们将会拨开乌云见蓝天。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和VARBINARY变量在达到8000个字节的极限的时候可以自动“升级”到MAX版本。例如,如下的批处理: DECLARE @String1 VARCHAR(4001) DECLARE @String2 VARCHAR(4001) SET @String1 = REPLICATE(’1’, 4001) SET @String2 = REPLICATE(’2’, 4001) SELECT LEN(@String1 + @String2) 4001+4001=8002,但是指定了尺寸的VARCHAR的极限是8000。由于这两个变量中没有一个是MAX类型,LEN函数的结果就是8000,不是8002。在将两个变量连接的时候,一种简单的修正方法就是声明这两个变量中的一个为VARCHAR(MAX)或者将其中的一个变量进行转换。与一个规定了尺寸的类型进行连接的时候,优先考虑MAX类型,最终结果是MAX类型。所以,以下批处理的结果是8002,正如我们期望的一样: DECLARE @String1 VARCHAR(4001) DECLARE @String2 VARCHAR(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)
免责声明: 本文仅代表作者个人观点,与爱易网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
|