2014-10-01 105 views
6

阿尔特整理更改的SQL Server 2012的排序规则数据库

我需要从Latin1_General_CI_AS特定服务器上改变我们的数据库之一的整理,以SQL_Latin1_General_CP1_CI_AI使之我们的数据库的其他部分相匹配。

Alter Collation Dialog - SQL Server 2012 R2

的问题

然而,当我试图做到这一点,我得到以下错误:

ALTER DATABASE failed. The default collation of database 'XxxxxXxxxxx' cannot be set to SQL_Latin1_General_CP1_CI_AI. (Microsoft SQL Server, Error: 5075)

我的研究

我的谷歌搜索上这个话题已经揭示了一些文章ich表示我需要导出所有数据,删除数据库,使用正确的归类重新创建它,然后重新导入数据。

例如:Problem with database collation change (SQL Server 2008)

显然,这是一个显著的任务,特别是因为主外键关系必须保留,我们的数据库是相当大(超过一万个数据行)。

我的问题

有没有办法来改变现有的SQL Server 2012数据库,不需要导出和重新导入所有数据的整理?

或者,是否有一些工具或脚本可以以可靠的方式自动执行此过程?

回答

3

下对我的作品的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...).

但我只是能够更改默认排序规则,我有填充的表。在MSDN页ALTER DATABASE状态“备注”一节中,“更改数据库排序规则”下:

Before you apply a different collation to a database, make sure that the following conditions are in place:

  1. You are the only one currently using the database.

  2. 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.

所以,我建议确保数据库处于单用户模式,并且,如果你有任何这四个项目,你的:

  • 把它们
  • 更改归类
  • ,然后重新添加

BUT,此时所有已更改的都是数据库的默认排序规则。用户表(即非系统表)中任何现有列的归类仍将具有原始归类。如果您希望现有的字符串列 - CHAR,VARCHAR,NCHAR,NVARCHAR和已弃用的TEXTNTEXT - 要采用新归类,则需要单独更改每个列。而且,如果在这些列上定义了任何索引,那么这些索引将首先被删除(禁用是不够的),并在ALTER COLUMN(其他依赖会阻止ALTER COLUMN已被删除以便获得ALTER DATABASE工作)。下面的例子说明这种行为:不依赖

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上述声明完全成功更改列排序规则:

测试设置

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。

测试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, Level 16, State 9, Line 60
ALTER TABLE ALTER COLUMN ExtendedASCIIString failed because one or more objects access this column.

此外,请注意,校勘数据库范围系统目录视图中的一些字符串列(例如sys.objects,sys.columns,sys.indexes等)将更改为新的Collat​​ion。如果您的代码已连接到任何这些字符串列(即name),那么您可能会开始收到排序规则不匹配错误,直到更改用户表中连接列的排序规则为止。

+0

非常感谢研究的答案srutzky。我会试试这个。 – 2014-10-01 03:42:53

+0

如果数据库中的任何内容使用任何有问题的列,则此方法不起作用。例如,如果您有一个类似于“WHERE x = y”且x和y是varchars的SP,则由于问题(2),您无法更改排序规则。所以基本上它适用于你实际上不关心的数据库,并且对于任何真实世界都是失败的。 – 2016-07-25 16:55:33

+0

@MauryMarkowitz关于“如果你有一个类似于”WHERE x = y“和x和y是varchars的SP,你不能因为问题(2)_”而改变排序规则:“你是否尝试过并发现它不工作,或者你要根据我引用的文档说什么?因为我已经尝试过了,它确实有效。你误解了第二点。它与存储的特效无关,(N)VARCHAR列具有定义的校对。它是字符串文字,参数和系统目录表中的一些列,它们受数据库默认归类控制时会受到影响。 – 2016-07-25 18:23:33

相关问题