以下内容适用于 SQL Server 2012:
ALTER DATABASE CURRENT COLLATE SQL_Latin1_General_CP1_CI_AI;
链接问题中接受的答案并不完全正确,至少对于 SQL Server 2012 来说不正确。它说:
啊,这是 SQL Server 中最严重的问题之一:一旦创建了对象,就无法更改排序规则(对于表和数据库都是如此......)。
但我只能更改默认排序规则,并且我有已填充的表。 MSDN 页面修改数据库 http://technet.microsoft.com/en-us/library/ms174269(v=sql.110).aspx在“备注”部分的“更改数据库排序规则”下指出:
在将不同的排序规则应用于数据库之前,请确保满足以下条件:
您是当前唯一使用该数据库的人。
-
模式绑定对象不依赖于数据库的排序规则。
如果数据库中存在以下依赖于数据库排序规则的对象,则 ALTER DATABASE数据库名称COLLATE 语句将失败。 SQL Server 将为每个阻止 ALTER 操作的对象返回一条错误消息:
因此,我建议确保数据库处于单用户模式,并且如果您有这四个项目中的任何一个,则:
BUT,此时所有已更改的是数据库的默认排序规则。用户表(即非系统表)中任何现有列的排序规则仍将具有原始排序规则。如果您想要现有的字符串列--CHAR
, VARCHAR
, NCHAR
, NVARCHAR
,以及已弃用的TEXT
and NTEXT
-- 要采用新的排序规则,您需要单独更改每一列。并且,如果在这些列上定义了任何索引,则需要首先删除这些索引(禁用还不够),然后在ALTER COLUMN
(会阻止的其他依赖项ALTER COLUMN
为了获得ALTER DATABASE
上班)。下面的示例说明了这种行为:
测试设置
USE [tempdb];
SET NOCOUNT ON;
CREATE TABLE dbo.ChangeCollationParent
(
[ChangeCollationParentID] INT NOT NULL IDENTITY(1, 1)
CONSTRAINT [PK_ChangeCollationParent] PRIMARY KEY,
ExtendedASCIIString VARCHAR(50) COLLATE Latin1_General_CI_AS NULL,
UnicodeString NVARCHAR(50) COLLATE Latin1_General_CI_AS NULL
);
CREATE TABLE dbo.ChangeCollationChild
(
[ChangeCollationChildID] INT NOT NULL IDENTITY(1, 1)
CONSTRAINT [PK_ChangeCollationChild] PRIMARY KEY,
[ChangeCollationParentID] INT NULL
CONSTRAINT [FK_ChangeCollationChild_ChangeCollationParent] FOREIGN KEY
REFERENCES dbo.ChangeCollationParent([ChangeCollationParentID]),
ExtendedASCIIString VARCHAR(50) COLLATE Latin1_General_CI_AS NULL,
UnicodeString NVARCHAR(50) COLLATE Latin1_General_CI_AS NULL
);
INSERT INTO dbo.ChangeCollationParent ([ExtendedASCIIString], [UnicodeString])
VALUES ('test1' + CHAR(200), N'test1' + NCHAR(200));
INSERT INTO dbo.ChangeCollationParent ([ExtendedASCIIString], [UnicodeString])
VALUES ('test2' + CHAR(170), N'test2' + NCHAR(170));
INSERT INTO dbo.ChangeCollationChild
([ChangeCollationParentID], [ExtendedASCIIString], [UnicodeString])
VALUES (1, 'testA ' + CHAR(200), N'testA ' + NCHAR(200));
INSERT INTO dbo.ChangeCollationChild
([ChangeCollationParentID], [ExtendedASCIIString], [UnicodeString])
VALUES (1, 'testB ' + CHAR(170), N'testB ' + NCHAR(170));
SELECT * FROM dbo.ChangeCollationParent;
SELECT * FROM dbo.ChangeCollationChild;
测试 1:更改没有依赖关系的列排序规则
ALTER TABLE dbo.ChangeCollationParent
ALTER COLUMN [ExtendedASCIIString] VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL;
ALTER TABLE dbo.ChangeCollationParent
ALTER COLUMN [UnicodeString] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL;
ALTER TABLE dbo.ChangeCollationChild
ALTER COLUMN [ExtendedASCIIString] VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL;
ALTER TABLE dbo.ChangeCollationChild
ALTER COLUMN [UnicodeString] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AI NULL;
SELECT * FROM dbo.ChangeCollationParent;
SELECT * FROM dbo.ChangeCollationChild;
The ALTER COLUMN
上述语句成功完成。
测试 2:更改具有依赖关系的列排序规则
-- First, create an index:
CREATE NONCLUSTERED INDEX [IX_ChangeCollationParent_ExtendedASCIIString]
ON dbo.ChangeCollationParent ([ExtendedASCIIString] ASC);
-- Next, change the Collation back to the original setting:
ALTER TABLE dbo.ChangeCollationParent
ALTER COLUMN [ExtendedASCIIString] VARCHAR(50) COLLATE Latin1_General_CI_AS NULL;
这一次,ALTER COLUMN
声明收到以下错误:
消息 5074,16 级,状态 1,第 60 行
索引“IX_ChangeCollationParent_ExtendedASCIIString”依赖于列“ExtendedASCIIString”。
消息 4922,16 级,状态 9,第 60 行
ALTER TABLE ALTER COLUMN ExtendedASCIIString 失败,因为一个或多个对象访问此列。
ALSO,请注意,数据库范围的系统目录视图中某些字符串列的排序规则(例如sys.objects
, sys.columns
, sys.indexes
等)将更改为新的排序规则。如果您的代码具有与任何这些字符串列的联接(即name
),那么您可能会开始收到排序规则不匹配错误,直到您更改用户表中连接列的排序规则。
UPDATE:
如果更改整个实例的排序规则是您的愿望或选择,那么有一种更简单的方法可以绕过所有这些限制。它没有文档记录,因此不受支持(所以如果它不起作用,微软不会提供帮助)。但是,它会更改所有级别的排序规则:实例、所有数据库以及所有用户表中的所有字符串列。它通过简单地更新表的元数据等来获得新的排序规则来做到这一点,并避免所有典型的限制。然后,它删除并重新创建具有字符串列的所有索引。此方法还有一些细微差别,可能会产生影响,但可以修复。这个方法是-q
命令行开关sqlservr.exe
。我在以下帖子中记录了所有行为,包括通过进行如此广泛的排序规则更改来列出所有可能受影响的区域:
更改实例、数据库和所有用户数据库中所有列的排序规则:可能会出现什么问题? https://sqlquantumleap.com/2018/06/11/changing-the-collation-of-the-instance-and-all-columns-across-all-user-databases-what-could-possibly-go-wrong/