UCS-2 kodlaması her zaman karakter başına 2 bayttır ve 0 - 65535 (0x0000 - 0xFFFF) aralığına sahiptir. UTF-16 (Big Endian veya Little Endian'dan bağımsız olarak) 0 - 1114111 (0x0000 - 0x10FFFF) aralığındadır. 0 - 65535 / 0x0000 - 0xFFFF UTF-16 aralığı karakter başına 2 bayt, 65536 / 0xFFFF değeri ise karakter başına 4 bayttır.
Windows ve SQL Server, UCS-2 kodlamasını kullanmaya başladı çünkü mevcuttu ve UTF-16 henüz sonuçlanmadı. Neyse ki, UCS-2 eşlemelerinin UTF-16 eşlemelerinin tam bir alt kümesi olduğu konusunda UCS-2 ve UTF-16'nın tasarımlarına yeterince ön düşünce yapıldı (yani: 0 - 65535 / 0x0000 - 0xFFFF aralığı UTF-16 , UCS-2'dir). VE, 65536 - 1114111 (0x10000 - 0x10FFFF) UTF-16 aralığı, UCS-2 aralığındaki iki kod noktasından (özellikle 0xD800 - 0xDBFF ve 0xDC00 - 0xDFFF aralıklarıyla) ayrılmış olup, bu amaçla ayrılmıştır. anlamına gelir. İki Kod Noktasının bu birleşimi bir Vekil Çift olarak bilinir ve Vekil Çiftler, UCS-2 aralığının ötesinde, Tamamlayıcı Karakterler olarak bilinen karakterleri temsil eder.
Tüm bu bilgiler, NVARCHAR
SQL Server'da / Unicode verilerinin iki yönünü açıklar :
- Çeşitli yerleşik işlevleri (sadece
NCHAR()
bir Ek Karakter-Aware Harmanlama kullanmadığınızda Vekil Çiftlerini / Yardımcı Karakterler dokunmayın) (SCA; yani bir kez _SC
, ya da _140_
ancak _BIN*
adı) Çünkü olmayan SCA Harmanlamalar (özellikle SQL_
Harmanlamalar) başlangıçta UTF-16'nın tamamlanmasından önce uygulandı (bazen 2000'de sanırım). Olmayan SQL_
var Harmanlamalar _90_
veya _100_
adlarında ancak _SC
karşılaştırma ve sıralama açısından Tamamlayıcı Karakterler için minimum destek var.
- Tam Unicode / UTF-16 karakter seti,
NVARCHAR
/ NCHAR
/ XML
/ NTEXT
veri tiplerinde veri kaybı olmadan, UCS-2 ve UTF-16 aynı byte dizileri olduğundan saklanabilir . Tek fark, UTF-16'nın Vekil Çiftleri oluşturmak için vekil kod noktalarını kullanması ve UCS-2'nin bunları herhangi bir karakterle eşleştirememesi, bu nedenle yerleşik işlevlerde iki bilinmeyen karakter olarak görünmesidir.
Bu arkaplan bilgisi göz önüne alınarak, şimdi belirli soruları inceleyebiliriz:
SELECT NCHAR(128512);
Aynı şekilde dönmek istiyorum :SELECT N'😀';
Bu, yalnızca geçerli veritabanının - sorgunun yürütülmekte olduğu yerdeyse), Tamamlayıcı Karaktere Uygun olan varsayılan bir Harmanlama içeriyorsa ve bunlar SQL Server 2012'de tanıtıldıysa. Dize giriş parametrelerine sahip yerleşik işlevler, Harmanlama özelliğine sahip olabilir COLLATE
cümle aracılığıyla satır içi (yani LEN(N'string' COLLATE Some_Collation_SC)
) ve bir varsayılan SCA Harmanlama içeren bir Veritabanı içinde yürütülmesi gerekmez . Bununla birlikte, NCHAR()
bir INT
giriş parametresini kabul etme ve COLLATE
yan tümce gibi yerleşik işlevler bu bağlamda geçerli değildir (bu nedenle NCHAR()
, geçerli veritabanında Tamamlayıcı Karaktere Uygun olan varsayılan bir harmanlama olduğunda yalnızca Tamamlayıcı Karakterleri destekler; ancak bu gereksizdir). değiştirilebilecek rahatsızlıklardan dolayı öneriye oy verin:NCHAR () işlevi, aktif veritabanının varsayılan harmanlama değerine bakılmaksızın, 0x10000 - 0x10FFFF değerleri için her zaman Ek Karakter döndürmelidir ).
Harmanlamadan bağımsız olarak, SQL Server'ın perspektif dışındaki durumlar dışında genişletilmiş karakterleri anlayabilmesi ve ilgilenebilmesinin bir açıklaması var mı NCHAR
?
SQL Server, Veri Kaydımı Olmadan Ek Karakterleri nasıl saklayabildiğini ve alabildiğini bu cevabın üst bölümünde açıkladı. Ancak, NCHAR
Tamamlayıcı Karakterlerle ilgili sorunları olan (bir SCA Harmanlaması kullanılmadığında), yalnızca yerleşik bir işlev olduğu doğru değildir. Örneğin, 1 değerini LEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)
verirken 2 LEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)
değerini verir.
Soru'da belirtilen ikinci bağlantıya (örneğin, "Microsoft'un Ek Karakterler Harmanlama Bilgisi") gidip biraz aşağıya inerseniz, yerleşik işlevlerin bir grafiğini ve etkin Harmanlamaya göre nasıl davrandıklarını görürsünüz.
"Ek karakter" bayrağını içeren bir harmanlamayı nasıl bulabilirim?
2012'den önceki bir SQL Server sürümünde yapamazsınız. Ancak, SQL Server 2012 ile başlayarak, aşağıdaki sorguyu kullanabilirsiniz:
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%');
Sorgunuz yakındı, ancak kalıpla başladı SQL
ve SQL Server Harmanlamaları (yani başlayanlar SQL_
) bir süredir Windows Harmanlamaları lehine (başlamıyorlar) kullanımdan kaldırıldı SQL_
. Dolayısıyla, SQL_
Harmanlamalar güncellenmiyor ve bu nedenle _SC
seçeneği içerecek yeni sürümleri yok (ve SQL Server 2017'den başlayarak, tüm yeni harmanlamalar otomatik olarak Ek Karakterleri destekliyor ve _SC
bayrağa gerek duymuyorlar veya bayrağa gerek duymuyorlar ve evet) sorgusuna hemen yukarıda gösterilenler bunun yanı sıra _UTF8
, SQL Server 2019'a eklenen harmanlamaları almak için de geçerlidir ).
Harmanlamaları eski örneklere yükleyebilir misiniz?
Hayır, Harmanlamaları önceki SQL Server sürümüne yükleyemezsiniz.
Harmanlamanın "ek karakter (SC) bayrağını" içermediği bir veritabanında kodu kullanarak (asıl Ek Karakteri kullanmadan) kod kullanarak bir Unicode string değişkenini (örneğin nvarchar) Ek Karaktere nasıl ayarlayabilirim?
...
Sunucu SQL Server 2008 R2 olmasına rağmen, sonraki sürümler için herhangi bir çözümü de merak ediyorum.
Bir SCA Harmanlama kullanmıyorsanız, 65535 / U + FFFF üzerindeki Kod Noktalarını iki şekilde enjekte edebilirsiniz:
- Vekil Çiftini
NCHAR()
, her biri çiftin bir parçası olan işleve yapılan iki çağrı açısından
- Vekil Çiftini
VARBINARY
, Küçük Endian (yani ters çevrilmiş) bayt dizisinin şeklini dönüştürmek açısından belirtin .
Tamamlayıcı Karakterler / Vekil Çiftleri eklemek için bu iki yöntem etkili Harmanlama Tamamlayıcı Karaktere Uygun olsa bile işe yarayacaktır ve SQL Server'ın tüm sürümlerinde aynı şekilde çalışmalıdır, en azından 2005 kadar geriye (muhtemelen muhtemelen SQL Server 2000 de).
Örnek:
- Karakter:
💩
- Adı: kaka yığını
- Ondalık: 128169
- Kod Noktası: U + 1F4A9
- Vekil Çifti: U + D83D ve 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)
GÜNCELLEŞTİRME
65536 - 1114111 (0x010000 - 0x10FFFF) arasında herhangi bir Kod Noktasından Vekil Çifti değerlerini (her ikisinde INT
ve BINARY
formda) almak için aşağıdaki iTVF'yi kullanabilirsiniz . Ve, giriş parametresi INT
türündeyken, Kod Noktasının ikili / onaltılık formuna geçebilirsiniz ve dolaylı olarak doğru tamsayı değerine dönüştürür.
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
Yukarıdaki işlevi kullanarak, aşağıdaki iki sorgu:
SELECT * FROM dbo.GetSupplementaryCharacterInfo(128169);
SELECT * FROM dbo.GetSupplementaryCharacterInfo(0x01F4A9);
her ikisi de aşağıdakileri döndürür:
CodePoint HighSurrogate LowSurrgate CodePoint HighSurrgate LowSurrgate UTF-16LE Char
INT INT INT BIN BIN BIN actr
128169 55357 56489 0x01F4A9 0xD83D 0xDCA9 0x3DD8A9DC 💩
GÜNCELLEME 2: Daha İyi Bir Güncelleme!
Yukarıda gösterilen iTVF'i 188.657 kod puanını döndürecek şekilde uyarladım, böylece belirli bir değere uymanıza gerek kalmayacak. Tabii ki, bir TVF olarak, WHERE
belirli bir kod noktasına ya da kod noktalarına ya da "benzer karakterlere" vb. Göre filtrelemek için bir cümle ekleyebilirsiniz . T-SQL, HTML ve C stilinde (yani, BMP ve Ek Karakterler) gelin \xHHHH
. Bununla ilgili her şeyi burada okuyun:
SSMS Tip # 3: TÜM Unicode Karakterlere Kolayca Erişim / Araştırma (Evet, Emojiler Dahil)