Sql server 唯一索引、varchar列和(空白)空格的行为

Sql server 唯一索引、varchar列和(空白)空格的行为,sql-server,tsql,string-comparison,unique-index,Sql Server,Tsql,String Comparison,Unique Index,我正在使用Microsoft SQL Server 2008 R2和最新的service pack/修补程序,数据库排序规则为SQL\u Latin1\u General\u CP1\u CI\u AS 以下代码: SET ANSI_PADDING ON; GO CREATE TABLE Test ( Code VARCHAR(16) NULL ); CREATE UNIQUE INDEX UniqueIndex ON Test(Code); INSERT INTO Test

我正在使用Microsoft SQL Server 2008 R2和最新的service pack/修补程序,数据库排序规则为SQL\u Latin1\u General\u CP1\u CI\u 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行受影响

Msg 2601,第14级,状态1,第8行

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

声明已终止

‐‐‐‐‐‐‐‐‐

>样本:

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

此规则的唯一例外是LIKE谓词。什么时候合适 LIKE谓词表达式的侧面具有一个带有尾随符号的值 空间,SQL Server不会将这两个值填充到相同的长度 在比较发生之前。因为类似的目的 根据定义,谓词是为了方便模式搜索,而不是 与简单的字符串相等性测试相比,这并不违反 符合前面提到的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
这里有更多的细节

关于指标:

如果您提供的值与现有值不同,则插入值必须唯一的列将失败 仅限尾随空格。将考虑以下所有字符串 由唯一约束、主键或唯一索引等效。 同样,如果您有一个包含以下数据的现有表,请尝试 添加唯一的限制,它将失败,因为值为 被认为是相同的

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

摘自。

谢谢大家的指点。我为自己懒得用谷歌搜索而感到内疚。在我看来,标准定义的行为是不直观的。我可以想象,十分之九的开发人员会说“a”和“a”不是同一个字符串,但哦,好吧。这是我在Azure SQL中遇到的最不直观的事情之一。。。