Функция REPLACE в T-SQL 2008 отличается от T-SQL 2005 - PullRequest
5 голосов
/ 08 августа 2011

Я нахожусь в процессе миграции баз данных с 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                    "

T-SQL в SQL Server 2005 удаляет даже законное конечное пространство, не говоря уже о том, что он угрожает char(25) как varchar(25). T-SQL в SQL Server 2008 более тщательно подходит к типу и возвращает результаты в соответствии с типом, который он получает для преобразования

У меня есть номера в разных объектах T-SQL, в основном в триггерах. Основная идея просто внести минимальные изменения, чтобы сохранить то же поведение в SQL Server 2008

Возможные способы сделать это

  • Переопределить встроенную функцию REPLACE Быстрый поиск показывает, что это невозможно, однако мой напарник хочет исследовать эту опцию
  • Используйте функции Rtrim() вместе с REPLACE. Это потребует замены в точных местах кода в нескольких подпрограммах (где используются столбцы char)
  • Создание собственной версии Замените в CLR, чтобы увидеть, что CLR позволяет мне поддерживать поведение SQL Server 2005, а затем снова искать и заменять функцию в точном месте

Я хотел бы спросить всех, сталкивался ли кто-нибудь с этой проблемой, как вы справились?

Также приветствуются любые предложения, может быть, я просто не знаю, какие настройки на уровне экземпляра сервера или базы данных могут изменить поведение.

Заранее спасибо!

Ответы [ 2 ]

7 голосов
/ 08 августа 2011

У вас есть различные опции SET ANSI_PADDING , которыми также можно управлять с помощью SET ANSI_DEFAULTS

В текущем состоянии REPLACE ведет себя одинаково в обеих редакциях.Оба ( 2005 , 2008 ) говорят:

Возвращает nvarchar, если один из входных аргументов имеет тип данных nvarchar;в противном случае REPLACE возвращает varchar.

Редактировать: есть 2 ошибки / функции Connect

Мой ответ выше, вероятно, неправильный

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

Проверьте уровень совместимости с БД:

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

И в качестве исправления, извините, я бы использовал rtrim, однако это исправление?Вы не можете переопределить замену, и если вы планируете срочный вызов clr, почему бы не обернуть замену / rtrim в SQL udf

1 голос
/ 14 января 2013

по мнению MS, это правильное поведение, и SQL2005 ошибался. в вашем коде вы используете Replace () не только как функцию corection (найти шаблон и заменить другим шаблоном) , но и как функцию Trim () (если ничего не найдено, по крайней мере обрезать входящее значение )

но это неправильно, когда вы работаете с Char (). единственная причина использовать Char () в качестве типа данных - сохранить длину данных значений любой ценой (IMHO), так как вам необходимо убедиться, что длина возвращаемого значения ВСЕГДА одинакова, независимо от фактического количества сохраненных символов. это важно, когда вам нужно построить какую-то структуру с использованием конкатенации строк как в файле фиксированной длины для вывода, и не заботьтесь о проверках длины данных или преобразованиях. в противном случае вы также можете использовать varchar () или nvarchar ()

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

В SQL Server 2005 завершающие пробелы, указанные в первом входном параметре функции REPLACE, обрезаются, когда параметр имеет тип char. Например, в операторе SELECT '<' + REPLACE (CONVERT (char (6), 'ABC'), '', 'L') + '>' значение 'ABC' неправильно оценивается как 'ABC'.

В SQL Server 2008 конечные пробелы всегда сохраняются. Для приложений, которые полагаются на предыдущее поведение функции, используйте функцию RTRIM при указании первого входного параметра для функции. Например, следующий синтаксис будет воспроизводить поведение SQL Server 2005 SELECT '<' + REPLACE (RTRIM (CONVERT (char (6), 'ABC')), '', 'L') + '>'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...