如果我故意将尾随空格存储在一个 VARCHAR
专栏,如何强制SQL Server将数据视为不匹配?
SELECT 'foo' WHERE 'bar' = 'bar '
我努力了:
SELECT 'foo' WHERE LEN('bar') = LEN('bar ')
我看到浮动的一种方法是在每个字符串的末尾添加一个特定的字符,然后将其删除以供我的演示文稿...但这看起来很傻。
有没有一种方法我忽略了?
我注意到它不适用于 领导 所以也许我运行一个函数,在比较之前反转字符顺序....问题是这使得查询unSARGable ....
来自文档 LEN(Transact-SQL):
返回指定字符串表达式的字符数, 不包括尾随空白。要返回用于表示表达式的字节数,请使用 DATALENGTH
功能
另外,从支持页面上 SQL Server如何将字符串与尾随空格进行比较:
SQL Server遵循ANSI / ISO SQL-92规范,介绍如何将字符串与空格进行比较。 ANSI标准要求 填充比较中使用的字符串,以便在比较它们之前匹配它们的长度。
更新: 我删除了我的代码 LIKE
(在比较期间不填充空格)和 DATALENGTH()
因为它们对比较字符串并非万无一失
在许多其他地方也有人问过其他解决方案:
来自文档 LEN(Transact-SQL):
返回指定字符串表达式的字符数, 不包括尾随空白。要返回用于表示表达式的字节数,请使用 DATALENGTH
功能
另外,从支持页面上 SQL Server如何将字符串与尾随空格进行比较:
SQL Server遵循ANSI / ISO SQL-92规范,介绍如何将字符串与空格进行比较。 ANSI标准要求 填充比较中使用的字符串,以便在比较它们之前匹配它们的长度。
更新: 我删除了我的代码 LIKE
(在比较期间不填充空格)和 DATALENGTH()
因为它们对比较字符串并非万无一失
在许多其他地方也有人问过其他解决方案:
就像你说的,我不认为有很多选择。我能想出的唯一两个是这些:
DECLARE @x nvarchar(50)
DECLARE @y nvarchar(50)
SET @x = 'CAT '
SET @y = 'CAT'
SELECT 1 WHERE len(@x + '_') = len(@y + '_')
SELECT 1 WHERE reverse(@x) = reverse(@y)
编辑
想到第三个:
SELECT 1 WHERE REPLACE(@x, ' ', '_') = REPLACE(@y, ' ', '_')
第四,假设您使用的是SQL 2005+
SELECT 1 WHERE QUOTENAME(@x) = QUOTENAME(@y)
就个人而言,我喜欢 reverse
想法最好,但这一切都取决于哪一个最适合你。
你可以尝试这样的东西:
declare @a varchar(10), @b varchar(10)
set @a='foo'
set @b='foo '
select @a, @b, DATALENGTH(@a), DATALENGTH(@b)
我只有两个建议。一种是重新审视需要您存储尾随空格的设计 - 在SQL中处理它们总是很痛苦。
第二个(给出您的SARG能力评论)将添加计算列到存储长度的表,并将此列添加到适当的索引。这样,至少,长度比较应该是SARG能力的。
经过一番搜索,我找到的最简单的解决方案是Anthony Bloesch
网络日志。
只需在数据末尾添加一些文本(char足够)(追加)
SELECT 'foo' WHERE 'bar' + 'BOGUS_TXT' = 'bar ' + 'BOGUS_TXT'
也适用于'WHERE IN'
SELECT <columnA>
FROM <tableA>
WHERE <columnA> + 'BOGUS_TXT' in ( SELECT <columnB> + 'BOGUS_TXT' FROM <tableB> )
我打算使用的方法是使用正常的比较,该比较应该是索引可键控的(“sargable”),并由 DATALENGTH
(因为 LEN
忽略空白)。它看起来像这样:
DECLARE @testValue VARCHAR(MAX) = 'x';
SELECT t.Id, t.Value
FROM dbo.MyTable t
WHERE t.Value = @testValue AND DATALENGTH(t.Value) = DATALENGTH(@testValue)
由查询优化器决定过滤器的顺序,但如果对正在测试的表有意义,则应选择使用索引进行数据查找,然后使用更昂贵的标量进一步过滤剩余的结果操作。但是,正如另一个答案所述,最好通过使用索引计算列来完全避免这些标量操作。如果您无法控制架构,或者您希望避免创建计算列,或者创建和维护计算列被认为比较差的查询性能更昂贵,则此处介绍的方法可能有意义。