Bir SQL Server Unicode / NVARCHAR dizesini bir emojiye veya Ek Karaktere nasıl ayarlarım?


23

Unicode kod noktasına göre belirli bir karaktere Unicode string değişkeni ayarlamak istiyorum.

65535 ötesinde bir kod noktası kullanmak istiyorum, ancak SQL Server 2008 R2 veritabanının bir harmanlaması var SQL_Latin1_General_CP1_CI_AS.

Göre Microsoft'un NCHAR belgelerinde , NCHARaşağıdaki gibi işlev bir tamsayı alır:

integer_expression

Veritabanının harmanlama, ek karakter (SC) bayrağını içermediğinde, bu 0 ile 65535 (0 - 0xFFFF) arasında bir pozitif tam sayıdır. Bu aralığın dışında bir değer belirtilirse, NULL döndürülür. Ek karakterler hakkında daha fazla bilgi için, bkz. Harmanlama ve Unicode Desteği.

Veritabanının harmanlanması ek karakter (SC) bayrağını desteklediğinde, bu 0 - 1114111 (0 - 0x10FFFF) arasında bir pozitif tam sayıdır. Bu aralığın dışında bir değer belirtilirse, NULL döndürülür.

Yani bu kod:

SELECT NCHAR(128512);

İade NULLbu veritabanında.

Şunun aynısını döndürmesini istiyorum:

SELECT N'😀';

Harmanlamayı "ek karakter (SC) bayrağını" içermeyen bir veritabanında kod kullanarak (asıl emoji karakterini kullanmadan) kod kullanarak bir Unicode dizesi değişkenini (örneğin nvarchar) bir emojiye nasıl ayarlayabilirim?

Emoji Unicode kod noktalarının tam listesi

(Sonuçta herhangi bir karakterin çalışmasını istiyorum. Sadece referans kolaylığı için emojiyi seçtim.)

(Sunucu SQL Server 2008 R2 olmasına rağmen, sonraki sürümler için herhangi bir çözümü merak ediyorum.)

Bunun mümkün olmadığını varsayarak, uygun bir harmanlama olan başka bir veritabanında satır içi kullanıcı tanımlı bir işleve başvurabilir miyim?

"Ek karakter" bayrağını içeren bir harmanlamayı nasıl bulabilirim?

Bu sunucumuzda hiçbir kayıt döndürmez:

SELECT * FROM sys.fn_helpcollations() 
WHERE name LIKE 'SQL%[_]SC';

SQL Server 2012 tanıtıldı gibi görünüyor Latin1_General_100_CI_AS_SC . Harmanlamaları eski örneklere yükleyebilir misiniz?

Harmanlama Referansları:

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?


Kapsamlı ek bilgi için teşekkürler. Artık bu sorunla karşı karşıya değilim, ancak bu bilgiyi zihinsel olarak yer imi altında tutacağım.
Riley Binbaşı

1
Sorun değil. Hala bir şeye ihtiyacın olduğunu düşünmemiştim , sadece uyarlamayı kullanabileceğini / takdir edebileceğini ...
Solomon Rutzky

Yanıtlar:


36

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, NVARCHARSQL Server'da / Unicode verilerinin iki yönünü açıklar :

  1. Ç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 _SCkarşılaştırma ve sıralama açısından Tamamlayıcı Karakterler için minimum destek var.
  2. Tam Unicode / UTF-16 karakter seti, NVARCHAR/ NCHAR/ XML/ NTEXTveri 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 COLLATEcü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 INTgiriş parametresini kabul etme ve COLLATEyan 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, NCHARTamamlayı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ı SQLve 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 _SCseç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 _SCbayrağ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:

  1. Vekil Çiftini NCHAR(), her biri çiftin bir parçası olan işleve yapılan iki çağrı açısından
  2. 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 INTve BINARYformda) almak için aşağıdaki iTVF'yi kullanabilirsiniz . Ve, giriş parametresi INTtü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, WHEREbelirli 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)


1
Harika iş Solomon! Müthiş açıklama
Ronen Ariely
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.