我们可以阻止 SQL 服务器忽略值中的尾随空格吗?

Can we stop SQL Server EXCEPT from ignoring trailing spaces in values

我正在审核 2 个相同结构 table 中的值。 T-SQL EXCEPT 语句忽略了一个 table 中值的尾随 space,因此这些值不匹配,但也不会出现在我们的审核。

我已经尝试寻找方法来改变 SQL 比较列的方式。我做了类似的事情以确保它区分大小写,但找不到可以使其在字段值中包含白色 space/padding 的内容。

示例数据在 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

这个目前returns没有结果,说明数值是一样的。但是第二个table中的值最后有一个space。

我希望得到 "Product Name"

的结果

当我需要比较区分大小写的东西时,我可以添加

COLLATE SQL_Latin1_General_CP1_CS_AS

是否有类似的东西会因为空白 space 而显示不同的值?

根据这篇文章 (https://support.microsoft.com/en-us/help/316626/inf-how-sql-server-compares-strings-with-trailing-spaces) :

The ANSI standard requires padding for the character strings used in comparisons so that their lengths match before comparing them. The padding directly affects the semantics of WHERE and HAVING clause predicates and other Transact-SQL string comparisons. For example, Transact-SQL considers the strings 'abc' and 'abc ' to be equivalent for most comparison operations.

此行为是有意的。

您可以使用较慢的方法来实现您想要的:

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 方法会给出 'wrong' 结果)

这是旧的,已经回答了,但由于在 JOIN 条件下进行比较,我也在努力解决这个问题。虽然 SQL 服务器确实会忽略尾随 space,但它不会忽略前导 space。因此,对于我的 JOIN 条件,我比较了向前和向后(使用反向函数),这给了我一组更准确的结果。

在下面的示例中,我希望一个 table 中尾随 space 的行仅匹配 JOINed table 中尾随 space 的行。 REVERSE 函数对此有所帮助。

DECLARE @DbData AS TABLE (
    Id INT,
    StartDate DATETIME,
    OrgName VARCHAR(100)

)

DECLARE @IncomingData AS TABLE (
    Id INT,
    StartDate DATETIME,
    OrgName VARCHAR(100)
)

INSERT INTO @DbData (Id, StartDate, OrgName) 
SELECT 1, CAST('1 Jan 2022' AS DATE), 'Test ' UNION ALL 
SELECT 2, CAST('1 Jan 2022' AS DATE), 'Test' UNION ALL
SELECT 3, CAST('1 Jan 2022' AS DATE), 'Other Test' UNION ALL
SELECT 4, CAST('1 Jan 2022' AS DATE), 'Other Test ' 

INSERT INTO @IncomingData (Id, StartDate, OrgName)
SELECT 1, CAST('1 Jan 2022' AS DATE), 'Test ' UNION ALL 
SELECT 2, CAST('1 Jan 2022' AS DATE), 'Test' UNION ALL
SELECT 3, CAST('1 Jan 2022' AS DATE), 'Other Test' 

SELECT '~' + dd.OrgName + '~', '~' + id.OrgName + '~', * 
FROM @DbData dd
JOIN @IncomingData id ON id.StartDate = dd.StartDate
    AND dd.OrgName = id.OrgName
    AND REVERSE(dd.OrgName) = REVERSE(id.OrgName) -- Try the query with and without this line to see the difference it makes