Dịch tự động khi chuyển đổi Unicode sang không Unicode / NVARCHAR sang VARCHAR


8

Mã Unicode 9619 là một ký tự gọi là "Bóng tối": ( http://unicode-table.com/en/search/?q=9619 ).

Sử dụng SQL_Latin1_General_CP1_CI_ASđối chiếu và trang mã 1252, tôi hy vọng rằng việc truyền / chuyển đổi ký tự Unicode đó sang loại dữ liệu không phải là Unicode sẽ dẫn đến một dấu hỏi ( ?) vì trang mã 1252 dường như không chứa ký tự này và điều này dường như là của SQL Server hành vi khi chuyển đổi không thể diễn ra.

Vì vậy, câu hỏi của tôi là: tại sao SQL Server chuyển đổi ký tự này thành mã ASCII 166 là "Đường ống, thanh dọc bị hỏng" : ¦?

SELECT NCHAR(9619), CAST(NCHAR(9619) AS CHAR(1)), ASCII(CAST(NCHAR(9619) AS CHAR(1)))

3
SQL Server sử dụng cái mà bài báo này gọi là phép biến đổi homoglyphic và thường chuyển đổi các ký tự không thể được biểu diễn thành gần tương đương. Chẳng hạn như mất dấu vào một ký tự hoặc thay đổi dấu ngoặc kép thông minh thành dấu ngoặc kép. Tôi đồng ý rằng mặc dù không nhìn rất gần! Tôi không chắc chắn nếu hoặc nơi các biến đổi này được ghi lại.
Martin Smith

Wow, không có ý kiến ​​gì ... trời ạ, có vẻ như không đúng ... nó không giống nhân vật. Tại sao không chỉ là "... ôi, không có ký tự nào được tìm thấy trong trang mã này ..." và không chuyển đổi?
Henry Lee

1
Chỉ cần đọc trang này và nhớ điều này. Không chắc chắn nếu SQL Server sử dụng chính xác các thuật toán "phù hợp nhất".
Martin Smith

1
@MartinSmith liên quan đến việc không chắc chắn về ánh xạ "phù hợp nhất" cho SQL Server, vui lòng xem câu trả lời của tôi dưới đây khi tôi tìm thấy các ánh xạ đó :-).
Solomon Rutzky

Câu trả lời:


8

Tại sao SQL chuyển đổi Unicode 9619 sang mã ASCII 166?

SQL Server không sử dụng bất kỳ logic tùy chỉnh đặc biệt nào ở đây; nó đang sử dụng các dịch vụ hệ điều hành tiêu chuẩn để thực hiện chuyển đổi.

Cụ thể, loại SQL Server và dịch vụ biểu thức ( sqlTsEs) gọi vào thường trình hệ điều hành WideCharToMultiBytetrong kernel32.dll. SQL Server đặt các tham số đầu vào WideCharToMultiBytesao cho thường trình thực hiện 'dịch nhanh'. Điều này nhanh hơn yêu cầu sử dụng một ký tự mặc định cụ thể khi không có bản dịch trực tiếp.

Bản dịch nhanh dựa vào trang mã đích để thực hiện ánh xạ phù hợp nhất cho bất kỳ ký tự chưa từng có nào, như được đề cập trong liên kết Martin Smith cung cấp trong một nhận xét cho câu hỏi:

Các chiến lược phù hợp nhất khác nhau cho các trang mã khác nhau và chúng không được ghi lại chi tiết.

Khi các tham số đầu vào được đặt để dịch nhanh, hãy WideCharToMultiBytegọi dịch vụ HĐH GetMBNoDefault( nguồn ). Kiểm tra ngăn xếp cuộc gọi SQL Server khi thực hiện chuyển đổi được chỉ định trong câu hỏi xác nhận điều này:

Theo dõi ngăn xếp SQL Server


7

Chuyển đổi từ dữ liệu Unicode sang một Trang Mã cụ thể sử dụng chiến lược "Phù hợp nhất" (như đã lưu ý trong câu trả lời của @ Paul và trong liên kết mà @Martin đã lưu ý trong một nhận xét về Câu hỏi). Theo trang MSDN cho Mã hóa ký tự trong .NET Framework :

Ánh xạ phù hợp nhất là hành vi mặc định cho một đối tượng Mã hóa mã hóa dữ liệu Unicode thành dữ liệu trang mã ...

Nhưng chính xác những ánh xạ này là gì? Trang MSDN được sử dụng để nêu sau đây:

Các chiến lược phù hợp nhất khác nhau cho các trang mã khác nhau và chúng không được ghi lại chi tiết.

Tuy nhiên, điều đó không hoàn toàn chính xác. Có lẽ "chiến lược" để xác định ánh xạ không được ghi lại chính xác. Đồng ý. Nhưng, bản đồ được ghi lại, không phải là nơi dễ tìm nhất.

Vì vậy, nhờ Microsoft chuyển tài liệu sang GitHub, trang đó hiện trạng thái như sau (vì tôi đã cập nhật nó):

Chiến lược phù hợp nhất không được ghi lại chi tiết. Tuy nhiên, một số trang mã được ghi lại tại trang web của Unicode Consortium . Vui lòng xem lại tệp readme.txt trong thư mục đó để biết mô tả về cách diễn giải các tệp ánh xạ.

Nếu bạn truy cập URL sau, bạn sẽ thấy một danh sách một số tệp, mỗi tệp được đặt tên cho Trang Mã mà nó ánh xạ các ký tự Unicode thành:

ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/

Hầu hết các tệp được cập nhật lần cuối (hoặc ít nhất là được đặt ở đó) vào ngày 2006-10-04 và một trong số chúng đã được cập nhật vào ngày 2012-05-2014. Phần đầu tiên của các tệp đó ánh xạ mã ASCII thành Điểm Mã Unicode tương đương. Nhưng phần thứ hai của mỗi tệp ánh xạ các ký tự Unicode thành "tương đương" ASCII của chúng.

Tôi đã viết một tập lệnh thử nghiệm sử dụng ánh xạ mã để kiểm tra xem SQL Server có thực sự sử dụng các ánh xạ đó không. Điều đó có thể được xác định bằng cách trả lời hai câu hỏi sau:

  1. Đối với tất cả các Điểm Mã được ánh xạ, SQL Server có chuyển đổi chúng thành ánh xạ được chỉ định không?
  2. Đối với tất cả các Điểm Mã chưa được ánh xạ, SQL Server có chuyển đổi bất kỳ điểm nào trong số chúng thành ?ký tự không " " không?

Kịch bản thử nghiệm quá dài để đặt ở đây, vì vậy tôi đã đăng nó lên Pastebin tại:

Ánh xạ trang Unicode sang mã trong SQL Server

Chạy tập lệnh sẽ cho thấy câu trả lời cho câu hỏi đầu tiên ở trên là "Có" (có nghĩa là tất cả các ánh xạ được cung cấp đều được tuân thủ). Nó cũng sẽ chỉ ra rằng câu trả lời cho câu hỏi thứ hai là "Không" (có nghĩa là, không có Điểm Mã nào chưa được chuyển đổi thành bất cứ thứ gì ngoại trừ ký tự cho "không xác định"). Do đó, tệp ánh xạ đó rất chính xác :-).

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.