N'Șc 'được coi là khóa trùng lặp của N'C' bằng cách sử dụng đối chiếu Latin1_General_CI_AS


11

Tôi có một bảng với một khóa duy nhất bao gồm một NVARCHAR(50)cột (đúng hay không, nhưng có). Vì vậy, khi cố gắng chèn Șchoặc C(không quan trọng thứ tự chèn), nó bị hỏng ở lần chèn thứ 2 do các vấn đề đối chiếu. Đây là lỗi:

(1 hàng bị ảnh hưởng) Msg 2601, Cấp 14, Trạng thái 1, Dòng 16 Không thể chèn hàng khóa trùng lặp trong đối tượng 'dbo.testT' với chỉ mục duy nhất 'IX_TestT'. Giá trị khóa trùng lặp là (C).

Chọn trả về:

nhập mô tả hình ảnh ở đây

Đối chiếu cơ sở dữ liệu mặc định là Latin1_General_CI_AS. Dành thời gian để tìm cách giải quyết nó, mà không thay đổi quá nhiều cấu trúc đã có, nhưng không thể tìm ra cách để làm việc. Đã thử các bộ sưu tập và kết hợp khác nhau, mọi thứ đều thất bại. Đọc ( ở đâyở đây ) về mở rộng nhân vật và như vậy, vẫn còn bị mắc kẹt. Đây là một mã mẫu mà tôi đang sử dụng để tái tạo vấn đề, vui lòng sửa đổi và đề xuất bất cứ điều gì có thể giúp giải quyết vấn đề này.

CREATE TABLE testT (
    [Default_Collation]     [NVARCHAR] (50) COLLATE DATABASE_DEFAULT,
    [Latin1_General_CI_AS]  [NVARCHAR] (50) COLLATE Latin1_General_CI_AS,
    [Latin1_General_CI_AI]  [NVARCHAR] (50) COLLATE Latin1_General_CI_AI,
    [SQL_Collation]         [NVARCHAR] (50) COLLATE SQL_Latin1_General_CP1_CI_AS);
CREATE UNIQUE CLUSTERED INDEX [IX_TestT] ON [dbo].[testT] ([Default_Collation])
ON [PRIMARY]
GO

INSERT INTO testT
SELECT  N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc'   --COLLATE Latin1_General_CI_AS

INSERT INTO testT
SELECT  N'C'    --COLLATE Latin1_General_CI_AS 
        ,N'C'   --COLLATE Latin1_General_CI_AS
        ,N'C'   --COLLATE Latin1_General_CI_AS
        ,N'C'   --COLLATE SQL_Latin1_General_CP1_CI_AS

SELECT * FROM testT;

DROP TABLE testT;

Câu trả lời:


10

Vấn đề là Bộ sưu tập SQL Server cũ (tức là những bộ có tên bắt đầu bằng SQL_ Bộ 80sưu tập Bộ sưu tập ) và hai phiên bản đầu tiên của Bộ sưu tập Windows ( bộ đi kèm với SQL Server 2000 và không có số phiên bản trong tên và 90bộ đi kèm với SQL Server 2005) đang thiếu các trọng số sắp xếp cho rất nhiều ký tự. Điều này chủ yếu được sửa chữa bắt đầu với 100loạt Collations đi kèm với SQL Server 2008.

Như bạn có thể thấy trong các ví dụ dưới đây, Șký tự khớp với một chuỗi trống khi sử dụng Collations không nhị phân, phiên bản 80 hoặc 90 (và Collations SQL Server) vì cả hai đều có cùng trọng số sắp xếp: 0. Không có gì. Nada. Điều này có nghĩa là khi so sánh N'Șc'với N'C'(sử dụng 100 Collations trước loạt), bạn thực sự so sánh N'c'với N'C'(thử nghiệm # 1):

SELECT 1 WHERE N'Șc' = N'C' COLLATE Latin1_General_CS_AS;
-- no result (due to "c" and "C" being different case)

SELECT 2 WHERE N'Ș' = N'' COLLATE SQL_Latin1_General_CP1_CI_AS;
SELECT 3 WHERE N'Ș' = N'' COLLATE Latin1_General_CI_AS;

SELECT 4 WHERE N'Ș' = N'' COLLATE Latin1_General_BIN2;
-- no result (due to "Ș" still being a code point and empty string has no code points)

SELECT 5 WHERE N'Ș' = N'' COLLATE Latin1_General_100_CI_AS;
-- no result (due to "Ș" finally having a sort weight in 100 series Collations)

SELECT 6 WHERE N'Ș' = N'' COLLATE Chinese_PRC_CI_AI;
SELECT 7 WHERE N'Ș' = N'' COLLATE Chinese_PRC_90_CI_AI;

SELECT 8 WHERE N'Ș' = N'' COLLATE Indic_General_90_CI_AI;
SELECT 9 WHERE N'Ș' = N'' COLLATE Indic_General_100_CI_AI;
-- no result (due to "Ș" finally having a sort weight in 100 series Collations)

Vì vậy, thật không may, bạn sẽ cần bỏ PK, thay đổi cột để có Collation 100 cấp (ví dụ Latin1_General_100_CI_AS_SC), sau đó tạo lại PK. Hãy lưu ý rằng sự khác biệt ở chỗ gợi ý Collation từ Collation hiện nay là cả 100 các _SCvào cuối, cho phép nó để xử lý đúng đắn các nhân vật bổ sung.

Điều này không có nghĩa là bạn cần phải:

  1. thay đổi Collations của các bảng khác (trừ khi chúng có cùng thiết lập NVARCHARtrong PK)
  2. thay đổi đối chiếu mặc định của cơ sở dữ liệu. Vấn đề chính với việc không thay đổi Collation của DB là sẽ có sự khác biệt về hành vi giữa việc thực hiện table.column = N'Ș'@variable = N'Ș'vì các biến và chuỗi ký tự sử dụng Collation mặc định của Cơ sở dữ liệu.

Để biết thêm ví dụ về hành vi này, vui lòng xem phần "Nhân vật bổ sung" của bài đăng trên blog sau đây của tôi:

Uni-Code: Tìm kiếm danh sách các ký tự hợp lệ cho mã định danh T-SQL, Phần 3 của 2 (Số nhận dạng được phân tách)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.