Mã hóa UCS-2 luôn là 2 byte cho mỗi ký tự và có phạm vi 0 - 65535 (0x0000 - 0xFFFF). UTF-16 (không phân biệt Big Endian hay Little Endian) có phạm vi 0 - 1114111 (0x0000 - 0x10FFFF). Phạm vi 0 - 65535 / 0x0000 - 0xFFFF của UTF-16 là 2 byte mỗi ký tự trong khi phạm vi trên 65536 / 0xFFFF là 4 byte mỗi ký tự.
Windows và SQL Server bắt đầu sử dụng mã hóa UCS-2 vì nó đã có sẵn và UTF-16 chưa được hoàn thiện. Tuy nhiên, may mắn thay, đã có đủ ý tưởng được đưa vào các thiết kế của UCS-2 và UTF-16 rằng các ánh xạ UCS-2 là một tập hợp con hoàn chỉnh của ánh xạ UTF-16 (có nghĩa là: phạm vi 0 - 65535 / 0x0000 - 0xFFFF của UTF-16 là UCS-2). VÀ, phạm vi 65536 - 1114111 (0x10000 - 0x10FFFF) của UTF-16 được xây dựng từ hai Điểm Mã trong phạm vi UCS-2 (phạm vi 0xD800 - 0xDBFF và 0xDC00 - 0xDFFF, cụ thể) Ý nghĩa. Sự kết hợp của hai Điểm Mã này được gọi là Cặp thay thế và Cặp thay thế đại diện cho các nhân vật nằm ngoài phạm vi UCS-2 được gọi là Nhân vật bổ sung.
Tất cả thông tin đó giải thích hai khía cạnh của NVARCHAR
/ dữ liệu Unicode trong SQL Server:
- Một số được xây dựng trong chức năng (không chỉ
NCHAR()
) không xử lý Surrogate cặp / Nhân vật phụ khi không sử dụng một nhân vật-Aware Collation bổ sung (SCA; một ví dụ với _SC
, hoặc _140_
nhưng không phải _BIN*
trong tên) vì không SCA Collations (đặc biệt là SQL_
Bộ sưu tập) ban đầu được triển khai trước khi UTF-16 được hoàn thành (đôi khi vào năm 2000, tôi tin). Các tổ hợp không SQL_
có _90_
hoặc có _100_
tên của họ nhưng không _SC
có hỗ trợ tối thiểu cho các Nhân vật bổ sung về mặt so sánh và sắp xếp.
- Bộ ký tự Unicode / UTF-16 đầy đủ có thể được lưu trữ, mà không mất dữ liệu, trong
NVARCHAR
/ NCHAR
/ XML
/ NTEXT
kiểu dữ liệu vì UCS-2 và UTF-16 là các chuỗi byte chính xác giống nhau. Sự khác biệt duy nhất là UTF-16 sử dụng các điểm mã thay thế để xây dựng các cặp thay thế và UCS-2 đơn giản là không thể ánh xạ chúng tới bất kỳ ký tự nào, do đó chúng xuất hiện với các hàm tích hợp dưới dạng hai ký tự không xác định.
Với thông tin cơ bản đó, bây giờ chúng ta có thể đi qua các câu hỏi cụ thể:
Tôi muốn SELECT NCHAR(128512);
trả lại giống như thế này:SELECT N'😀';
Điều đó chỉ có thể xảy ra nếu cơ sở dữ liệu hiện tại - nơi truy vấn đang được thực thi - có Collation mặc định là Aware Ký tự bổ sung và được giới thiệu trong SQL Server 2012. Các hàm dựng sẵn có tham số đầu vào chuỗi có thể cung cấp Collation nội tuyến thông qua COLLATE
mệnh đề (nghĩa là LEN(N'string' COLLATE Some_Collation_SC)
) và không cần phải được thực thi trong Cơ sở dữ liệu có Đối chiếu mặc định SCA. Tuy nhiên, các hàm dựng sẵn như NCHAR()
chấp nhận INT
tham số đầu vào và COLLATE
mệnh đề không hợp lệ trong ngữ cảnh đó (đó là lý do tại sao NCHAR()
chỉ hỗ trợ các ký tự bổ sung khi cơ sở dữ liệu hiện tại có đối chiếu mặc định là Aware ký tự bổ sung, nhưng điều này là không cần thiết sự bất tiện có thể thay đổi, vì vậy hãy bỏ phiếu cho đề xuất của tôi:Hàm NCHAR () phải luôn trả về Ký tự bổ sung cho các giá trị 0x10000 - 0x10FFFF bất kể đối chiếu mặc định của cơ sở dữ liệu đang hoạt động ).
Có một lời giải thích cho lý do tại sao, bất kể đối chiếu, SQL Server có thể hiểu và xử lý các ký tự mở rộng ngoại trừ từ quan điểm của NCHAR
?
Cách SQL Server có thể lưu trữ và truy xuất các ký tự bổ sung mà không mất dữ liệu đã được giải thích trong phần trên cùng của câu trả lời này. Nhưng, sự thật không phải NCHAR
là chức năng tích hợp duy nhất có vấn đề với Nhân vật bổ sung (khi không sử dụng Đối chiếu SCA). Ví dụ: LEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)
trả về giá trị là 2 trong khi LEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)
trả về giá trị là 1.
Nếu bạn truy cập liên kết thứ hai được đăng trong Câu hỏi (tức là "Thông tin đối chiếu các ký tự bổ sung của Microsoft") và cuộn xuống một chút, bạn sẽ thấy một biểu đồ về các chức năng tích hợp và cách chúng hoạt động dựa trên Collation hiệu quả.
Làm cách nào để tìm một đối chiếu có cờ "ký tự bổ sung"?
Trong phiên bản SQL Server trước năm 2012, bạn không thể. Nhưng, bắt đầu với SQL Server 2012, bạn có thể sử dụng truy vấn sau:
SELECT col.*
FROM sys.fn_helpcollations() col
WHERE col.[name] LIKE N'%[_]SC'
OR col.[name] LIKE N'%[_]SC[_]%'
OR (COLLATIONPROPERTY(col.[name], 'Version') = 3
AND col.[name] NOT LIKE N'%[_]BIN%');
Truy vấn của bạn đã gần, nhưng mẫu bắt đầu bằng SQL
và Bộ sưu tập SQL Server (tức là những bộ bắt đầu bằng SQL_
) đã không được dùng trong một thời gian có lợi cho Bộ sưu tập Windows (những bộ không bắt đầu bằng SQL_
). Vì vậy, các Bộ SQL_
sưu tập không được cập nhật và do đó không có phiên bản mới hơn bao gồm _SC
tùy chọn (và bắt đầu trong SQL Server 2017, tất cả các bộ sưu tập mới đều tự động hỗ trợ Ký tự bổ sung và không cần, hoặc có _SC
cờ, và có, truy vấn hiển thị ngay trên các tài khoản cho điều đó cũng như chọn các _UTF8
đối chiếu được thêm vào trong SQL Server 2019).
Bạn có thể cài đặt collations trên các trường hợp cũ hơn?
Không, bạn không thể cài đặt Collations vào phiên bản SQL Server trước đó.
Làm cách nào tôi có thể đặt biến chuỗi Unicode (ví dụ: nvarchar) thành Ký tự bổ sung bằng cách sử dụng mã (không sử dụng Ký tự bổ sung thực tế) trong cơ sở dữ liệu trong đó đối chiếu "không chứa cờ ký tự bổ sung (SC)"?
...
Mặc dù máy chủ là SQL Server 2008 R2, tôi cũng tò mò về bất kỳ giải pháp nào cho các phiên bản sau.
Khi không sử dụng Đối chiếu SCA, bạn có thể đưa Điểm Mã trên 65535 / U + FFFF theo hai cách:
- Chỉ định Cặp thay thế theo hai lệnh gọi đến
NCHAR()
hàm, mỗi lệnh có một phần của cặp
- Chỉ định Cặp thay thế về mặt chuyển đổi
VARBINARY
hình thức của chuỗi byte Endian (nghĩa là đảo ngược).
Hai phương thức chèn Nhân vật bổ sung / Cặp thay thế này sẽ hoạt động ngay cả khi Đối chiếu hiệu quả là Nhận thức ký tự bổ sung và sẽ hoạt động giống nhau trên tất cả các phiên bản của SQL Server, ít nhất là từ năm 2005 (mặc dù có lẽ cũng sẽ hoạt động trong SQL Server 2000 cũng vậy).
Thí dụ:
- Tính cách:
💩
- Tên: Cọc của Poo
- Số thập phân: 128169
- Điểm mã: U + 1F4A9
- Cặp thay thế: U + D83D & U + DF21
SELECT N'💩', -- 💩
UNICODE(N'💩' COLLATE Latin1_General_100_CI_AS), -- 55357
UNICODE(N'💩' COLLATE Latin1_General_100_CI_AS_SC), -- 128169
NCHAR(128169), -- 💩 in DB with _SC Collation, else NULL
NCHAR(0x1F4A9), -- 💩 in DB with _SC Collation, else NULL
CONVERT(VARBINARY(4), 128169), -- 0x0001F4A9
CONVERT(VARBINARY(4), N'💩'), -- 0x3DD8A9DC
CONVERT(NVARCHAR(10), 0x3DD8A9DC), -- 💩 (regardless of DB Collation)
NCHAR(0xD83D) + NCHAR(0xDCA9) -- 💩 (regardless of DB Collation)
CẬP NHẬT
Bạn có thể sử dụng iTVF sau để nhận các giá trị Cặp thay thế (cả hai INT
và BINARY
dạng) từ bất kỳ Điểm Mã nào trong khoảng 65536 - 1114111 (0x010000 - 0x10FFFF). Và, trong khi tham số đầu vào là loại INT
, bạn có thể chuyển ở dạng nhị phân / hex của Điểm Mã và nó sẽ hoàn toàn chuyển đổi thành giá trị nguyên chính xác.
CREATE FUNCTION dbo.GetSupplementaryCharacterInfo(@CodePoint INT)
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN
WITH calc AS
(
SELECT 55232 + (@CodePoint / 1024) AS [HighSurrogateINT],
56320 + (@CodePoint % 1024) AS [LowSurrogateINT]
WHERE @CodePoint BETWEEN 65536 AND 1114111
)
SELECT @CodePoint AS [CodePointINT],
HighSurrogateINT,
LowSurrogateINT,
CONVERT(VARBINARY(3), @CodePoint) AS [CodePointBIN],
CONVERT(BINARY(2), HighSurrogateINT) AS [HighSurrogateBIN],
CONVERT(BINARY(2), LowSurrogateINT) AS [LowSurrogateBIN],
CONVERT(binary(4), NCHAR(HighSurrogateINT) + NCHAR(LowSurrogateINT)) AS [UTF-16LE],
NCHAR(HighSurrogateINT) + NCHAR(LowSurrogateINT) AS [Character]
FROM calc;
GO
Sử dụng chức năng trên, hai truy vấn sau:
SELECT * FROM dbo.GetSupplementaryCharacterInfo(128169);
SELECT * FROM dbo.GetSupplementaryCharacterInfo(0x01F4A9);
cả hai trả về như sau:
CodePoint HighSurrogate LowSurrgate CodePoint HighSurrgate LowSurrgate UTF-16LE Char
INT INT INT BIN BIN BIN actr
128169 55357 56489 0x01F4A9 0xD83D 0xDCA9 0x3DD8A9DC 💩
CẬP NHẬT 2: Một bản cập nhật thậm chí còn tốt hơn!
Tôi đã điều chỉnh iTVF được hiển thị ở trên để trả về 188.657 điểm mã để bạn không cần phải khớp với bất kỳ giá trị cụ thể nào. Tất nhiên, là một TVF, bạn có thể thêm một WHERE
mệnh đề để lọc trên một điểm mã cụ thể hoặc phạm vi các điểm mã hoặc "ký tự tương tự", v.v. Và, nó bao gồm các cột bổ sung với các chuỗi thoát được định dạng trước để tạo từng mã điểm (cả BMP và Ký tự bổ sung) theo kiểu T-SQL, HTML và C (nghĩa là \xHHHH
). Đọc tất cả về nó ở đây:
Mẹo SSMS # 3: Dễ dàng truy cập / nghiên cứu TẤT CẢ các ký tự Unicode (Có, bao gồm cả biểu tượng cảm xúc)