Tại sao các ký tự này đều bằng nhau trong SQL Server?


20

Tôi chỉ không nhận được nó. Xem truy vấn SQL này:

select nchar(65217) -- ﻁ
select nchar(65218) -- ﻂ
select nchar(65219) -- ﻃ
select nchar(65220) -- ﻄ
if nchar(65217) = nchar(65218)
    print 'equal'
if nchar(65217) = nchar(65219)
    print 'equal'
if nchar(65217) = nchar(65220)
    print 'equal'

Dựa trên mối quan hệ bắc cầu , điều đó có nghĩa là SQL Server coi tất cả chúng là cùng một ký tự.

Tuy nhiên, trong các môi trường khác, ví dụ C #, chúng không giống nhau.

Điều tôi bối rối là:

  1. Cách so sánh chuỗi hoạt động trong SQL Server
  2. Tại sao so sánh không hoạt động giống nhau trên một máy và một nền tảng, nhưng các môi trường khác nhau
  3. 4 nhân vật này đại diện cho một nhân vật dễ hiểu. Tại sao chúng rất phong phú trong bản đồ ký tự Unicode?

Điều này tất nhiên dẫn đến những vấn đề to lớn, bởi vì tôi đang làm việc trên một ứng dụng xử lý văn bản và dữ liệu đến gần như từ mọi nơi và tôi cần bình thường hóa văn bản trước khi xử lý nó.

Nếu tôi biết lý do của sự khác biệt, tôi có thể tìm một giải pháp để xử lý nó. Cảm ơn bạn.

Câu trả lời:


28

Tất cả dữ liệu ký tự trong SQL Server được liên kết với đối chiếu, xác định miền của các ký tự có thể được lưu trữ cũng như các quy tắc được sử dụng để so sánh và sắp xếp dữ liệu. Đối chiếu áp dụng cho cả dữ liệu Unicode và không Unicode.

SQL Server bao gồm 3 loại đối chiếu rộng: nhị phân, di sản và Windows. Các bộ sưu tập trong danh mục nhị phân ( _BINhậu tố) sử dụng các điểm mã cơ bản để so sánh để so sánh bằng nhau trả về không bằng nhau nếu các điểm mã khác nhau bất kể ký tự. Di sản ( SQL_tiền tố) và các đối chiếu Windows cung cấp ngữ nghĩa sắp xếp và so sánh cho các quy tắc từ điển tự nhiên hơn. Điều này cho phép so sánh để xem xét trường hợp, dấu, chiều rộng và Kana. Các đối chiếu Windows cung cấp word-sortcác quy tắc mạnh mẽ hơn , phù hợp chặt chẽ với HĐH Windows trong khi các đối chiếu kế thừa chỉ xem xét các ký tự đơn.

Ví dụ dưới đây minh họa sự khác biệt giữa Windows và đối chiếu nhị phân với ký tự Teth:

CREATE TABLE dbo.WindowsColationExample
    (
      Character1 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character2 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character3 nchar(1) COLLATE Arabic_100_CI_AS_SC
    , Character4 nchar(1) COLLATE Arabic_100_CI_AS_SC
    );

CREATE TABLE dbo.BinaryColationExample
    (
      Character1 nchar(1) COLLATE Arabic_100_BIN
    , Character2 nchar(1) COLLATE Arabic_100_BIN
    , Character3 nchar(1) COLLATE Arabic_100_BIN
    , Character4 nchar(1) COLLATE Arabic_100_BIN
    );

INSERT  INTO dbo.BinaryColationExample
VALUES  ( NCHAR(65217), NCHAR(65218), NCHAR(65219), NCHAR(65220) );
INSERT  INTO dbo.WindowsColationExample
VALUES  ( NCHAR(65217), NCHAR(65218), NCHAR(65219), NCHAR(65220) );

--all characters compare not equal
SELECT *
FROM dbo.BinaryColationExample
WHERE
    character1 = character2
    OR character1 = character3
    OR character1 = character4
    OR character2 = character3
    OR character2 = character4
    OR character3 = character4;

--all characters compare equal
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character2;
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character3;
SELECT *
FROM dbo.WindowsColationExample
WHERE character1 = character4;
SELECT *
FROM dbo.WindowsColationExample
WHERE character2 = character3;
SELECT *
FROM dbo.WindowsColationExample
WHERE character2 = character4;
SELECT *
FROM dbo.WindowsColationExample
WHERE character3 = character4;

Lý do tại sao Unicode có thể chứa các điểm mã khác nhau cho các glyph giống hệt nhau được nêu trong http://en.wikipedia.org/wiki/D repeatate_char character_in_Unicode . Tôi tóm tắt, nó có thể là để tương thích di sản hoặc các nhân vật không tương đương về mặt kinh điển. Lưu ý rằng ký tự Teth được sử dụng trong các ngôn ngữ khác nhau ( http://en.wikipedia.org/wiki/Teth ).


15

Điều này có liên quan đến COLLATIONcơ sở dữ liệu của bạn ( thêm thông tin trong BOL ).

Tôi không hoàn toàn chắc chắn về ngôn ngữ của ký tự cụ thể mà bạn gặp vấn đề (Tôi đoán tiếng Ba Tư dựa trên chuỗi này ), nhưng nếu bạn chỉ định đối chiếu chính xác trong toán tử đẳng thức, thì bạn sẽ có kết quả chính xác.

if nchar(65217) COLLATE Persian_100_BIN = nchar(65218) COLLATE Persian_100_BIN 
    print 'equal'; -- nothing returned
if nchar(65217)  COLLATE Persian_100_BIN  = nchar(65217)  COLLATE Persian_100_BIN 
    print 'equal'; -- prints 'equal'
if nchar(65217) COLLATE Latin1_General_CI_AI = nchar(65220) COLLATE Latin1_General_CI_AI
    print 'equal'; -- prints 'equal'
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.