Je veux définir une variable de chaîne Unicode sur un caractère particulier en fonction de son point de code Unicode.
Je veux utiliser un point de code au-delà de 65535, mais la base de données SQL Server 2008 R2 a un classement de SQL_Latin1_General_CP1_CI_AS
.
Selon la documentation NCHAR de Microsoft , la NCHAR
fonction prend un entier comme suit:
expression_entier
Lorsque le classement de la base de données ne contient pas l'indicateur de caractère supplémentaire (SC), il s'agit d'un nombre entier positif compris entre 0 et 65535 (0 et 0xFFFF). Si une valeur en dehors de cette plage est spécifiée, NULL est retourné. Pour plus d'informations sur les caractères supplémentaires, voir Prise en charge du classement et d'Unicode.
Lorsque le classement de la base de données prend en charge l'indicateur de caractère supplémentaire (SC), il s'agit d'un nombre entier positif compris entre 0 et 1114111 (0 et 0x10FFFF). Si une valeur en dehors de cette plage est spécifiée, NULL est retourné.
Donc, ce code:
SELECT NCHAR(128512);
Retourne NULL
dans cette base de données.
Je voudrais qu'il renvoie le même que celui-ci:
SELECT N'😀';
Comment puis-je définir une variable de chaîne Unicode (par exemple nvarchar) sur un emoji en utilisant du code (sans utiliser le caractère emoji réel) dans une base de données où le classement "ne contient pas l'indicateur de caractère supplémentaire (SC)"?
Liste complète des points de code emoji Unicode
(En fin de compte, je veux que n'importe quel personnage fonctionne. J'ai simplement choisi les emoji pour faciliter la référence.)
(Bien que le serveur soit SQL Server 2008 R2, je suis également curieux de savoir quelles solutions pour les versions ultérieures.)
En supposant qu'il n'y ait aucun moyen, pourrais-je référencer une fonction définie par l'utilisateur en ligne dans une autre base de données qui avait un classement approprié?
Comment trouver un classement qui a le drapeau "caractère supplémentaire"?
Cela ne renvoie aucun enregistrement sur notre serveur:
SELECT * FROM sys.fn_helpcollations()
WHERE name LIKE 'SQL%[_]SC';
Il semble que SQL Server 2012 a été introduit, Latin1_General_100_CI_AS_SC
ce qui fonctionnerait. Pouvez-vous installer des classements sur des instances plus anciennes?
Références de collation:
- Réponse à Quelle est la différence entre char, nchar, varchar et nvarchar dans SQL Server?
- Informations de classement des caractères supplémentaires de Microsoft
- Liste de classement SQL Server 2008 R2 de Microsoft
Y a-t-il une explication pour laquelle, indépendamment du classement, SQL Server peut comprendre et gérer les caractères étendus, sauf du point de vue de NCHAR
?
Réponses:
Le codage UCS-2 est toujours de 2 octets par caractère et a une plage de 0 à 65535 (0x0000 - 0xFFFF). UTF-16 (indépendamment de Big Endian ou Little Endian) a une plage de 0 - 1114111 (0x0000 - 0x10FFFF). La plage 0 - 65535 / 0x0000 - 0xFFFF de UTF-16 est de 2 octets par caractère tandis que la plage au-dessus de 65536 / 0xFFFF est de 4 octets par caractère.
Windows et SQL Server ont commencé à utiliser l'encodage UCS-2 car il était disponible et UTF-16 n'était pas encore finalisé. Heureusement, cependant, les conceptions de UCS-2 et UTF-16 ont été suffisamment conçues pour que les mappages UCS-2 soient un sous-ensemble complet des mappages UTF-16 (ce qui signifie: la plage 0 - 65535 / 0x0000 - 0xFFFF de l'UTF-16 est UCS-2). ET, la plage UTF-16 65536 - 1114111 (0x10000 - 0x10FFFF) est construite à partir de deux points de code dans la plage UCS-2 (plages 0xD800 - 0xDBFF et 0xDC00 - 0xDFFF, en particulier) qui ont été réservés à cet effet et qui n'ont autrement aucune sens. Cette combinaison de deux points de code est connue sous le nom de paire de substitution, et les paires de substitution représentent des caractères au-delà de la plage UCS-2, appelés caractères supplémentaires.
Toutes ces informations expliquent deux aspects des
NVARCHAR
données / Unicode dans SQL Server:NCHAR()
) ne gèrent pas / paires Surrogate caractères supplémentaires lorsqu'ils ne sont pas en utilisant un caractère supplémentaire-Aware Collation (SCA, à savoir un avec_SC
, ou_140_
non_BIN*
dans le nom) parce que le (non-SCA en particulier la collation par défautSQL_
Les classements) ont été mis en œuvre à l'origine avant l'achèvement de l'UTF-16 (quelque part en 2000, je crois). Les non-SQL_
classements qui ont_90_
ou_100_
en leur nom mais ne_SC
prennent pas en charge les caractères supplémentaires en termes de comparaison et de tri.NVARCHAR
/NCHAR
/XML
/NTEXT
car UCS-2 et UTF-16 sont exactement les mêmes séquences d'octets. La seule différence est que UTF-16 utilise les points de code de substitution pour construire des paires de substitution, et UCS-2 ne peut tout simplement pas les mapper à des caractères, ils apparaissent donc dans les fonctions intégrées comme deux caractères inconnus.Avec ces informations de fond à l'esprit, nous pouvons maintenant passer par les questions spécifiques:
Cela ne peut se produire que si la base de données actuelle - où la requête est exécutée - a un classement par défaut qui est compatible avec les caractères supplémentaires, et ceux qui ont été introduits dans SQL Server 2012. Les fonctions intégrées qui ont des paramètres d'entrée de chaîne peuvent avoir le classement fourni en ligne via la
COLLATE
clause (c'est-à-direLEN(N'string' COLLATE Some_Collation_SC)
) et n'ont pas besoin d'être exécutés dans une base de données qui a un classement SCA par défaut. Cependant, les fonctions intégrées telles que l'NCHAR()
acceptation d'unINT
paramètre d'entrée et laCOLLATE
clause ne sont pas valides dans ce contexte (c'est pourquoiNCHAR()
ne prend en charge les caractères supplémentaires que lorsque la base de données actuelle a un classement par défaut qui est compatible avec les caractères supplémentaires; mais ceci n'est pas nécessaire inconvénients qui peuvent être modifiés, veuillez donc voter pour ma suggestion:La fonction NCHAR () doit toujours renvoyer un caractère supplémentaire pour les valeurs 0x10000 - 0x10FFFF, indépendamment du classement par défaut de la base de données active ).La façon dont SQL Server peut stocker et récupérer des caractères supplémentaires sans perte de données a été expliquée dans la partie supérieure de cette réponse. Mais, il n'est pas vrai que
NCHAR
c'est la seule fonction intégrée qui a des problèmes avec les caractères supplémentaires (lorsque vous n'utilisez pas un classement SCA). Par exemple,LEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)
renvoie une valeur de 2 tandis queLEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)
renvoie une valeur de 1.Si vous accédez au deuxième lien publié dans la question (c'est-à-dire «Informations de classement des caractères supplémentaires de Microsoft») et faites défiler un peu vers le bas, vous verrez un graphique des fonctions intégrées et comment elles se comportent en fonction du classement effectif.
Dans une version de SQL Server antérieure à 2012, vous ne pouvez pas. Mais, à partir de SQL Server 2012, vous pouvez utiliser la requête suivante:
Votre requête était fermée, mais le modèle a commencé par
SQL
et les classements SQL Server (c'est-à-dire ceux commençant parSQL_
) sont obsolètes depuis un certain temps en faveur des classements Windows (ceux qui ne commencent pas parSQL_
). Ainsi, lesSQL_
classements ne sont pas mis à jour et n'ont donc pas de versions plus récentes qui incluraient l'_SC
option (et à partir de SQL Server 2017, tous les nouveaux classements prennent automatiquement en charge les caractères supplémentaires et n'ont pas besoin, ou n'ont pas, l'_SC
indicateur; et oui, la requête montré juste au-dessus explique cela et reprend les_UTF8
classements ajoutés dans SQL Server 2019).Non, vous ne pouvez pas installer Collations dans une version précédente de SQL Server.
Lorsque vous n'utilisez pas de classement SCA, vous pouvez injecter des points de code au-dessus de 65535 / U + FFFF de deux manières:
NCHAR()
fonction, chacun avec une partie de la paireVARBINARY
forme de la séquence d'octets Little Endian (c'est-à-dire inversée).Ces deux méthodes d'insertion de caractères supplémentaires / paires de substitution fonctionneront même si le classement effectif est compatible avec les caractères supplémentaires, et devraient fonctionner de la même manière sur toutes les versions de SQL Server, au moins aussi tôt qu'en 2005 (mais cela fonctionnerait probablement aussi dans SQL Server 2000 également).
Exemple:
💩
MISE À JOUR
Vous pouvez utiliser l'iTVF suivant pour obtenir les valeurs de la paire de substitution (dans les deux
INT
etBINARY
sous forme) à partir de n'importe quel point de code entre 65536 - 1114111 (0x010000 - 0x10FFFF). Et, tandis que le paramètre d'entrée est de typeINT
, vous pouvez passer sous la forme binaire / hexadécimale du point de code et il sera implicitement converti en la valeur entière correcte.En utilisant la fonction ci-dessus, les deux requêtes suivantes:
les deux renvoient les éléments suivants:
MISE À JOUR 2: Une mise à jour encore meilleure!
J'ai adapté l'iTVF illustré ci-dessus pour renvoyer maintenant 188 657 points de code, vous n'avez donc pas besoin de l'adapter à une valeur particulière. Bien sûr, étant un TVF, vous pouvez ajouter une
WHERE
clause pour filtrer sur un point de code particulier, ou une plage de points de code, ou "caractères similaires", etc. Et, il comprend des colonnes supplémentaires avec des séquences d'échappement pré-formatées pour construire chaque code point (à la fois BMP et caractères supplémentaires) en T-SQL, HTML et style C (c'est-à-dire\xHHHH
). Lisez tout a propos de ça ici:Astuce SSMS # 3: Accédez / recherchez facilement TOUS les caractères Unicode (Oui, y compris les Emojis 😸)
la source