SQL Server varchar不等式 - 撇号产生奇怪的结果

时间:2013-12-03 23:00:38

标签: tsql sql-server-2012

使用SQL Server 2012

请注意以下类似于我公司代码中使用的查询。 name列的类型为nvarchar(100):

select * 
from foo
where name >= 'papa d''s' 
    and name < 'papa d''szzzzzz'

这会产生一些意想不到的结果。除了返回name ='papa d's pizza inc'的任何记录之外,它还返回name ='papa ds pizza inc'的记录。注意第二个结果中缺少的撇号。

现在看看这两个问题:

select 1 where 'papa ds pizza inc' >= 'papa d''s'
GO
select 1 where 'papa ds pizza inc' < 'papa d''szzzzzz'

只有第一个查询返回1,这意味着我的第一个查询中的AND条件应该失败。

有人能告诉我这里发生了什么吗?

如果您可以描述为什么有人会以这种方式查询而不是使用带通配符的LIKE子句,那么

奖励积分,假设注入被其他验证阻止。

1 个答案:

答案 0 :(得分:2)

问题与您的name列是双字节字符串(nvarchar)并且您的字符串文字是单字节字符串(char / varchar )。像'foobar'这样的SQL字符串文字是单字节字符串(char / varchar)。要使它成为双字节字符串(nchar / nvarchar),您需要在其前面添加NN'foobar'是一个双字节字符串。

我认为你发现了一个SQL Server错误。您可以通过Microsoft Connect在https://connect.microsoft.com/SQLServer报告(但我不会屏住呼吸修复它)。

我正在使用一个vanilla SQL Server 2012安装,其默认排序规则为SQL_Latin1_General_CP1_CI_AS。

  • 使用单字节(varchar)字符串执行此查询:

    declare @name varchar(100) = 'papa ds pizza inc'
    select 'gt' where @name >= 'papa d''s'
    UNION
    select 'lt' where @name <  'papa d''szzzzzz'
    

    我们得到预期的结果集:

    gt
    
  • 将数据类型更改为双字节(nvarchar),

    declare @name nvarchar(100) = N'papa ds pizza inc'
    select 'gt' where @name >= 'papa d''s'
    UNION
    select 'lt' where @name <  'papa d''szzzzzz'
    

    我们得到了意想不到的结果集

    gt
    lt
    
  • 如果我们采用正确工作的单字节版本并将文字转换为双字节文字:

    declare @name varchar(100) = 'papa ds pizza inc'
    select 'gt' where @name >= N'papa d''s'
    UNION
    select 'lt' where @name <  N'papa d''szzzzzz'
    

    我们再次得到错误且意外的结果集:

    gt
    lt