我需要将特定服务器上某个数据库的排序规则从latin1_General_CI_AS更改为sql_latin1_General_CP1_CI_AI,以便与其他数据库匹配.
问题
但是,当我尝试这样做时,我收到以下错误:
ALTER DATABASE Failed. The default collation of database ‘XxxxxXxxxxx’ cannot be set to sql_latin1_General_CP1_CI_AI. (Microsoft sql Server,Error: 5075)
我的研究
我在这个主题上的Google搜索显示了一些文章,这些文章表明我需要导出所有数据,删除数据库,使用正确的排序规则重新创建数据,然后重新导入数据.
例如:Problem with database collation change (SQL Server 2008)
显然这是一项重要任务,特别是因为必须保留主外键关系,并且我们的数据库非常大(超过一千万个数据行).
我的问题
有没有办法更改现有sql Server 2012数据库的排序规则,不需要导出和重新导入所有数据?
或者,是否有一些工具或脚本能够以可靠的方式自动执行此过程?
解决方法
ALTER DATABASE CURRENT COLLATE sql_latin1_General_CP1_CI_AI;
链接问题中接受的答案并不完全正确,至少不适用于sql Server 2012.它说:
Ahh,this is one of the worst problems in sql Server: you cannot change the collation once an object is created (this is true both for tables and databases…).
但我只能更改默认排序规则,并且我已经填充了表格. “备注”部分的“更改数据库归类”下的ALTER DATABASE的MSDN页面:
Before you apply a different collation to a database,make sure that the following conditions are in place:
You are the only one currently using the database.
No schema-bound object depends on the collation of the database.
If the following objects,which depend on the database collation,exist in the database,the ALTER DATABASE database_name COLLATE statement will fail. sql Server will return an error message for each object blocking the ALTER action:
user-defined functions and views created with SCHEMABINDING.
Computed columns.
CHECK constraints.
Table-valued functions that return tables with character columns with collations inherited from the default database collation.
因此,我建议确保数据库处于单用户模式,如果您有这四个项目中的任何一个,那么您:
>放下它们
>改变整理
>然后重新添加它们
但是,此时所有已更改的是数据库的默认排序规则.用户表(即非系统表)中任何现有列的排序仍将具有原始排序规则.如果希望现有字符串列(CHAR,VARCHAR,NCHAR,NVARCHAR以及不推荐使用的TEXT和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]),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],'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;
上面的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语句收到以下错误:
Msg 5074,Level 16,State 1,Line 60
The index ‘IX_ChangeCollationParent_ExtendedASCIIString’ is dependent on column ‘ExtendedASCIIString’.
Msg 4922,State 9,Line 60
ALTER TABLE ALTER COLUMN ExtendedASCIIString Failed because one or more objects access this column.
另请注意,数据库范围的系统目录视图中的某些字符串列的排序规则(例如sys.objects,sys.columns,sys.indexes等)将更改为新的排序规则.如果您的代码具有任何这些字符串列(即名称)的JOIN,那么您可能会开始获取排序规则不匹配错误,直到更改用户表中连接列的排序规则.
更新:
如果需要更改整个实例的排序规则或选项,则可以使用更简单的方法绕过所有这些限制.它没有文档,因此不受支持(因此,如果它不起作用,微软将不会提供帮助).但是,它会更改所有级别的排序规则:实例,所有数据库以及所有用户表中的所有字符串列.它通过简单地更新表的元数据等来实现这一点并避免所有典型的限制,以获得新的排序规则.然后它删除并重新创建具有字符串列的所有索引.此方法也有一些细微差别可能会产生影响,但可以修复.此方法是sqlservr.exe的-q命令行开关.我已记录了所有行为,包括通过执行如此广泛的整理更改列出所有可能受影响的区域,在以下帖子中: