代码之家  ›  专栏  ›  技术社区  ›  Matthew

对于比较varchar和不带尾随空格的变量,如何使SQL Server返回false?

  •  11
  • Matthew  · 技术社区  · 14 年前

    如果我故意将尾随空格存储在 VARCHAR 列,如何强制SQL Server将数据视为不匹配?

    SELECT 'foo' WHERE 'bar' = 'bar    '
    

    我已经尝试过:

    SELECT 'foo' WHERE LEN('bar') = LEN('bar    ')
    

    我见过浮动的一种方法是在每个字符串的末尾附加一个特定的字符,然后将其去掉以供演示…但这似乎很愚蠢。

    有没有我忽略的方法?

    我注意到它不适用于 主要的 空格,所以我可能会运行一个函数,在比较之前颠倒字符顺序……问题是这会使查询变得不可组织….

    7 回复  |  直到 5 年前
        1
  •  6
  •   KyleMit Steven Vachon    6 年前

    从上的文档 LEN (Transact-SQL) :

    返回指定字符串表达式的字符数, 不包括尾随空格 . 要返回用于表示表达式的字节数,请使用 DATALENGTH 功能

    另外,从上的支持页 How SQL Server Compares Strings with Trailing Spaces :

    对于如何将字符串与空格进行比较,SQL Server遵循ANSI/ISO SQL-92规范。ANSI标准要求 比较中使用的字符串的填充,以便在比较字符串之前使其长度匹配 .

    更新 : 我用删除代码 LIKE (比较时不填充空格)和 DATALENGTH() 因为它们不是比较字符串的万无一失

    在许多其他地方也有这样的要求,其他解决方案也有这样的要求:

        2
  •  3
  •   LittleBobbyTables - Au Revoir    14 年前

    就像你说的,我认为没有很多选择。我能想到的只有这两个:

    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 最好的想法,但这一切都取决于谁为你表现最好。

        3
  •  2
  •   DForck42    14 年前

    你可以试试这样的方法:

    declare @a varchar(10), @b varchar(10)
    set @a='foo'
    set @b='foo   '
    
    select @a, @b, DATALENGTH(@a), DATALENGTH(@b)
    
        4
  •  1
  •   Damien_The_Unbeliever    14 年前

    我只有两条建议。一种方法是重新审视需要存储尾随空格的设计——它们在SQL中总是很难处理。

    第二步(考虑到您的sarg注释)是将计算列添加到存储长度的表中,并将此列添加到适当的索引中。这样,至少长度比较应该是可行的。

        5
  •  1
  •   Bruno Silva    9 年前

    经过一些搜索,我找到的最简单的解决方案是在安东尼·布卢埃什。 WebLog .

    只需在数据末尾添加一些文本(一个字符就足够了)(追加)

    SELECT 'foo' WHERE 'bar' + 'BOGUS_TXT' = 'bar    ' + 'BOGUS_TXT'
    

    也适用于“在哪里”

    SELECT <columnA>
    FROM <tableA>
    WHERE <columnA> + 'BOGUS_TXT' in ( SELECT <columnB> + 'BOGUS_TXT' FROM <tableB> )
    
        6
  •  1
  •   Kenny Evitt    6 年前

    IM计划使用的方法是使用一个正常的比较,这个比较应该是索引可键入的(可搜索的),并由一个 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)
    

    由查询优化器决定过滤器的顺序,但如果对正在测试的表有意义的话,它应该选择使用索引进行数据查找,然后使用更昂贵的标量操作进一步按长度筛选剩余的结果。然而,正如另一个答案所述,最好使用索引计算列来避免这些标量操作。如果您对模式没有控制权,或者您希望避免创建计算列,或者如果创建和维护计算列被认为比查询性能更差的话,那么这里介绍的方法可能是有意义的。

        7
  •  0
  •   Extragorey    5 年前

    有时最愚蠢的解决方案是最好的:

    SELECT 'foo' WHERE 'bar' + 'x' = 'bar     ' + 'x'
    

    所以在进行比较之前,基本上在两个字符串中附加任何字符。