T-SQL 2008中的REPLACE功能与T-SQL 2005不同

时间:2011-08-08 16:43:58

标签: sql sql-server tsql replace

我正在将数据库从SQL Server 2005迁移到2008年。

在测试期间,我发现一个不一致。根据BOL http://msdn.microsoft.com/en-us/library/ms186862(v=SQL.100).aspx(2008)和http://msdn.microsoft.com/en-us/library/ms186862(v=SQL.90).aspx(2005)返回varchar。到目前为止两者都是一样的。但是,如果我们传递给REPLACE函数列类型char,则会出现差异。看看这段代码

declare @test table
(
  testcharstring char(25)
) 

insert into @test
  select 'Hello'
  union
  select 'World'
  union
  select 'Hello world '

select 
  '"'+testcharstring+'"' as original
  ,'"'+replace(testcharstring,'a','A')+'"' as afterreplace
  --,'"'+replace(rtrim(testcharstring),'a','A')+'"'
from @test

SQL Server 2005的结果

original                    afterreplace
--------------------------- ---------------------------
"Hello                    " "Hello"
"Hello world              " "Hello world"
"World                    " "World"

SQL Server 2008的结果

original                    afterreplace
--------------------------- ---------------------------
"Hello                    " "Hello                    "
"Hello world              " "Hello world              "
"World                    " "World                    "

SQL Server 2005中的T-SQL甚至删除了合法的尾随空格,而不是说它char(25)威胁为varchar(25)。 SQL Server 2008中的T-SQL更仔细地处理类型,并根据它收到的用于转换的类型返回结果

我在不同的T-SQL对象中有数字位置,主要是在触发器中。主要思想是进行最小的更改以在SQL Server 2008中保持相同的行为

可能的方法

  • 覆盖内置REPLACE功能快速搜索表明我的队友无法研究该选项
  • Rtrim()个功能与REPLACE一起使用。这将需要在多个例程(使用char列)中的代码中的确切位置进行替换
  • 创建自己的版本在CLR中替换以查看CLR允许我保持SQL Server 2005行为,然后再次在确切位置搜索和替换函数

我想问一下每个人是否有人遇到过这个问题,你是怎么解决的?

也欢迎任何建议,也许我只是不知道服务器实例或数据库级别上的哪些设置可以改变行为。

提前谢谢!

2 个答案:

答案 0 :(得分:7)

您有不同的SET ANSI_PADDING选项,也可以由SET ANSI_DEFAULTS

控制

目前,REPLACE在两个版本中表现相同。两者(20052008)都说:

  

如果其中一个输入参数是nvarchar数据类型,则返回nvarchar;否则,REPLACE返回varchar。

编辑:有2个连接错误/功能

我上面的回答可能是错误的

http://connect.microsoft.com/SQLServer/feedback/details/259840/trailing-spaces-are-lost-when-a-char-value-is-fed-to-replace

检查DB兼容级别:

http://connect.microsoft.com/SQLServer/feedback/details/126092/t-sql-replace-function-seems-to-be-broken-for-char-x-variables

作为修复,对不起,我会使用rtrim,但这是一个修复?你不能覆盖替换,如果你计划clr紧急,为什么不将replace / rtrim包装在SQL udf中

答案 1 :(得分:1)

根据MS,这是一个正确的行为,SQL2005错了。 在你的代码中你使用Replace()不仅作为核心功能(查找模式并替换为另一种模式)而且还作为Trim()函数(如果没有找到任何至少修剪传入值)

但是当你使用Char()时这是错误的。使用Char()作为数据类型的唯一原因是不惜一切代价保留值数据长度。(恕我直言),因为您需要确保返回的值长度总是相同,而不管实际存储的字符数。 当您需要使用字符串连接构建某种结构时,这很重要 与固定长度文件中的输出一样,并且不用担心数据长度检查或转换。 否则你也可以使用varchar()或nvarchar()

http://msdn.microsoft.com/en-us/library/ms143359(v=sql.100).aspx

在SQL Server 2005中,当参数的类型为char时,将修剪在REPLACE函数的第一个输入参数中指定的尾随空格。例如,在语句SELECT'<'中+ REPLACE(CONVERT(char(6),'ABC'),'','L')+'>',值'ABC'被错误地评估为'ABC'。

在SQL Server 2008中,始终保留尾随空格。对于依赖于函数先前行为的应用程序,在为函数指定第一个输入参数时使用RTRIM函数。例如,以下语法将重现SQL Server 2005行为SELECT'<' + REPLACE(RTRIM(CONVERT(char(6),'ABC')),'','L')+'>'。