Zac*_*ith 7 sql-server collation sql-server-2012
我是 SQL Server 的新手,不知道 T-SQL 可能不区分大小写的可能性。
我一直在通过拆分表和约束来规范化实体。我很害怕如果我现在更改排序规则,例如,如果“不区分大小写”的外键值指向具有不同大小写的 PK 值,那么其中一些约束可能无效。
如果我在数据库上运行这个查询(在基本数据库上测试):
ALTER DATABASE <db_name>
COLLATE SQL_Latin1_General_Cp1_CS_AS ;
GO
Run Code Online (Sandbox Code Playgroud)
如果违反某些约束会发生什么?
是否有任何其他原因我应该小心进行数据库范围的更改,例如更改排序规则?
更改数据库的排序规则不会影响现有列。它会影响创建的未指定COLLATE子句(包括表变量)、字符串文字和变量值(不是变量名称解析,由实例级排序规则确定)的新非 XML 字符串列。这意味着,以下内容将受到影响:
IF (@Variable = 'string')
BEGIN
...
END;
Run Code Online (Sandbox Code Playgroud)
此更改还将影响数据库级别的元数据,例如模式名称、对象、列、索引等。意思是,以下两种情况将受到影响:
SELECT ...
FROM sys.indexes si
WHERE si.[name] = N'somename'; -- real name = SomeName
Run Code Online (Sandbox Code Playgroud)
和:
SELECT ...
FROM dbo.sometable st -- real name = SomeTable
Run Code Online (Sandbox Code Playgroud)
在这两个示例中,它们将在不区分大小写的排序规则中工作,但在区分大小写的排序规则中分别不返回任何内容或错误。
最后,正如@JonathanFite 提醒我的那样,更改 DB Collation可能会影响涉及临时表的查询。临时表(不是表变量)中字符串列的默认排序规则是默认排序规则[tempdb](应该与 相同[model],这应该是实例默认值,除非有人恢复[model]来自具有不同默认排序规则的服务器),而不是本地数据库的排序规则。意思是,即使每次都会创建临时表,因此您可能希望它们像使用新排序规则的“新创建的表”一样,但实际上它们会像“现有表”一样运行,并且会继续像之前一样运行排序规则更改。如果您需要临时表中的字符串列使用新的排序规则,则需要COLLATE DATABASE_DEFAULT在使用 using 显式设置它们的排序规则CREATE TABLE 声明。
因此,您确实需要进行大量测试!
如果要更改现有列,则需要删除现有约束,发出ALTER TABLE ... ALTER COLUMN并重新创建约束。由于排序顺序可能不同,您还需要重建使用已更改排序规则的任何列的索引。
此外,最好不要使用以SQL_. 而是使用Latin1_General_100_CS_AS. SQL_自 SQL Server 2000发布以来,以 开头的排序规则已经过时(即使没有正式弃用)。他们对VARCHAR/ 8 位数据的处理已经过时,并且不符合更新的行为。不幸的是,出于向后兼容性的原因,美国英语安装的默认排序规则曾经是SQL_Latin1排序规则,如使用 SQL Server 排序规则MSDN 页面中所述:
为了向后兼容,默认的英语 (US) 排序规则是 SQL_Latin1_General*。
这也在设置MSDN 页面的排序规则设置中的默认排序规则图表中注明(点击 Control-F 并粘贴到 中sql_latin)。我相信这个默认值从 SQL Server 2014 开始更改为 Windows 排序规则,但是文档,即使是 SQL Server 2016 设置,仍然指向排序规则的 2008 R2 设置页面。
下面是一个脚本,用于查看更改数据库排序规则时的一些行为差异:
USE [master];
GO
IF (DB_ID(N'ChangeDatabaseCollationTest') IS NULL)
BEGIN
CREATE DATABASE [ChangeDatabaseCollationTest] COLLATE Latin1_General_100_CI_AS;
END;
GO
USE [ChangeDatabaseCollationTest];
GO
-- Current DB Collation: Latin1_General_100_CI_AS
EXEC sp_help 'sys.objects';
-- Collation for [name] = Latin1_General_100_CI_AS
IF ('A' = 'a')
BEGIN
SELECT 'Case INsensitive comparison works.';
END;
ELSE
BEGIN
SELECT 'Case INsensitive comparison did NOT work.';
END;
-- Case INsensitive comparison works.
CREATE TABLE dbo.CaseTest_a (ID INT); -- success
SELECT * FROM dbo.CaseTest_A; -- success
CREATE TABLE dbo.CaseTest_A (ID INT); -- error:
-- Msg 2714, Level 16, State 6, Line 5
-- There is already an object named 'CaseTest_A' in the database.
ALTER DATABASE [ChangeCollationTest] COLLATE Latin1_General_100_CS_AS; -- success
IF ('A' = 'a')
BEGIN
SELECT 'Case INsensitive comparison works.';
END;
ELSE
BEGIN
SELECT 'Case INsensitive comparison did NOT work.';
END;
-- Case INsensitive comparison did NOT work.
SELECT * FROM dbo.CaseTest_A; -- error:
-- Msg 208, Level 16, State 1, Line 56
-- Invalid object name 'dbo.CaseTest_A'.
CREATE TABLE dbo.CaseTest_A (ID INT); -- success
EXEC sp_help 'sys.objects';
-- Collation for [name] = Latin1_General_100_CS_AS
ALTER DATABASE [ChangeCollationTest] COLLATE Latin1_General_100_CI_AS; -- error:
-- Msg 1505, Level 16, State 1, Line 23
-- The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for
-- the object name 'dbo.sysschobjs' and the index name 'nc1'. The duplicate key
-- value is (0, 1, CaseTest_A).
-- Msg 5072, Level 16, State 1, Line 23
-- ALTER DATABASE failed. The default collation of database 'ChangeCollationTest'
-- cannot be set to Latin1_General_100_CI_AS.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9996 次 |
| 最近记录: |