coc*_*lla 5 sql-server unicode sql-server-2016
Phone
SQL Server 在唯一索引中将它们视为相同的下面插入的值是什么意思?
CREATE TABLE Phone
(
Id int identity(1, 1) primary key,
Phone nvarchar(448) not null
)
go
create unique index IX_Phone on Phone(Phone)
with (data_compression = page);
go
insert into Phone Values ('?281/?263-?8400');
insert into Phone Values ('?281/?263-?8400');
select * from Phone;
drop table Phone;
Run Code Online (Sandbox Code Playgroud)
我收到一条错误消息:
消息 2601,级别 14,状态 1,第 13 行无法在唯一索引为“IX_Phone”的对象“dbo.Phone”中插入重复的键行。重复的键值为 (?281/?263-?8400)。
您的问题是您将unicode字符串作为non-unicode传递。
\n\n你的\'\xe2\x80\x8e281/\xe2\x80\x8e263-\xe2\x80\x8e8400\'是一个15个字符的字符串,而不是12个,有3个不可打印的8206符号,从左到右标记
\n\nselect len(\'\xe2\x80\x8e281/\xe2\x80\x8e263-\xe2\x80\x8e8400\'); -- 15 !!!\n
Run Code Online (Sandbox Code Playgroud)\n\n尝试一下我将 unicode 值作为unicode传递的代码,看看完全没有问题:
\n\nCREATE TABLE dbo.Phone\n(\n Id int identity(1, 1) primary key,\n Phone nvarchar(448) not null\n)\ngo\n\ncreate unique index IX_Phone on Phone(Phone)\nwith (data_compression = page);\ngo\n\ninsert into Phone(phone) Values (N\'?281/?263-?8400\');\ninsert into Phone(phone) Values (N\'\xe2\x80\x8e281/\xe2\x80\x8e263-\xe2\x80\x8e8400\');\n\nselect * from Phone;\n
Run Code Online (Sandbox Code Playgroud)\n\n这就是你的字符串 \'\xe2\x80\x8e281/\xe2\x80\x8e263-\xe2\x80\x8e8400\' 真正包含的内容(dbo.nums
是我包含自然数的表):
declare @t table(col1 nvarchar(100), col2 nvarchar(100));\ninsert into @t values (N\'?281/?263-?8400\', N\'\xe2\x80\x8e281/\xe2\x80\x8e263-\xe2\x80\x8e8400\'); \n\nselect n, unicode(substring(col1, n, 1)), unicode(substring(col2, n, 1))\nfrom @t cross join dbo.nums\nwhere n <= 15;\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n现在,当您将 unicode 字符串作为非 unicode 传递时会发生什么。
\n\n您的不可打印符号 8206 会转换为?
,这就是非 unicode 字符串的工作方式:在相应代码页中找不到并表示为 ascii 代码的每个字符都用问号替换。
因此,例如,如果您使用拉丁语排序规则并尝试比较希伯来语和西里尔字符(相同数量的字符),因为varchar
它们总是相等,只是因为它们在比较时被转换为问号nvarchar
它们不同:
因此,如果现在您尝试将这 2 个值(希伯来语 + 西里尔字母)插入到您的 Phone 表中,将它们传递为non-unicode
(不使用N
)传递,则只会插入其中一个,而另一个将被唯一约束拒绝。\n并且如果您尝试从电话中选择,将返回“??????”
归档时间: |
|
查看次数: |
1293 次 |
最近记录: |