Можем ли мы остановить SQL Server EXCEPT от игнорирования конечных пробелов в значениях - PullRequest
1 голос
/ 15 апреля 2019

Я проверяю значения в 2 одинаковых таблицах структуры.Оператор T-SQL EXCEPT игнорирует завершающий пробел для значения в одной таблице, поэтому значения не совпадают, но также не отображаются в нашем аудите.

Я пытался найти способыизменить, как SQL сравнивает столбцы.Я сделал что-то подобное, чтобы убедиться, что он чувствителен к регистру, но не смог найти что-то, что заставило бы его включить пробел / отступ в значении поля.

Пример данных будет иметь значение в MyTable как "Product Name », в то время как RemoteTable имеет значение« Product Name ».

Чтобы быстро воспроизвести, вот уменьшенная версия того, что я делаю сейчас:

DECLARE @SampleLocal TABLE(ProductName varchar(50))
DECLARE @RemoteTable TABLE(ProductName varchar(50))

INSERT INTO @SampleLocal (ProductName) VALUES ('Product Name')
INSERT INTO @RemoteTable (ProductName) VALUES ('Product Name ')

SELECT ProductName COLLATE SQL_Latin1_General_CP1_CS_AS ProductName  
FROM @SampleLocal

EXCEPT

SELECT ProductName COLLATE SQL_Latin1_General_CP1_CS_AS ProductName  
FROM @RemoteTable

В настоящее время это не возвращает результатов, показывая, что значения одинаковы.Но значение во второй таблице имеет пробел в конце.

Я ожидал бы получить результат с «Product Name»

Когда мне нужно было сравнить вещи с чувствительностью к регистру, яудалось добавить

COLLATE SQL_Latin1_General_CP1_CS_AS

Есть ли что-то похожее, что показывало бы значение, отличное из-за пробела?

1 Ответ

4 голосов
/ 15 апреля 2019

Согласно этой статье (https://support.microsoft.com/en-us/help/316626/inf-how-sql-server-compares-strings-with-trailing-spaces):

Стандарт ANSI требует заполнения для строк символов, используемых в сравнениях, чтобы их длина соответствовала перед сравнением. Заполнение напрямую влияет на семантику предикатов предложения WHERE и HAVING и другие сравнения строк Transact-SQL. Например, Transact-SQL считает, что строки 'abc' и 'abc' эквивалентны для большинства операций сравнения.

Это поведение предназначено.

Вы можете использовать более медленный метод для достижения желаемого:

SELECT innerItems.ProductName
FROM
(
    SELECT DATALENGTH(ProductName) as realLength, ProductName  COLLATE SQL_Latin1_General_CP1_CS_AS as ProductName 
    FROM @SampleLocal
    EXCEPT
    SELECT DATALENGTH(ProductName) as realLength, ProductName  COLLATE SQL_Latin1_General_CP1_CS_AS as ProductName
    FROM @RemoteTable
) innerItems

Сравнение значений и реальной длины вместе делает магию здесь. (В этом случае метод len даст «неправильный» результат)

...