Yar*_*lav 11 sql-server collation t-sql sql-server-2014 unique-constraint
我有一个带有唯一键的表,其中包含一NVARCHAR(50)
列(正确与否,但在那里)。因此,当尝试插入?c
或C
(与插入顺序无关)时,由于整理问题,它会在第二次插入时中断。这是错误:
(受影响的 1 行)消息 2601,级别 14,状态 1,第 16 行无法在具有唯一索引“IX_TestT”的对象“dbo.testT”中插入重复的关键行。重复的键值为 (C)。
选择退货:
数据库默认排序规则是Latin1_General_CI_AS
. 花了一些时间寻找如何解决它,而不会对现有结构进行太多更改,但找不到开始工作的方法。尝试了不同的排序规则和组合,一切都失败了。阅读(这里和这里)关于字符扩展等,仍然卡住了。这是我用来复制问题的示例代码,请随时修改并推荐任何有助于解决此问题的内容。
CREATE TABLE testT (
[Default_Collation] [NVARCHAR] (50) COLLATE DATABASE_DEFAULT,
[Latin1_General_CI_AS] [NVARCHAR] (50) COLLATE Latin1_General_CI_AS,
[Latin1_General_CI_AI] [NVARCHAR] (50) COLLATE Latin1_General_CI_AI,
[SQL_Collation] [NVARCHAR] (50) COLLATE SQL_Latin1_General_CP1_CI_AS);
CREATE UNIQUE CLUSTERED INDEX [IX_TestT] ON [dbo].[testT] ([Default_Collation])
ON [PRIMARY]
GO
INSERT INTO testT
SELECT N'?c', --COLLATE Latin1_General_CI_AS
N'?c', --COLLATE Latin1_General_CI_AS
N'?c', --COLLATE Latin1_General_CI_AS
N'?c' --COLLATE Latin1_General_CI_AS
INSERT INTO testT
SELECT N'C' --COLLATE Latin1_General_CI_AS
,N'C' --COLLATE Latin1_General_CI_AS
,N'C' --COLLATE Latin1_General_CI_AS
,N'C' --COLLATE SQL_Latin1_General_CP1_CI_AS
SELECT * FROM testT;
DROP TABLE testT;
Run Code Online (Sandbox Code Playgroud)
Sol*_*zky 11
问题是,旧的SQL Server排序规则(即那些开始的名字SQL_
)和Windows排序规则的前两个版本(在80
其附带的SQL Server 2000,并且没有在名称的版本号系列,以及90
一系列SQL Server 2005 附带)缺少许多字符的排序权重。从100
SQL Server 2008 附带的系列排序规则开始,这大部分得到纠正。
正如您在下面的示例中看到的,?
当使用非二进制版本 80 或 90 排序规则(和 SQL Server 排序规则)时,该字符匹配空字符串,因为它们都具有相同的排序权重:0。没有。纳达。这意味着当N'?c'
与N'C'
(使用系列前的 100 排序规则)进行比较N'c'
时,您实际上是在与N'C'
(测试 #1)进行比较:
SELECT 1 WHERE N'?c' = N'C' COLLATE Latin1_General_CS_AS;
-- no result (due to "c" and "C" being different case)
SELECT 2 WHERE N'?' = N'' COLLATE SQL_Latin1_General_CP1_CI_AS;
SELECT 3 WHERE N'?' = N'' COLLATE Latin1_General_CI_AS;
SELECT 4 WHERE N'?' = N'' COLLATE Latin1_General_BIN2;
-- no result (due to "?" still being a code point and empty string has no code points)
SELECT 5 WHERE N'?' = N'' COLLATE Latin1_General_100_CI_AS;
-- no result (due to "?" finally having a sort weight in 100 series Collations)
SELECT 6 WHERE N'?' = N'' COLLATE Chinese_PRC_CI_AI;
SELECT 7 WHERE N'?' = N'' COLLATE Chinese_PRC_90_CI_AI;
SELECT 8 WHERE N'?' = N'' COLLATE Indic_General_90_CI_AI;
SELECT 9 WHERE N'?' = N'' COLLATE Indic_General_100_CI_AI;
-- no result (due to "?" finally having a sort weight in 100 series Collations)
Run Code Online (Sandbox Code Playgroud)
因此,不幸的是,您将需要删除 PK,将列更改为具有 100 级排序规则(例如Latin1_General_100_CI_AS_SC
),然后重新创建 PK。请注意,建议的排序规则与当前排序规则的区别在于结尾的the100
和the _SC
,这使其能够正确处理补充字符。
但这并不意味着你需要:
NVARCHAR
在 PK 中具有相同的设置)table.column = N'?'
和操作之间存在行为差异@variable = N'?'
。有关此行为的更多示例,请参阅我的以下博客文章的“补充字符”部分:
统一代码:搜索 T-SQL 标识符的真实有效字符列表,第 3 部分,共 2 部分(分隔标识符)
归档时间: |
|
查看次数: |
297 次 |
最近记录: |