Say*_*Pal 11 t-sql sql-server unicode collation sql-server-2016
作为默认的SQL_Latin1_General_CP1_CI_ASSQL服务器的排序规则不能区分ss和ß,我想换一个特定列的排序规则在表中SQL_Latin1_General_CP437_BIN2,如建议在这里.
但是,我不确定这是否通常是一种好的做法.此外,我不确定除以下之外的其他影响:
我很好奇这个变化的其他主要影响,如果有的话.
此外,我还想知道以下哪一个最适合这种情况:
SQL_Latin1_General_CP437_BIN
描述: Latin1-常规,Unicode数据的二进制排序,SQL Server在代码页437上的排序顺序30用于非Unicode数据
SQL_Latin1_General_CP437_BIN2
描述: Latin1-常规,Unicode数据的二进制代码点比较排序,SQL Server在代码页437上的排序顺序30用于非Unicode数据
SQL_Latin1_General_CP850_BIN
描述: Latin1-常规,Unicode数据的二进制排序,SQL Server在代码页850上的排序顺序40,用于非Unicode数据
SQL_Latin1_General_CP850_BIN2
描述: Latin1-常规,Unicode数据的二进制代码点比较排序,SQL Server在代码页850上的排序顺序40,用于非Unicode数据
如果您认为其他排序规则更适合此方案,请同时提及这些排序规则.
2017年3月19日更新: 对于提出此问题的任何人:
玩得开心 :)
Sol*_*zky 16
关于Collations的一些事情:
从SQL_SQL Server 2000开始,Collations被弃用(是的,2000).如果你可以避免使用它们,你应该(但这并不意味着如果没有迫切需要改变一堆东西!).
SQL_Collations 的问题实际上只与VARCHAR(即非Unicode)数据有关,因为NVARCHAR(即Unicode)数据使用OS中的规则.但VARCHAR遗憾的是,排序和比较数据的规则使用了简单的映射,并没有包含更复杂的语言规则.这就是为什么ss并且ß在VARCHAR使用相同的SQL_Latin1_General_CP1_CI_ASCollation 存储时不等同.当在单词的中间使用时,这些已弃用的Collations也无法给破折号赋予较低的权重.非SQL_Collations(即Windows Collations)对两者使用相同的规则VARCHAR,NVARCHAR因此VARCHAR处理更加健壮,更加一致NVARCHAR.
从_BINSQL Server 2005开始,Collations已被弃用.如果你可以避免使用它们,你应该(但这并不意味着如果没有迫切需要改变一堆东西!).
_BINCollations 的问题相当微妙,因为它只影响排序.由于它们在字节级别进行比较(因此没有语言规则),因此在Collations _BIN和_BIN2Collations 之间进行比较是相同的.但是,由于SQL Server(和Windows/PC)是Little Endian,实体以反向字节顺序存储.这在处理双字节"字符"时变得明显,这就是NVARCHAR数据:UTF-16 Little Endian.这意味着Unicode代码点U + 1216在Big Endian系统上具有0x1216的十六进制/二进制表示,但在Little Endian系统上存储为0x1612.要完整循环,以便最后一点的重要性(希望)变得明显:_BINCollations将逐字节比较(在第一个字符之后),因此将U + 1216视为0x16然后是0x12,而_BIN2Collations将比较代码点代码点,因此将U + 1216视为0x12然后是0x16.
这种特殊的列NVARCHAR(一个VARCHAR使用列SQL_Latin1_General_CP1_CI_AS不等同于ss和ß)等单独仅此列,也没有什么区别SQL_Latin1_General_CP437_BIN2,并SQL_Latin1_General_CP850_BIN2为Unicode是一个单一的,包罗万象的字符集所致.
对于VARCHAR数据,会有区别,因为它们是不同的代码页(437和850),并且它们都不同于您现在使用的CP1代码页(==代码页1252).
虽然使用二进制排序往往是矫枉过正,在这种情况下,它可能会因为只有一个区域/文化并不等于必须ß与ss匈牙利.使用匈牙利语校对可能有一些你不想要的语言规则(或者至少不会期望),所以二进制校对在这里似乎是更好的选择(不是你要问的4个中的任何一个:-) .请记住,通过使用二进制排序规则,您不仅放弃所有语言规则,而且还失去了将同一字符的不同版本等同起来的能力,例如A(Latin Capital Letter A U + 0041)和?(Fullwidth)拉丁大写字母A U + FF21).
使用以下查询来查看哪些排序规则是非二进制的,并且不等于这些字符:
DECLARE @SQL NVARCHAR(MAX) = N'DECLARE @Counter INT = 1;';
SELECT @SQL += REPLACE(N'
IF(N''ß'' COLLATE {Name} <> N''ss'' COLLATE {Name})
BEGIN
RAISERROR(N''%4d. {Name}'', 10, 1, @Counter) WITH NOWAIT;
SET @Counter += 1;
END;
', N'{Name}', col.[name]) + NCHAR(13) + NCHAR(10)
FROM sys.fn_helpcollations() col
WHERE col.[name] NOT LIKE N'SQL[_]%'
AND col.[name] NOT LIKE N'%[_]BIN%'
ORDER BY col.[name]
--PRINT @SQL;
EXEC (@SQL);
Run Code Online (Sandbox Code Playgroud)所以:
Latin1_General_100_BIN2.如果大多数/所有使用此列需要查询ß与ss被看作是不同的,然后继续前进,改变使用的列Latin1_General_100_BIN2.这可能需要删除以下依赖对象,然后在以下后重新创建ALTER TABLE:
提示:确保检查列的当前NULL/NOT NULL设置,并在ALTER TABLE ... ALTER COLUMN ...语句中指定它以使其不会更改.
COLLATE在每个条件的基础上(例如WHERE tab.[ThisColumn] LIKE N'%ss%' COLLATE Latin1_General_100_BIN2)覆盖那些与子句的比较操作.该COLLATE只需要一方(的运营商)关键字作为排序规则的优先将其应用到另一边.通常,BIN2优先于BIN,并且您可能希望在sql排序规则上选择Windows排序规则.例如Latin1_General_100_BIN2
使用BIN排序规则
如果SQL Server应用程序与使用二进制排序规则的旧版SQL Server交互,请继续使用二进制文件.对于混合环境,二进制排序可能是更合适的选择.
出于类似的原因是什么刚被有关规定BIN2排序规则,除非你有特殊要求,以保持向后兼容性问题,您应该倾斜向使用Windows排序规则,并开始与SQL不是SQL Server特定的归类(即那些有现在被认为有点"sucky";-)).
- 更改数据库默认排序规则时@srutzky - Latin1_General_BIN性能影响
rextester演示:http://rextester.com/KIIDYH74471
create table t (
a varchar(16) --collate SQL_Latin1_General_CP1_CI_AS /* default */
, b varchar(16) --collate SQL_Latin1_General_CP1_CI_AS
, c nvarchar(16) --collate SQL_Latin1_General_CP1_CI_AS
, d nvarchar(16) --collate SQL_Latin1_General_CP1_CI_AS
);
insert into t values ('ss','ß',N'ss',N'ß');
select *
, case when a = b then '=' else '!=' end as [a=b] /* != */
, case when a = d then '=' else '!=' end as [a=d] /* = */
, case when c = b then '=' else '!=' end as [c=b] /* = */
, case when c = d then '=' else '!=' end as [c=d] /* = */
from t;
Run Code Online (Sandbox Code Playgroud)
收益:
+----+---+----+---+-----+-----+-----+-----+
| a | b | c | d | a=b | a=d | c=b | c=d |
+----+---+----+---+-----+-----+-----+-----+
| ss | ß | ss | ß | != | = | = | = |
+----+---+----+---+-----+-----+-----+-----+
Run Code Online (Sandbox Code Playgroud)
create table t (
a varchar(16) collate Latin1_General_100_BIN2
, b varchar(16) collate Latin1_General_100_BIN2
, c nvarchar(16) collate Latin1_General_100_BIN2
, d nvarchar(16) collate Latin1_General_100_BIN2
);
insert into t values ('ss','ß',N'ss',N'ß');
select *
, case when a = b then '=' else '!=' end as [a=b] /* != */
, case when a = d then '=' else '!=' end as [a=d] /* != */
, case when c = b then '=' else '!=' end as [c=b] /* != */
, case when c = d then '=' else '!=' end as [c=d] /* != */
from t;
Run Code Online (Sandbox Code Playgroud)
收益:
+----+---+----+---+-----+-----+-----+-----+
| a | b | c | d | a=b | a=d | c=b | c=d |
+----+---+----+---+-----+-----+-----+-----+
| ss | ß | ss | ß | != | != | != | != |
+----+---+----+---+-----+-----+-----+-----+
Run Code Online (Sandbox Code Playgroud)