我使用的是Microsoft SQL Server 2008 R2(带有最新的service pack/修补程序),数据库排序规则为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)。
语句已终止。
‐‐‐‐
>样本<
(1行受影响)
我的问题是:
- 我认为索引无法存储尾部空格。有人能给我指一下指定/定义这种行为的官方文件吗
- 是否有一个设置可以更改此行为,即使其将"sample"one_answers"sample"识别为两个不同的值(顺便说一句,它们是),以便两者都可以在索引中
- 到底为什么SELECT返回一行?SQL Server一定对WHERE子句中的空格做了一些非常有趣/聪明的处理,因为如果我删除索引中的唯一性,两个INSERT都将运行正常,SELECT将返回两行
如有任何正确方向的帮助/指示,我们将不胜感激。谢谢
解释了尾随空格:
SQL Server遵循ANSI/ISO SQL-92规范(第8.2节,,关于如何比较字符串的一般规则#3)带有空格。ANSI标准要求对字符进行填充比较中使用的字符串,以便它们的长度在比较它们。填充直接影响WHERE的语义和HAVING子句谓词和其他Transact-SQL字符串比较。例如,Transact-SQL考虑字符串"abc"one_answers"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 '
(取自此处。)