由于SQL Server的默认SQL_Latin1_General_CP1_CI_AS
排序规则无法区分ss
和ß
,因此我想将表中特定列的排序规则更改为{{1} },如here中所述。
但是,我不确定这是否通常是一种好习惯。此外,我不确定除以下内容之外的其他影响:
我很好奇这个变化的其他主要影响,如果有的话。
此外,我还想知道以下哪一个最适合这种情况:
SQL_Latin1_General_CP437_BIN
描述:Latin1-常规,Unicode数据的二进制排序,SQL Server在代码页437上排序,用于非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日更新: 对于提出这个问题的任何人:
玩得开心:)
答案 0 :(得分:16)
关于Collations的一些事情:
从SQL Server 2000开始,SQL_
排序已弃用(是的,2000)。如果你可以避免使用它们,你应该(但这并不意味着如果没有迫切需要改变一堆东西!)。
SQL_
排序规则的问题实际上只与VARCHAR
(即非Unicode)数据有关,因为NVARCHAR
(即Unicode)数据使用操作系统中的规则。但遗憾的是,VARCHAR
数据的排序和比较规则使用了简单的映射,并没有包含更复杂的语言规则。这就是ss
和ß
使用相同的VARCHAR
排序规则存储为SQL_Latin1_General_CP1_CI_AS
时不等同的原因。当在单词的中间使用时,这些已弃用的Collations也无法给破折号赋予较低的权重。非SQL_
排序规则(即Windows排序规则)对VARCHAR
和NVARCHAR
使用相同的规则,因此VARCHAR
处理更加健壮,与{{1}更加一致}。
从SQL Server 2005开始,NVARCHAR
排序已弃用。如果您可以避免使用它们,那么您应该(但这并不意味着如果没有迫切需要改变一堆事情) !)。
_BIN
排序规则的问题相当微妙,因为它只影响排序。 _BIN
和_BIN
归类之间的比较是相同的,因为它们在字节级别进行比较(因此没有语言规则)。但是,由于SQL Server(和Windows / PC)是Little Endian,实体以反向字节顺序存储。这在处理双字节“字符”时变得明显,这是_BIN2
数据:UTF-16 Little Endian。这意味着Unicode代码点U + 1216在Big Endian系统上具有0x1216的十六进制/二进制表示,但在Little Endian系统上存储为0x1612。要完全循环,以便最后一点的重要性(希望)变得明显:NVARCHAR
Collations将逐字节比较(在第一个字符之后),因此将U + 1216视为0x16然后是0x12,而_BIN
排序将按代码点比较代码点,因此将U + 1216视为0x12,然后是0x16。
此特定列为_BIN2
(使用NVARCHAR
的{{1}}列不等同于VARCHAR
和SQL_Latin1_General_CP1_CI_AS
),因此仅适用于此列单独,ss
和ß
之间没有区别,因为Unicode是一个单一的全包字符集。
对于SQL_Latin1_General_CP437_BIN2
数据,会有不同之处,因为它们是不同的代码页(437和850),而且这两者都不同于您正在使用(SQL_Latin1_General_CP850_BIN2
==代码页1252)。
虽然使用二进制排序通常是矫枉过正,但在这种情况下,可能有必要,因为只有一个区域设置/文化不等同于VARCHAR
和CP1
:匈牙利语。使用匈牙利语校对可能有一些你不想要的语言规则(或者至少不会期望),所以二进制校对在这里似乎是更好的选择(不是你要问的4个中的任何一个:-) 。请记住,通过使用二进制排序规则,您不仅放弃所有语言规则,而且还失去了将同一个字符的不同版本等同起来的能力,例如ß
(Latin Capital Letter A U+0041)和ss
(Fullwidth Latin Capital Letter A U+FF21)。
使用以下查询查看哪些排序规则是非二进制的,并且不等同于这些字符:
A
所以:
A
。如果使用此列的大多数/所有查询都需要将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);
与Latin1_General_100_BIN2
视为不同,请继续并更改列以使用ß
。这可能需要删除以下依赖对象,然后在ss
:
提示:请务必检查列的当前NULL / NOT NULL设置,并在Latin1_General_100_BIN2
语句中指定它,以便它不会被更改。
ALTER TABLE
)仅覆盖那些具有ALTER TABLE ... ALTER COLUMN ...
子句的比较操作。只应在运营商的一方需要COLLATE
关键字,因为排序优先顺序会将其应用到另一方。有关使用字符串和排序规则的详细信息,请访问:Collations Info
答案 1 :(得分:6)
通常,BIN2
优于BIN
,您可能希望在sql排序规则上选择Windows排序规则。例如Latin1_General_100_BIN2
Guidelines for Using BIN and BIN2 Collations
使用BIN归类的指南
如果您的SQL Server应用程序与使用二进制排序规则的旧版SQL Server交互,请继续使用二进制文件。对于混合环境,二进制排序可能是更合适的选择。
出于与 BIN2排序规则有关的类似原因,除非您对维护向后兼容性行为有特定要求,否则您应该倾向于使用Windows排序规则而不是SQL Server特定的排序规则(即以SQL 开头的那些现在被认为是有点&#34; sucky&#34 ;;-))。
- @srutzky - Latin1_General_BIN performance impact when changing the database default collation
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;
返回:
+----+---+----+---+-----+-----+-----+-----+
| a | b | c | d | a=b | a=d | c=b | c=d |
+----+---+----+---+-----+-----+-----+-----+
| ss | ß | ss | ß | != | = | = | = |
+----+---+----+---+-----+-----+-----+-----+
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;
返回:
+----+---+----+---+-----+-----+-----+-----+
| a | b | c | d | a=b | a=d | c=b | c=d |
+----+---+----+---+-----+-----+-----+-----+
| ss | ß | ss | ß | != | != | != | != |
+----+---+----+---+-----+-----+-----+-----+