Automatische Übersetzung beim Konvertieren von Unicode in Nicht-Unicode / NVARCHAR in VARCHAR


8

Der Unicode-Codepunkt 9619 ist ein Zeichen namens "Dunkler Schatten": ( http://unicode-table.com/de/search/?q=9619 ).

Bei Verwendung der SQL_Latin1_General_CP1_CI_ASCodepage Kollatierung und 1252 würde ich erwarten, dass das Umwandeln / Konvertieren dieses Unicode-Zeichens in einen Nicht-Unicode-Datentyp zu einem Fragezeichen ( ?) führt, da die Codepage 1252 dieses Zeichen nicht zu enthalten scheint und dies anscheinend SQL Server ist Verhalten, wenn keine Konvertierung stattfinden kann.

Meine Frage lautet also: Warum konvertiert SQL Server dieses Zeichen in einen ASCII-Code 166, der "Pipe, Broken Vertical Bar" lautet : ¦?

SELECT NCHAR(9619), CAST(NCHAR(9619) AS CHAR(1)), ASCII(CAST(NCHAR(9619) AS CHAR(1)))

3
SQL Server verwendet die in diesem Dokument als homoglyphisch bezeichnete Transformation und konvertiert häufig Zeichen, die nicht dargestellt werden können, in nahezu äquivalente Zeichen. Zum Beispiel den Akzent eines Zeichens verlieren oder intelligente Anführungszeichen in einfache Anführungszeichen ändern. Ich bin damit einverstanden, dass das nicht sehr genau aussieht! Ich bin nicht sicher, ob oder wo diese Transformationen dokumentiert sind.
Martin Smith

Wow, hatte keine Ahnung ... Herrgott, scheint einfach nicht richtig zu sein ... es ist nicht der gleiche Charakter. Warum nicht einfach ein "... oops, kein solches Zeichen in dieser Codepage gefunden ..." und die Konvertierung nicht bestehen?
Henry Lee

1
Ich habe gerade diese Seite gelesen und mich daran erinnert. Ich bin mir nicht sicher, ob SQL Server genau dieselben "Best-Fit" -Algorithmen verwendet.
Martin Smith

1
@MartinSmith bezüglich der Ungewissheit, ob die Zuordnungen für SQL Server am besten passen, lesen Sie bitte meine Antwort unten, da ich diese Zuordnungen gefunden habe :-).
Solomon Rutzky

Antworten:


8

Warum konvertiert SQL Unicode 9619 in ASCII-Code 166?

SQL Server verwendet hier keine spezielle benutzerdefinierte Logik. Für die Konvertierung werden Standardbetriebssystemdienste verwendet.

Insbesondere sqlTsEsruft der SQL Server-Typ und Ausdrucksdienst ( ) die Betriebssystemroutine WideCharToMultiBytein auf kernel32.dll. SQL Server setzt die Eingabeparameter WideCharToMultiByteso, dass die Routine eine 'schnelle Übersetzung' durchführt. Dies ist schneller als die Anforderung, dass ein bestimmtes Standardzeichen verwendet wird, wenn keine direkte Übersetzung vorhanden ist.

Die schnelle Übersetzung basiert auf der Zielcodepage, um eine optimale Anpassung für nicht übereinstimmende Zeichen durchzuführen , wie in dem Link erwähnt, den Martin Smith in einem Kommentar zur Frage angegeben hat:

Die Best-Fit-Strategien variieren für verschiedene Codepages und sind nicht detailliert dokumentiert.

Wenn die Eingabeparameter für eine schnelle Übersetzung festgelegt sind, wird WideCharToMultiByteder Betriebssystemdienst GetMBNoDefault( Quelle ) aufgerufen . Die Überprüfung des SQL Server-Aufrufstapels bei der Durchführung der in der Frage angegebenen Konvertierung bestätigt Folgendes:

SQL Server-Stack-Trace


7

Bei der Konvertierung von Unicode-Daten in eine bestimmte Codepage wird die sogenannte "Best-Fit" -Strategie verwendet (wie in der Antwort von @ Paul und in dem Link angegeben, den @Martin in einem Kommentar zur Frage vermerkt hat). Laut dieser MSDN-Seite für die Zeichenkodierung in .NET Framework :

Die Best-Fit-Zuordnung ist das Standardverhalten für ein Codierungsobjekt, das Unicode-Daten in Codepage-Daten codiert ...

Aber was genau sind diese Zuordnungen? Das MSDN - Seite verwendet die folgende angeben:

Die Best-Fit-Strategien variieren für verschiedene Codepages und sind nicht detailliert dokumentiert.

Das war jedoch nicht ganz richtig. Möglicherweise sind die "Strategien" zur Bestimmung der Zuordnungen nicht genau dokumentiert. OK. Die Zuordnungen selbst sind jedoch dokumentiert, nur nicht an den am einfachsten zu findenden Orten.

Dank Microsoft, das die Dokumentation auf GitHub verschoben hat, wird auf dieser Seite nun Folgendes angezeigt (weil ich sie aktualisiert habe 😸):

Best-Fit-Strategien werden nicht detailliert dokumentiert. Auf der Website des Unicode-Konsortiums sind jedoch mehrere Codepages dokumentiert . In der Datei readme.txt in diesem Ordner finden Sie eine Beschreibung der Interpretation der Zuordnungsdateien.

Wenn Sie zur folgenden URL gehen, wird eine Liste mit mehreren Dateien angezeigt, die jeweils nach der Codepage benannt sind, der Unicode-Zeichen zugeordnet sind:

ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/

Die meisten Dateien wurden zuletzt am 04.10.2006 aktualisiert (oder zumindest dort abgelegt), und eine davon wurde am 14.03.2012 aktualisiert. Der erste Teil dieser Dateien ordnet ASCII-Codes einem entsprechenden Unicode-Codepunkt zu. Der zweite Teil jeder Datei ordnet die Unicode-Zeichen jedoch ihren ASCII-Äquivalenten zu.

Ich habe ein Testskript geschrieben, das die Codezuordnungen verwendet, um zu überprüfen, ob SQL Server diese Zuordnungen wirklich verwendet. Dies kann durch Beantwortung dieser beiden Fragen festgestellt werden:

  1. Konvertiert SQL Server die zugeordneten Codepunkte in die angegebenen Zuordnungen?
  2. Konvertiert SQL Server für alle nicht zugeordneten Codepunkte einen von ihnen in ein Nicht- ?Zeichen.

Das Testskript ist zu lang, um es hier zu platzieren. Deshalb habe ich es auf Pastebin veröffentlicht unter:

Zuordnungen von Unicode zu Codepage in SQL Server

Durch Ausführen des Skripts wird angezeigt, dass die Antwort auf die erste Frage oben "Ja" lautet (was bedeutet, dass alle bereitgestellten Zuordnungen eingehalten werden). Es wird auch gezeigt, dass die Antwort auf die zweite Frage "Nein" lautet (was bedeutet, dass keiner der nicht zugeordneten Codepunkte in etwas anderes als das Zeichen für "unbekannt" umgewandelt wird). Daher ist diese Zuordnungsdatei sehr genau :-).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.