Подтвердить что ты не робот

Предложение SQL WHERE для сопоставления значений с конечными пробелами

В SQL Server 2008 у меня есть таблица с именем Zone с столбцом ZoneReference varchar(50) not null в качестве первичного ключа.

Если я запустил следующий запрос:

select '"' + ZoneReference + '"' as QuotedZoneReference
from Zone
where ZoneReference = 'WF11XU'

Получаю следующий результат:

"WF11XU "

Обратите внимание на конечное пространство.

Как это возможно? Если в этой строке есть конечное пространство, я ожидаю вернуть результаты нуль, поэтому я предполагаю, что это будет нечто, что SQL Server Management Studio отображает странно.

В вызове кода С# zoneReference.Trim() удаляется его, указывая, что это какой-то символ пробела.

Может ли кто-нибудь помочь?

4b9b3361

Ответ 1

Это ожидаемый результат: в SQL Server оператор = игнорирует конечные пробелы при сравнении.

SQL Server следует спецификации ANSI/ISO SQL-92 (раздел 8.2, Общие правила № 3) о том, как сравнивать строки с пробелами. Стандарт ANSI требует заполнения для символьных строк, используемых в сравнении, чтобы их длины совпадали перед их сравнением. Заполнение напрямую влияет на семантику предикатов предложения WHERE и HAVING и других сравнений строк Transact-SQL. Например, Transact-SQL считает, что строки abc и abc эквивалентны для большинства операций сравнения.

Единственным исключением из этого правила является предикат LIKE. Когда правая часть предикатного выражения LIKE имеет значение с конечным пространством, SQL Server не заполняет два значения до одной длины до того, как произойдет сравнение. Поскольку целью предиката LIKE, по определению, является облегчение поиска шаблонов, а не простых тестов равенства строк, это не нарушает раздел упомянутой ранее спецификации ANSI SQL-92.

Источник

Ответ 2

Промежуточные пробелы не всегда игнорируются. Сегодня я испытал этот вопрос. В моей таблице были столбцы NCHAR и соединялись с данными VARCHAR. Поскольку данные в таблице были не такими широкими, как поле, конечные пробелы были автоматически добавлены SQL Server.

У меня была ITVF (встроенная функция с табличной оценкой), которая принимала параметры varchar. Параметры использовались в JOIN для таблицы с полями NCHAR.

Соединения не удались, потому что данные, переданные функции, не имели завершающих пробелов, но данные в таблице выполнялись. Почему это было?

Я сработал на DEC TYPE PRECEDENCE. (См. http://technet.microsoft.com/en-us/library/ms190309.aspx)

При сравнении строк разных типов тип более низкого приоритета перед сравнением преобразуется в более высокий тип приоритета. Поэтому параметры VARCHAR были преобразованы в NCHAR. Сравнение NCHAR сравнивалось, и, по-видимому, пространства были значительными.

Как я это исправил? Я изменил определение функции для использования параметров NVARCHAR, которые имеют более высокий приоритет, чем NCHAR. Теперь NCHAR были автоматически изменены SQL Server в NVARCHAR, а конечные пробелы были проигнорированы.

Почему я просто не выполнял RTRIM? Тестирование показало, что RTRIM убил производительность, предотвращая оптимизации JOIN, которые SQL Server использовал бы в противном случае.

Почему бы не изменить тип данных таблицы? Таблицы уже установлены на клиентских сайтах, и они не хотят запускать сценарии обслуживания (время + деньги для оплаты DBAs) или дают нам доступ к их машинам (понятно).

Ответ 3

Да, Марк прав. Запустите следующий SQL:

create table #temp (name varchar(15))
insert into #temp values ('james ')
select '"' + name + '"' from #temp where name ='james'
select '"' + name + '"' from #temp where name like 'james'
drop table #temp

Но утверждение о "подобном" утверждении, похоже, не работает в приведенном выше примере. Выход:

(1 row(s) affected)

-----------------
"james "

(1 row(s) affected)


-----------------
"james "

(1 row(s) affected)

EDIT: Чтобы заставить его работать, вы можете положить конец:

and name <> rtrim(ltrim(name))

Уродливый, хотя.

EDIT2: Учитывая комментарии abovem, будет работать следующее:

select '"' + name + '"' from #temp where 'james' like name

Ответ 4

попробовать

    select Replace('"' + ZoneReference + '"'," ", "") as QuotedZoneReference from Zone where ZoneReference = 'WF11XU'