Le point de code Unicode 9619 est un caractère appelé "Ombre sombre": ▓
( http://unicode-table.com/en/search/?q=9619 ).
En utilisant le SQL_Latin1_General_CP1_CI_AS
classement et la page de codes 1252, je m'attendrais à ce que la conversion / conversion de ce caractère Unicode en type de données non Unicode entraîne un point d'interrogation ( ?
) car la page de codes 1252 ne semble pas contenir ce caractère et cela semble être SQL Server. comportement lorsque la conversion ne peut pas avoir lieu.
Donc ma question est: pourquoi SQL Server convertit-il ce caractère en un code ASCII 166 qui est "Pipe, barre verticale brisée" ¦
:?
SELECT NCHAR(9619), CAST(NCHAR(9619) AS CHAR(1)), ASCII(CAST(NCHAR(9619) AS CHAR(1)))
sql-server
collation
encoding
unicode
Henry Lee
la source
la source
Réponses:
SQL Server n'utilise aucune logique personnalisée spéciale ici; il utilise les services du système d'exploitation standard pour effectuer la conversion.
Plus précisément, le type SQL Server et le service d'expression (
sqlTsEs
) appellent la routine du système d'exploitationWideCharToMultiByte
danskernel32.dll
. SQL Server définit les paramètres d'entrée deWideCharToMultiByte
telle sorte que la routine effectue une «traduction rapide». C'est plus rapide que de demander qu'un caractère par défaut spécifique soit utilisé en l'absence de traduction directe.La traduction rapide repose sur la page de code cible pour effectuer un mappage optimal pour tous les caractères sans correspondance, comme mentionné dans le lien fourni par Martin Smith dans un commentaire à la question:
Lorsque les paramètres d'entrée sont définis pour une traduction rapide,
WideCharToMultiByte
appelle le service OSGetMBNoDefault
( source ). L'inspection de la pile d'appels de SQL Server lors de la conversion spécifiée dans la question le confirme:la source
La conversion des données Unicode vers une page de codes particulière utilise ce que l'on appelle la stratégie de "meilleur ajustement" (comme indiqué dans la réponse de @ Paul et dans le lien que @Martin a noté dans un commentaire sur la question). Selon cette page MSDN pour le codage de caractères dans le .NET Framework :
Mais que sont exactement ces mappages? Cette page MSDN utilisé pour communiquer ce qui suit:
Cependant, ce n'était pas tout à fait exact. Peut-être que les "stratégies" pour déterminer les mappages ne sont pas exactement documentées. D'accord. Mais, les mappages eux - mêmes sont documentés, mais pas dans les endroits les plus faciles à trouver.
Donc, grâce à Microsoft qui a déplacé la documentation vers GitHub, cette page indique maintenant ce qui suit (parce que je l'ai mise à jour 😸):
Si vous accédez à l'URL suivante, vous verrez une liste de plusieurs fichiers, chacun nommé pour la page de codes à laquelle il mappe les caractères Unicode:
ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/
La plupart des fichiers ont été mis à jour pour la dernière fois (ou du moins y ont été placés) le 2006-10-04, et l'un d'eux a été mis à jour le 2012-03-14. La première partie de ces fichiers mappe les codes ASCII dans un point de code Unicode équivalent. Mais la deuxième partie de chaque fichier mappe les caractères Unicode dans leurs "équivalents" ASCII.
J'ai écrit un script de test qui utilise les mappages de la page de code 1252 pour vérifier si SQL Server utilise vraiment ces mappages. Cela peut être déterminé en répondant à ces deux questions:
?
"?Le script de test est trop long pour être placé ici, donc je l'ai posté sur Pastebin à:
Mappages Unicode vers la page de codes dans SQL Server
L'exécution du script montrera que la réponse à la première question ci-dessus est "Oui" (ce qui signifie que tous les mappages fournis sont respectés). Cela montrera également que la réponse à la deuxième question est "Non" (ce qui signifie qu'aucun des points de code non mappés ne se transforme en autre chose que le caractère "inconnu"). Par conséquent, ce fichier de mappage est très précis :-).
la source