14

我正在使用 Microsoft SQL Server 2008 R2(带有最新的服务包/补丁)并且数据库排序规则是 SQL_Latin1_General_CP1_CI_AS。

以下代码:

SET ANSI_PADDING ON;
GO

CREATE TABLE Test (
   Code VARCHAR(16) NULL
);
CREATE UNIQUE INDEX UniqueIndex
    ON Test(Code);

INSERT INTO Test VALUES ('sample');
INSERT INTO Test VALUES ('sample ');

SELECT '>' + Code + '<' FROM Test WHERE Code = 'sample        ';
GO

产生以下结果:

(1 行受影响)

消息 2601,第 14 层,状态 1,第 8 行

无法在具有唯一索引“UniqueIndex”的对象“dbo.Test”中插入重复的键行。重复键值为 (sample )。

该语句已终止。

——————————————————</p>

>样品<

(1 行受影响)

我的问题是:

  1. 我假设索引不能存储尾随空格。谁能指出我指定/定义此行为的官方文档?
  2. 是否有更改此行为的设置,即使其将“sample”和“sample”识别为两个不同的值(顺便说一下),因此两者都可以在索引中。
  3. 为什么在地球上是 SELECT 返回一行?SQL Server 必须对 WHERE 子句中的空格做一些非常有趣/聪明的事情,因为如果我删除索引中的唯一性,两个 INSERT 都将运行正常,并且 SELECT 将返回两行!

任何正确方向的帮助/指针将不胜感激。谢谢。

4

1 回答 1

18

尾随空格解释

SQL Server 遵循关于如何比较字符串 和空格的 ANSI/ISO SQL-92 规范(第 8.2 节,一般规则 #3)。ANSI 标准要求对比较中使用的字符串进行填充,以便它们的长度在比较之前匹配。填充直接影响 WHERE 和 HAVING 子句谓词的语义以及其他 Transact-SQL 字符串比较。例如,Transact-SQL 认为字符串“abc”和“abc”对于大多数比较操作是等效的。

此规则的唯一例外是 LIKE 谓词。当 LIKE 谓词表达式的右侧包含一个带有尾随空格的值时,SQL Server 不会在比较发生之前将这两个值填充到相同的长度。因为根据定义,LIKE 谓词的目的是促进模式搜索而不是简单的字符串相等测试,所以这并不违反前面提到的 ANSI SQL-92 规范部分。

以下是上述所有案例的一个众所周知的示例:

DECLARE @a VARCHAR(10)
DECLARE @b varchar(10)

SET @a = '1'
SET @b = '1 ' --with trailing blank

SELECT 1
WHERE 
    @a = @b 
AND @a NOT LIKE @b
AND @b LIKE @a

以下是有关尾随空格和LIKE子句的更多详细信息。

关于指标:

如果您提供的值仅通过尾随空格与现有值区分开来,则插入其值必须唯一的列将失败。以下字符串都将被唯一约束、主键或唯一索引视为等效。同样,如果您有一个包含以下数据的现有表并尝试添加唯一限制,它将失败,因为这些值被认为是相同的。

PaddedColumn
------------
'abc'
'abc '
'abc  '
'abc    '

(取自这里。)

于 2012-02-27T06:12:27.277 回答