2009-12-10 27 views
31

Gần đây, chúng tôi đã chuyển cơ sở dữ liệu của chúng tôi từ máy chủ SQL Server 2005 sang máy chủ SQL Server 2008 của chúng tôi. Mọi thứ chuyển động tốt đẹp, tuy nhiên bây giờ chúng tôi nhận thấy rằng chúng tôi đang nhận được xung đột đối chiếu. Máy chủ cũ có một collation khác với máy chủ mới.Cập nhật Collation của tất cả các trường trong cơ sở dữ liệu khi đang bay

Bây giờ bảng của chúng tôi được tạo trước khi di chuyển là một đối chiếu và những bảng được tạo sau đó là một đối chiếu khác.

Có cách nào để cập nhật các bảng/cột với collation cũ để collation mới?

Tôi hiểu việc thiết lập collation cơ sở dữ liệu/máy chủ mặc định không sửa đổi bất kỳ bảng hiện có nào (link). Tôi thực sự không muốn tạo lại cơ sở dữ liệu nếu tôi không phải làm vậy.

Bất kỳ trợ giúp nào thực sự đánh giá cao.

CẬP NHẬT

Thanks for guys giúp đỡ của bạn, cuối cùng đã nhận nó làm việc.

Để tham khảo trong tương lai, đây là kịch bản cuối cùng của tôi:

SELECT 'ALTER TABLE [' + SYSOBJECTS.Name + '] ALTER COLUMN [' + SYSCOLUMNS.Name + '] ' + 
SYSTYPES.name + 
    CASE systypes.NAME 
    WHEN 'text' THEN ' ' 
    ELSE 
    '(' + RTRIM(CASE SYSCOLUMNS.length 
    WHEN -1 THEN 'MAX' 
    ELSE CONVERT(CHAR,SYSCOLUMNS.length) 
    END) + ') ' 
    END 

    + ' ' + ' COLLATE Latin1_General_CI_AS ' + CASE ISNULLABLE WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END 
    FROM SYSCOLUMNS , SYSOBJECTS , SYSTYPES 
    WHERE SYSCOLUMNS.ID = SYSOBJECTS.ID 
    AND SYSOBJECTS.TYPE = 'U' 
    AND SYSTYPES.Xtype = SYSCOLUMNS.xtype 
    AND SYSCOLUMNS.COLLATION IS NOT NULL 
    AND NOT (sysobjects.NAME LIKE 'sys%') 
    AND NOT (SYSTYPES.name LIKE 'sys%') 
    GO 

Đây là site có chứa các kịch bản tôi dựa trên. Tôi đã phải tinh chỉnh nó để làm cho nó hoạt động chính xác.

+1

Russell, bạn nên đưa ra giải pháp cho câu trả lời! –

+0

Cảm ơn Philipp, dù sao thì đó cũng là câu hỏi hàng đầu, và OMG Ponies đã giúp tôi đạt được điều đó. :) – Russell

Trả lời

6

Bạn có thể thay đổi collation của bất kỳ mới đối tượng được tạo trong cơ sở dữ liệu người dùng bằng cách sử dụng mệnh đề COLLATE của câu lệnh ALTER DATABASE. Câu lệnh này không không thay đổi đối chiếu các cột trong bất kỳ bảng do người dùng xác định hiện có nào. Chúng có thể được thay đổi bằng cách sử dụng mệnh đề COLLATE của ALTER TABLE.

tham khảo: Setting and Changing the Database Collation

Nếu có quá nhiều cột, bạn có thể lặp qua SYS.COLUMNS để áp dụng các TABLE ALTER.

+1

Vâng đó không phải là vấn đề của tôi, vấn đề của tôi là với các cột hiện có. – Russell

+0

Đó là lý do tại sao dòng cuối cùng nói để sử dụng 'ALTER TABLE' –

+0

Đó không phải là một tùy chọn vì có quá nhiều trường để thực hiện việc này. – Russell

2

Một tùy chọn là sử dụng một chương trình như So sánh SQL Cổng Đỏ (Tôi cũng chắc chắn có những người khác). Với nó, bạn có thể tạo các tập tin kịch bản cho lược đồ của bạn với collation bao gồm (hãy chắc chắn để bật nó trong các tùy chọn), sau đó thực hiện tìm kiếm/thay thế trong các tập tin cập nhật nó vào collation mới, sau đó so sánh chúng trở lại thực tế của bạn cơ sở dữ liệu.

Tại thời điểm này, SQL Compare sẽ có thể áp dụng những thay đổi đó (hoặc lưu thay đổi vào tệp tập lệnh nếu bạn muốn) và tất cả các cột hiện tại của bạn đều được sửa.

Về lý thuyết, bạn có thể thực hiện tất cả điều này trong khi vẫn đang trong giai đoạn dùng thử, mặc dù tôi khuyên bạn nên sử dụng công cụ tốt để làm cho nhiều tác vụ SQL dễ dàng hơn!

+0

So sánh Redgate là một công cụ tuyệt vời để sử dụng quá. : D – Russell

10

Chỉ trong trường hợp bất cứ ai nhìn vào này được sử dụng SQL server 2008, tôi đã phải thực hiện một vài thay đổi:

SELECT 'ALTER TABLE [' + sys.objects.name + '] ALTER COLUMN [' 
+ sys.columns.name + '] ' + sys.types.name + 
    CASE sys.types.name 
    WHEN 'text' THEN ' ' 
    ELSE 
    '(' + RTRIM(CASE sys.columns.max_length 
    WHEN -1 THEN 'MAX' 
    ELSE CONVERT(CHAR,sys.columns.max_length) 
    END) + ') ' 
    END 

    + ' ' + ' COLLATE Latin1_General_BIN ' + CASE sys.columns.is_nullable WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END 
    FROM sys.columns , sys.objects , sys.types 
    WHERE sys.columns.object_id = sys.objects.object_id 
    AND sys.objects.TYPE = 'U' 
    AND sys.types.system_type_id = sys.columns.system_type_id 
    AND sys.columns.collation_name IS NOT NULL 
    AND NOT (sys.objects.NAME LIKE 'sys%') 
    AND NOT (sys.types.name LIKE 'sys%') 
+0

Cảm ơn lời khuyên. Điều gì đã thay đổi? Tôi đã sử dụng kịch bản trên trên SQL Server 2008.: D – Russell

+1

Điều này sử dụng sys.columns thay vì SYSCOLUMNS – edosoft

+0

sau đó làm thế nào bạn sẽ lặp lại điều này và thực thi các câu lệnh? – Chagbert

4

Làm thế nào về:

DECLARE @collation NVARCHAR(64) 
SET @collation = 'Latin1_General_CI_AS' 

SELECT 
    'ALTER TABLE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] ' 
    + 'ALTER COLUMN [' + COLUMN_NAME + '] ' 
    + DATA_TYPE + '(' + CASE CHARACTER_MAXIMUM_LENGTH 
     WHEN -1 THEN 'MAX' 
     ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) END + ') ' 
    + 'COLLATE ' + @collation + ' ' 
    + CASE WHEN IS_NULLABLE = 'NO' THEN 'NOT NULL' ELSE 'NULL' END 
FROM INFORMATION_SCHEMA.columns 
WHERE COLLATION_NAME IS NOT NULL 
AND COLLATION_NAME <> @collation 
+1

'AND TABLE_NAME IN (SELECT TABLE_NAME từ information_schema.tables WHERE table_type = 'BASE TABLE')' – danihp

3

Để khắc phục vấn đề này, bạn cần sức mạnh lửa nhiều hơn sau đó kịch bản này cung cấp.Tôi đã thử kịch bản và gặp sự cố với các đối tượng phụ thuộc không thể cập nhật: chỉ mục, khóa và thủ tục. Giải pháp cuối cùng chỉ mất 5 phút với ứng dụng mã dự án này. Ứng dụng nói rằng đó là cho Sql Server 2000 nhưng tôi sử dụng nó thành công với 2008.

http://www.codeproject.com/Articles/12753/SQL-Server-2000-Collation-Changer

Tôi không thể nhấn mạnh điều này. BACKUP DATABASE CỦA BẠN. Tôi đã phải sử dụng bản sao lưu của mình ba lần để hoàn thành nhiệm vụ này.

-3

Mã không tính đến các byte đôi NText, NChar và NVarchar. Nếu bạn có NText nó sẽ thất bại với Ntext (16) không thể thiết lập kích thước trên NText.

Đối NCHAR và nvarchar nó tăng gấp đôi chiều dài, bởi vì nó không phân chia kích thước bằng 2.

Một chi tiết nhỏ Quirky, là đối với nvarchar ít nhất, -1 không phải là MAX, nhưng 0 được.

Đây là một hack rất rất xấu xí trên mã, chỉ để minh họa cho vấn đề:

ALTER TABLE [BlanketBruger] ALTER COLUMN [BrugerNavn] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BlanketBruger] ALTER COLUMN [BrugerFuldNavn] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [blanketgruppe] ALTER COLUMN [GruppeNavn] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [blanketSerie] ALTER COLUMN [SerieTitel] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [blanketSerie] ALTER COLUMN [SerieAlias] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [FormUse] ALTER COLUMN [HostName] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [value1] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [value2] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [ip] varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [username] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [gruppenavn] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [scriptname] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [querystring] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [useragent] nvarchar(400) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [sessionid] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BackendLog] ALTER COLUMN [htmlcontent] nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [value1] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [value2] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [ip] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [querystring] nvarchar(1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [useragent] nvarchar(400) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [frontendlog] ALTER COLUMN [sessionid] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [log4net] ALTER COLUMN [Thread] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Level] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Logger] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Message] text COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [log4net] ALTER COLUMN [Exception] varchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [log4net] ALTER COLUMN [Server] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Server] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Thread] varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Level] varchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [OioSamlLog] ALTER COLUMN [Message] varchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileContentIdentifier] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileContent] ntext COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
ALTER TABLE [BlanketSubmitTemp] ALTER COLUMN [FileName] nvarchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
+0

mã truy vấn thực tế sẽ hữu ích hơn so với kết quả ví dụ; chúng tôi không thể nói rằng bất kỳ cột nvarchar nào có kích thước gấp đôi .. –

0

Được rồi tôi đã viết lại mã bằng cách edosoft và đặt nó trong một vòng lặp để thực hiện những điều khoản T-SQL thực tế .

-- **************** BEGIN INPUT ********************** 
USE [YourDBName] 

DECLARE @collation NVARCHAR(128) 
-- enter you collation name below 
SET @collation = N'Latin1_General_CI_AS' 
-- **************** END INPUT ************************ 

-- **************** BEGIN LOGIC ********************** 
DECLARE @sqlCode VARCHAR(2048) 

DECLARE myCursor CURSOR LOCAL FOR 
    SELECT 'ALTER TABLE [' + sys.objects.name + '] 
     ALTER COLUMN ['+ sys.columns.name + '] ' + sys.types.name + 
     CASE sys.types.name 
      WHEN 'text' THEN ' ' 
      WHEN 'ntext' THEN ' ' 
      ELSE '(' + RTRIM(
       CASE 
        WHEN sys.columns.max_length = -1 THEN 'MAX' 
        WHEN sys.columns.max_length > 4000 THEN 'MAX' 
        ELSE CONVERT(CHAR,sys.columns.max_length) 
       END) + ')' 
     END 
     + ' COLLATE ' + @collation + CASE sys.columns.is_nullable WHEN 0 THEN ' NOT NULL' ELSE ' NULL' END 
     FROM sys.columns , sys.objects , sys.types 
     WHERE sys.columns.object_id = sys.objects.object_id 
      AND sys.objects.TYPE = 'U' 
      AND sys.types.system_type_id = sys.columns.system_type_id 
      AND sys.columns.collation_name IS NOT NULL 
      AND sys.columns.collation_name <> @collation 
      AND NOT (sys.objects.NAME LIKE 'sys%') 
      AND NOT (sys.types.name LIKE 'sys%') 

OPEN myCursor 
FETCH NEXT FROM myCursor INTO @sqlCode 

WHILE @@FETCH_STATUS = 0 BEGIN 
    PRINT 'Executing: ' + @sqlCode 
    BEGIN TRY 
     EXEC(@sqlCode); 
     PRINT 'Done!' + CHAR(10) 
    END TRY 
    BEGIN CATCH 
     PRINT 'Error: ' + ERROR_MESSAGE() + CHAR(10) 
    END CATCH 
    FETCH NEXT FROM myCursor INTO @sqlCode 
END 

PRINT 'Finished!' 
-- **************** END LOGIC ********************** 

Nếu bạn gặp lỗi tương tự như "Không thể tạo hàng có kích thước 8075 lớn hơn kích thước hàng tối đa cho phép 8060". Xây dựng lại bảng mà bạn đang gặp lỗi và chạy lại tập lệnh trên.

ALTER TABLE [dbo].[YourTableName] REBUILD 
Các vấn đề liên quan