Thay đổi Collation của cơ sở dữ liệu không ảnh hưởng đến các cột hiện có. Nó ảnh hưởng đến các cột chuỗi không phải XML mới được tạo mà không chỉ định COLLATE
mệnh đề (bao gồm các biến bảng), chuỗi ký tự và giá trị biến (không phải là độ phân giải tên biến, được xác định bởi Đối chiếu mức Instance). Có nghĩa, một cái gì đó như sau sẽ bị ảnh hưởng:
IF (@Variable = 'string')
BEGIN
...
END;
Thay đổi này cũng sẽ ảnh hưởng đến dữ liệu meta cấp cơ sở dữ liệu, chẳng hạn như tên của lược đồ, đối tượng, cột, chỉ mục, v.v. Ý nghĩa, hai kịch bản sau đây sẽ bị ảnh hưởng:
SELECT ...
FROM sys.indexes si
WHERE si.[name] = N'somename'; -- real name = SomeName
và:
SELECT ...
FROM dbo.sometable st -- real name = SomeTable
Trong cả hai ví dụ đó, chúng sẽ hoạt động trong Collation không phân biệt chữ hoa chữ thường, nhưng không trả lại gì hoặc lỗi tương ứng, trong Collation phân biệt chữ hoa chữ thường.
Cuối cùng, vì @JonathanFite đủ tốt bụng để nhắc nhở tôi, việc thay đổi DB Collation có thể ảnh hưởng đến các truy vấn liên quan đến các bảng tạm thời. Collation mặc định cho các cột chuỗi trong các bảng tạm thời (không phải biến bảng) là Collation mặc định cho [tempdb]
(nên giống với [model]
, đó phải là mặc định Instance, trừ khi có ai đó khôi phục[model]
từ một máy chủ có Collation mặc định khác), không phải Collation của Cơ sở dữ liệu cục bộ. Có nghĩa là, mặc dù các bảng tạm thời được tạo mỗi lần và do đó bạn có thể mong đợi chúng hoạt động như "các bảng mới được tạo" với Collation mới, nhưng thực tế chúng sẽ hoạt động như "các bảng hiện có" và sẽ tiếp tục hoạt động như trước đây sự thay đổi đối chiếu. Nếu bạn cần các cột chuỗi trong các bảng tạm thời để sử dụng Collation mới, bạn sẽ cần đặt Collation của chúng một cách rõ ràng bằng cách sử dụng COLLATE DATABASE_DEFAULT
trong các CREATE TABLE
câu lệnh.
Do đó bạn thực sự cần phải làm rất nhiều thử nghiệm!
Nếu bạn muốn thay đổi các cột hiện có thì bạn sẽ cần bỏ các ràng buộc hiện có, đưa ra ALTER TABLE ... ALTER COLUMN
và sau đó tạo lại các ràng buộc. Bạn cũng sẽ cần xây dựng lại các chỉ mục sử dụng bất kỳ cột nào có Collation thay đổi vì thứ tự sắp xếp có thể khác nhau.
Ngoài ra, tốt nhất là không sử dụng Collations bắt đầu bằng SQL_
. Thay vì sử dụng Latin1_General_100_CS_AS
. Các bộ sưu tập bắt đầu bằng SQL_
đã lỗi thời (ngay cả khi không chính thức bị từ chối) kể từ khi SQL Server 2000 được phát hành. Việc xử lý VARCHAR
dữ liệu / 8 bit của họ đã lỗi thời và không phù hợp với hành vi mới hơn. Thật không may, vì lý do tương thích ngược, Collation mặc định cho các bản cài đặt tiếng Anh Mỹ được sử dụng là SQL_Latin1
Collations, như đã lưu ý trong trang MSDN của SQL Server Collations :
Để tương thích ngược, đối chiếu ngôn ngữ tiếng Anh (Hoa Kỳ) mặc định là SQL_Latin1_General *.
Điều này cũng được ghi chú trong biểu đồ Đối chiếu mặc định trong Cài đặt đối chiếu trong trang Cài đặt MSDN (nhấn Control-F và dán vào sql_latin
). Tôi tin rằng mặc định này đã thay đổi thành Windows Collation bắt đầu trong SQL Server 2014, nhưng tài liệu, ngay cả đối với thiết lập SQL Server 2016, vẫn trỏ đến trang thiết lập 2008 R2 cho Collations.
Dưới đây là tập lệnh để xem một số khác biệt về hành vi khi thay đổi Đối chiếu của Cơ sở dữ liệu:
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.