Kra*_*ram 22 sql sql-server collation
我们有一个遗留数据库,其中一些(较旧的)列使用"SQL_Latin1_General_CP1_CI_AS",最近的更改使用了"Latin1_General_CI_AS".
这是一个痛苦,因为连接需要额外的COLLATE语句才能工作.
我想把所有内容都改为"Latin1_General_CI_AS".从我可以收集的内容来看,它们或多或少是相同的排序规则,在此过程中我不会丢失数据......
有谁知道是否是这种情况?
Zar*_*eth 31
这是一个更完整的答案:
这些排序规则之间的关键区别在于它们如何应用字符扩展规则.某些拉丁字符可能会扩展为多个字符.在处理非Unicode文本时,SQL_xxxx排序规则可能会忽略这些字符扩展,但会将它们应用于unicode文本.因此:当使用一个排序规则与另一个排序规则时,连接,排序和比较可能会返回不同的结果.
例:
在Latin1_General_CI_AS
这两个语句下返回相同的记录集,ß
扩展为ss
.
SELECT * FROM MyTable3 WHERE Comments = 'strasse'
SELECT * FROM MyTable3 WHERE Comments = 'straße'
Run Code Online (Sandbox Code Playgroud)
当使用SQL_Latin1_General_CP1_CI_AS
上述语句时返回不同的记录,因为它ß
被视为不同的字符ss
.
Sol*_*zky 24
如果您要更改数据库的排序规则,那么您肯定应该了解一些内容,以便您可以相应地进行规划:
关于数据丢失的可能性:
NVARCHAR
字段都是Unicode,它是单个字符集,因此这些字段不会有任何数据丢失(这也包括也存储为UTF-16 Little Endian的XML字段).存储对象/列/索引/等名称的元数据字段NVARCHAR
都不需要担心这些.VARCHAR
具有不同排序规则但不同排序规则之间相同代码页的字段不会成为问题,因为代码页是字符集.VARCHAR
具有不同排序规则并移动到不同代码页的字段(更改排序规则时)如果新代码页中未显示任何正在使用的字符,则可能会丢失数据.但是,这只是在物理上更改特定字段的排序规则(如下所述)时的问题,并且在更改数据库的默认排序规则时不会发生.局部变量和字符串文字从数据库默认值中获取其排序规则.更改数据库缺省值将更改用于本地变量和字符串文字的排序规则.但是,更改数据库的默认排序规则不会更改用于该数据库中表中现有字符串列的排序规则.在将列与文字和/或变量进行比较或连接时,这通常不会导致任何问题,因为文字和变量将由于排序优先顺序而采用列的排序规则.唯一可能的问题是代码页转换可能发生在128到255之间的值的字符,这些字符在列的排序规则使用的代码页中不可用.
如果您希望某个列的谓词/比较/排序/连接/等在更改数据库的默认排序规则时表现不同,则需要使用以下命令显式更改该列的排序规则:
ALTER TABLE [{table_name}]
ALTER COLUMN [{column_name}]
{same_datatype}
{same_NULL_or_NOT NULL_setting}
COLLATE {name_of_Database_default_Collation};
Run Code Online (Sandbox Code Playgroud)
请务必指定当前正在使用的完全相同的数据类型和NULL
/ NOT NULL
设置,否则如果它们不是默认值,它们可以恢复为默认值.之后,如果任何字符串列上的任何索引刚刚更改了其排序规则,那么您需要重建这些索引.
更改数据库的默认排序规则将改变某些特定数据库的元数据的整理,如name
在这两个领域sys.objects
,sys.columns
,sys.indexes
,等过滤对局部变量或字符串文字,这些制度的意见将不会是一个问题,因为整理会双方都在变化.但是,如果将任何本地系统视图连接到字符串字段上的临时表,并且本地数据库之间的数据库级排序规则tempdb
不匹配,则会出现"排序规则不匹配"错误.下面将讨论这一问题以及补救措施.
这两个Collations之间的一个区别在于它们如何为VARCHAR
数据排序某些字符(这不会影响NVARCHAR
数据).非EBCDIC SQL_
Collations对VARCHAR
数据使用所谓的"String Sort" ,而所有其他Collations,甚至NVARCHAR
非EBCDIC SQL_
Collations的数据都使用所谓的"Word Sort".不同之处在于,在"单词排序"中,短划线-
和撇号'
(可能还有一些其他字符?)的权重非常低,除非字符串中没有其他差异,否则基本上会被忽略.要查看此行为,请运行以下命令:
DECLARE @Test TABLE (Col1 VARCHAR(10) NOT NULL);
INSERT INTO @Test VALUES ('aa');
INSERT INTO @Test VALUES ('ac');
INSERT INTO @Test VALUES ('ah');
INSERT INTO @Test VALUES ('am');
INSERT INTO @Test VALUES ('aka');
INSERT INTO @Test VALUES ('akc');
INSERT INTO @Test VALUES ('ar');
INSERT INTO @Test VALUES ('a-f');
INSERT INTO @Test VALUES ('a_e');
INSERT INTO @Test VALUES ('a''kb');
SELECT * FROM @Test ORDER BY [Col1] COLLATE SQL_Latin1_General_CP1_CI_AS;
-- "String Sort" puts all punctuation ahead of letters
SELECT * FROM @Test ORDER BY [Col1] COLLATE Latin1_General_100_CI_AS;
-- "Word Sort" mostly ignores dash and apostrophe
Run Code Online (Sandbox Code Playgroud)
返回:
String Sort
-----------
a'kb
a-f
a_e
aa
ac
ah
aka
akc
am
ar
Run Code Online (Sandbox Code Playgroud)
和:
Word Sort
---------
a_e
aa
ac
a-f
ah
aka
a'kb
akc
am
ar
Run Code Online (Sandbox Code Playgroud)
虽然你将"失去""字符串排序"行为,但我不确定我会称之为"特征".这种行为被认为是不合需要的(事实证明它没有被提到任何Windows排序规则中).然而,这是两个归类(再次,只是为了非EBCDIC之间的行为的一定的差异VARCHAR
数据),并且可能必须基于"字符串排序"行为的代码和/或客户的期望.这需要测试您的代码并可能进行研究,以确定这种行为变化是否会对用户产生任何负面影响.
SQL_Latin1_General_CP1_CI_AS
和之间的另一个区别Latin1_General_100_CI_AS
是能够对数据进行扩展VARCHAR
(NVARCHAR
数据已经可以为大多数SQL_
Collations 执行这些操作),例如处理æ
就好像ae
:
IF ('æ' COLLATE SQL_Latin1_General_CP1_CI_AS =
'ae' COLLATE SQL_Latin1_General_CP1_CI_AS)
BEGIN
PRINT 'SQL_Latin1_General_CP1_CI_AS';
END;
IF ('æ' COLLATE Latin1_General_100_CI_AS =
'ae' COLLATE Latin1_General_100_CI_AS)
BEGIN
PRINT 'Latin1_General_100_CI_AS';
END;
Run Code Online (Sandbox Code Playgroud)
返回:
Latin1_General_100_CI_AS
Run Code Online (Sandbox Code Playgroud)
你在这里"失败"的唯一一件事就是无法进行这些扩展.一般来说,这是迁移到Windows排序规则的另一个好处.但是,就像"字符串排序"到"字排序"移动一样,同样谨慎适用:它是两个排序规则之间行为的明确差异(同样,仅用于VARCHAR
数据),并且您可能有代码和/或客户基于没有这些映射的期望.这需要测试您的代码并可能进行研究,以确定这种行为变化是否会对用户产生任何负面影响.
(首先在@ Zarepheth的答案中注明并在此处扩展)
另一个区别(也就是移动到Windows排序规则的好处)是过滤VARCHAR
在NVARCHAR
文字/变量/列上编制索引的列,您将不再使VARCHAR
列上的索引无效.这是由于Windows Collations对两者VARCHAR
和NVARCHAR
数据使用相同的Unicode排序和比较规则.由于两种类型之间的排序顺序相同,因此当VARCHAR
数据转换为NVARCHAR
(由于数据类型优先级而显式或隐式)时,索引中的项的顺序仍然有效.有关此行为的更多详细信息,请参阅我的帖子:混合VARCHAR和NVARCHAR类型时对索引的影响.
服务器级Collation用于设置系统数据库的排序规则,其中包括[model]
.该[model]
数据库作为模板来创建新的数据库,其中包括[tempdb]
在每个服务器启动.因此,如果数据库的默认排序规则与实例的默认排序规则不匹配,并且您将本地表连接到字符串字段上的临时表,则会出现排序规则不匹配错误.幸运的是,有一种简单的方法可以纠正CREATE #TempTable
执行时"当前"的数据库之间的整理差异[tempdb]
.创建临时表时,使用COLLATE
子句声明排序规则(在字符串列上)并使用特定排序规则(如果您知道数据库将始终使用该排序规则),或者DATABASE_DEFAULT
(如果您不总是知道排序规则)此代码将执行的DB):
CREATE TABLE #Temp (Col1 NVARCHAR(40) COLLATE DATABASE_DEFAULT);
Run Code Online (Sandbox Code Playgroud)
这对于表变量不是必需的,因为它们从"当前"数据库获得其默认排序规则.但是,如果您同时拥有表变量和临时表并将它们连接到字符串字段,那么您将需要使用COLLATE {specific_collation}
或COLLATE DATABASE_DEFAULT
如上面所示.
服务器级排序规则还控制本地变量名称,CURSOR
变量名称和GOTO
标签.虽然这些问题都不会受到本课题所涉及的具体变化的影响,但至少应该注意一些事项.
如果有多个版本可用,最好使用所需归类的最新版本.从SQL Server 2005开始,引入了"90"系列的排序规则,SQL Server 2008引入了"100"系列排序规则.您可以使用以下查询找到这些排序规则:
SELECT * FROM sys.fn_helpcollations() WHERE [name] LIKE N'%[_]90[_]%'; -- 476
SELECT * FROM sys.fn_helpcollations() WHERE [name] LIKE N'%[_]100[_]%'; -- 2686
Run Code Online (Sandbox Code Playgroud)此外,虽然这个问题询问不区分大小写的排序规则,但应注意的是,如果别人正在做一个类似的变化,但使用区分大小写的排序规则,则SQL Server排序规则和Windows排序规则的另一个区别,对于VARCHAR
唯一的数据,是哪种情况先排序.这意味着,如果您同时拥有A
和a
,则SQL_
Collations将A
在之前排序a
,而非SQL_
Collations(以及SQL_
处理NVARCHAR
数据时的Collations )将a
在之前排序A
.
有关更改数据库或整个实例的排序规则的更多信息和详细信息,请参阅我的帖子:
更改所有用户数据库中的实例,数据库和所有列的排序规则:可能出错的原因是什么?
dun*_*nos 15
这个MSDN论坛有更多信息:
哪个州:
如果排序规则是SQL_Latin1_General_CP1_CI_AS或Latin1_General_CI_AS,您应该看到的区别很小,但两者都有比其他更快或更慢的实例.
Latin1_General_CI_AS: - Latin1-一般,不区分大小写,区分重音,不区分kanatype,宽度不敏感
SQL_Latin1_General_CP1_CI_AS: - Latin1-常规,不区分大小写,区分重音,对kanatype不敏感,对Unicode数据不区分宽度,对于非Unicode数据,在代码页1252上的SQL Server排序顺序52
因此,在我看来,你不应该看到差别,特别是如果你的数据只是a-z0-9
SELECT * FROM ::fn_helpcollations()
WHERE name IN (
'SQL_Latin1_General_CP1_CI_AS',
'Latin1_General_CI_AS'
)
Run Code Online (Sandbox Code Playgroud)
...给...
Latin1_General_CI_AS:Latin1-一般,不区分大小写,区分重音,不区分kanatype,宽度不敏感
SQL_Latin1_General_CP1_CI_AS:Latin1-常规,不区分大小写,区分重音,对kanatype不敏感,对Unicode数据不区分宽度,对于非Unicode数据,SQL Server在代码页1252上排序52
所以从这里,我推断使用的代码页是相同的(Latin1-General => 1252),所以你应该不会遇到数据丢失 - 如果有什么要改变转换后它可能是排序顺序 - 这是可能无关紧要.