Pengkodean UCS-2 selalu 2 byte per karakter dan memiliki kisaran 0 - 65535 (0x0000 - 0xFFFF). UTF-16 (terlepas dari Big Endian atau Little Endian) memiliki kisaran 0 - 1114111 (0x0000 - 0x10FFFF). Rentang 0 - 65535 / 0x0000 - 0xFFFF dari UTF-16 adalah 2 byte per karakter sedangkan kisaran di atas 65536 / 0xFFFF adalah 4 byte per karakter.
Windows dan SQL Server mulai menggunakan pengkodean UCS-2 karena sudah tersedia dan UTF-16 belum selesai. Untungnya, bagaimanapun, ada cukup pemikiran ke depan dimasukkan ke dalam desain UCS-2 dan UTF-16 bahwa pemetaan UCS-2 adalah bagian lengkap dari pemetaan UTF-16 (artinya: kisaran 0 - 65535 / 0x0000 - 0xFFFF UTF-16 adalah UCS-2). DAN, kisaran UTF-16 65536 - 1114111 (0x10000 - 0x10FFFF) dibangun dari dua Poin Kode dalam kisaran UCS-2 (kisaran 0xD800 - 0xDBFF dan 0xDC00 - 0xDFFF, khusus) yang disediakan untuk tujuan ini dan sebaliknya tidak memiliki berarti. Kombinasi dua Poin Kode ini dikenal sebagai Pasangan Pengganti, dan Pasangan Pengganti mewakili karakter di luar rentang UCS-2 yang dikenal sebagai Karakter Tambahan.
Semua informasi itu menjelaskan dua aspek NVARCHAR
/ data Unicode di SQL Server:
- Beberapa fungsi bawaan (tidak hanya
NCHAR()
) tidak menangani Pasangan Pengganti / Karakter Tambahan saat tidak menggunakan Collation Character-Aware Collation (SCA; yaitu satu dengan _SC
, atau _140_
tetapi tidak _BIN*
dalam nama) karena Collations non-SCA (terutama SQL_
Collations) awalnya dilaksanakan sebelum UTF-16 selesai (sekitar tahun 2000, saya percaya). Non- SQL_
Collations yang memiliki _90_
atau _100_
atas nama mereka tetapi tidak _SC
memiliki dukungan minimal untuk Karakter Tambahan dalam hal perbandingan dan penyortiran.
- Penuh Unicode / UTF-16 set karakter dapat disimpan, tanpa kehilangan data, dalam
NVARCHAR
/ NCHAR
/ XML
/ NTEXT
tipe data karena UCS-2 dan UTF-16 adalah urutan byte yang sama persis. Satu-satunya perbedaan adalah bahwa UTF-16 memanfaatkan titik kode pengganti untuk membangun Pasangan Pengganti, dan UCS-2 tidak dapat memetakannya ke karakter apa pun, oleh karena itu mereka muncul pada fungsi bawaan sebagai dua karakter yang tidak dikenal.
Dengan mengingat informasi latar belakang itu, sekarang kita dapat melalui pertanyaan spesifik:
Saya ingin SELECT NCHAR(128512);
mengembalikan yang sama seperti ini:SELECT N'😀';
Itu hanya dapat terjadi jika database saat ini - di mana kueri sedang dieksekusi - memiliki Collation default yang Tambahan Karakter-Sadar, dan yang diperkenalkan di SQL Server 2012. Fungsi bawaan yang memiliki parameter input string dapat memiliki Collation yang disediakan sebaris melalui COLLATE
klausa (yaitu LEN(N'string' COLLATE Some_Collation_SC)
) dan tidak perlu dijalankan dalam Database yang memiliki Collation default SCA. Namun, fungsi bawaan seperti NCHAR()
menerima INT
parameter input dan COLLATE
klausa tidak valid dalam konteks itu (itulah sebabnya NCHAR()
hanya mendukung Karakter Tambahan ketika database saat ini memiliki susunan default yang Sadar Karakter-Sadar; tetapi ini tidak perlu ketidaknyamanan yang dapat diubah, jadi silakan pilih saran saya:Fungsi NCHAR () harus selalu mengembalikan Karakter Tambahan untuk nilai 0x10000 - 0x10FFFF terlepas dari susunan default basis data aktif ).
Apakah ada penjelasan mengapa, terlepas dari pemeriksaan, SQL Server dapat memahami dan menangani karakter yang diperluas kecuali dari perspektif NCHAR
?
Bagaimana SQL Server dapat menyimpan dan mengambil karakter tambahan tanpa kehilangan data dijelaskan di bagian atas jawaban ini. Tetapi, tidak benar bahwa NCHAR
satu-satunya fungsi bawaan yang memiliki masalah dengan Karakter Tambahan (saat tidak menggunakan SCA Collation). Misalnya, LEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)
mengembalikan nilai 2 sementara LEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)
mengembalikan nilai 1.
Jika Anda pergi ke tautan kedua yang diposting di Pertanyaan (yaitu "Informasi Pengumpulan Karakter Tambahan Microsoft") dan gulirkan sedikit ke bawah, Anda akan melihat bagan fungsi bawaan dan bagaimana mereka berperilaku berdasarkan Kolasi efektif.
Bagaimana cara menemukan collation yang memiliki bendera "karakter tambahan"?
Dalam versi SQL Server sebelum 2012 Anda tidak bisa. Tetapi, dimulai dengan SQL Server 2012, Anda dapat menggunakan kueri berikut:
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%');
Permintaan Anda sudah dekat, tetapi pola dimulai dengan SQL
dan SQL Server Collations (yaitu yang dimulai dengan SQL_
) telah ditinggalkan untuk sementara waktu karena Windows Collations (yang tidak dimulai dengan SQL_
). Jadi, SQL_
Collations tidak diperbarui dan karenanya tidak memiliki versi yang lebih baru yang akan menyertakan _SC
opsi (dan mulai di SQL Server 2017, semua collations baru secara otomatis mendukung Karakter Tambahan dan tidak perlu, atau memiliki, _SC
bendera; dan ya, kueri ditampilkan segera di atas akun untuk itu serta mengambil _UTF8
collations yang ditambahkan di SQL Server 2019).
Bisakah Anda menginstal collations pada instances lama?
Tidak, Anda tidak dapat menginstal Collations ke versi SQL Server sebelumnya.
Bagaimana saya bisa mengatur variabel string Unicode (misalnya nvarchar) ke Karakter Tambahan menggunakan kode (tanpa menggunakan Karakter Tambahan yang sebenarnya) dalam database di mana collation "tidak mengandung flag karakter tambahan (SC)"?
...
Meskipun servernya adalah SQL Server 2008 R2, saya juga ingin tahu tentang solusi apa pun untuk versi yang lebih baru.
Saat tidak menggunakan Collation SCA, Anda bisa menyuntikkan Poin Kode di atas 65535 / U + FFFF dengan dua cara:
- Tentukan Pasangan Pengganti dalam hal dua panggilan ke
NCHAR()
fungsi, masing-masing dengan satu bagian dari pasangan
- Tentukan Pasangan Pengganti dalam hal mengkonversi
VARBINARY
bentuk urutan byte Little Endian (yaitu dibalik).
Dua metode ini memasukkan Karakter Tambahan / Pasangan Pengganti akan bekerja bahkan jika Kolasi yang efektif adalah Karakter Tambahan-Sadar, dan harus bekerja sama di semua versi SQL Server, setidaknya sejauh 2005 (walaupun mungkin juga akan bekerja di SQL Server 2000 juga).
Contoh:
- Karakter:
💩
- Nama: Tumpukan Poo
- Desimal: 128169
- Poin Kode: U + 1F4A9
- Pasangan Pengganti: 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)
MEMPERBARUI
Anda dapat menggunakan iTVF berikut untuk mendapatkan nilai Pasangan Pengganti (dalam keduanya INT
dan dalam BINARY
bentuk) dari Titik Kode mana saja antara 65536 - 1114111 (0x010000 - 0x10FFFF). Dan, sementara parameter input bertipe INT
, Anda bisa meneruskan dalam bentuk biner / hex dari Kode Point dan secara implisit akan dikonversi ke nilai integer yang benar.
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
Menggunakan fungsi di atas, dua pertanyaan berikut:
SELECT * FROM dbo.GetSupplementaryCharacterInfo(128169);
SELECT * FROM dbo.GetSupplementaryCharacterInfo(0x01F4A9);
keduanya mengembalikan yang berikut:
CodePoint HighSurrogate LowSurrgate CodePoint HighSurrgate LowSurrgate UTF-16LE Char
INT INT INT BIN BIN BIN actr
128169 55357 56489 0x01F4A9 0xD83D 0xDCA9 0x3DD8A9DC 💩
UPDATE 2: Pembaruan Yang Lebih Baik!
Saya telah mengadaptasi iTVF yang ditunjukkan di atas untuk sekarang mengembalikan 188.657 poin kode sehingga Anda tidak perlu mencocokkannya dengan nilai tertentu. Tentu saja, sebagai TVF, Anda dapat menambahkan WHERE
klausa untuk memfilter pada titik kode tertentu, atau rentang titik kode, atau "karakter serupa", dll. Dan, itu termasuk kolom tambahan dengan urutan pelarian yang telah diformat untuk membangun setiap kode point (baik BMP dan Karakter Tambahan) dalam T-SQL, HTML, dan C-style (yaitu \xHHHH
). Baca semua tentang ini di sini:
Tip SSMS # 3: Mudah Mengakses / Meneliti SEMUA Karakter Unicode (Ya, Termasuk Emoji 😸)