Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Verwenden von Pyodbc unter Linux zum Einfügen von Unicode- oder UTF-8-Zeichen in ein nvarchar-mssql-Feld

Ich kann mich erinnern, dass ich diese Art von dummen Problemen mit odbc-Treibern hatte, auch wenn es damals eine Java+Oracle-Kombination war.

Die Kernsache ist, dass der odbc-Treiber anscheinend die Abfragezeichenfolge codiert, wenn er sie an die DB sendet. Selbst wenn das Feld Unicode ist und Sie Unicode angeben, scheint es in einigen Fällen keine Rolle zu spielen.

Sie müssen sicherstellen, dass das, was vom Treiber gesendet wird, dieselbe Codierung wie Ihre Datenbank hat (nicht nur Server, sondern auch Datenbank). Andernfalls erhalten Sie natürlich irre Zeichen, weil entweder der Client oder der Server beim Codieren/oder Decodieren Dinge durcheinander bringt. Haben Sie eine Vorstellung von dem Zeichensatz (Codepoint, wie MS gerne sagt), den Ihr Server standardmäßig zum Decodieren von Daten verwendet?

Sortierung hat mit diesem Problem nichts zu tun :)

Siehe diese MS-Seite zum Beispiel. Bei Unicode-Feldern wird die Sortierung nur verwendet, um die Sortierreihenfolge in der Spalte zu definieren, nicht um anzugeben, wie die Daten gespeichert werden.

Wenn Sie Ihre Daten als Unicode speichern, gibt es eine einzigartige Möglichkeit, sie darzustellen, das ist der Zweck von Unicode:Sie müssen keinen Zeichensatz definieren, der mit allen Sprachen kompatibel ist, die Sie verwenden werden :)

Die Frage hier ist "was passiert, wenn ich Daten an den Server gebe, die nicht sind Unicode?". Zum Beispiel:

  • Wenn ich eine UTF-8-Zeichenfolge an den Server sende, wie versteht er sie?
  • Wenn ich eine UTF-16-Zeichenfolge an den Server sende, wie versteht er sie?
  • Wenn ich einen Latin1-String an den Server sende, wie versteht er ihn?

Aus der Serverperspektive sind alle diese 3 Strings nur ein Strom von Bytes. Der Server kann die Codierung, in der Sie sie codiert haben, nicht erraten. Was bedeutet, dass Sie werden Probleme bekommen, wenn Ihr odbc-Client Bytestrings sendet (eine verschlüsselte Zeichenfolge) an den Server, anstatt unicode zu senden data:Wenn Sie dies tun, verwendet der Server eine vordefinierte Codierung (das war meine Frage:Welche Codierung wird der Server verwenden? Da es sich nicht um eine Schätzung handelt, muss es sich um einen Parameterwert handeln), und ob die Zeichenfolge mit a codiert wurde andere Kodierung, dzing , werden Daten beschädigt.

Es ist genau ähnlich wie in Python:

uni = u'Hey my name is André'
in_utf8 = uni.encode('utf-8')
# send the utf-8 data to server
# send(in_utf8)

# on server side
# server receives it. But server is Japanese.
# So the server treats the data with the National charset, shift-jis:
some_string = in_utf8 # some_string = receive()    
decoded = some_string.decode('sjis')

Probier es einfach. Es macht Spaß. Die decodierte Zeichenkette soll "Hey my name is André" lauten, ist aber "Hey my name is Andrテゥ". é wird durch Japanisch テゥ

ersetzt

Daher mein Vorschlag:Sie müssen sicherstellen, dass pyodbc die Daten direkt als Unicode senden kann. Wenn pyodbc dies nicht tut, erhalten Sie unerwartete Ergebnisse.

Und ich habe das Problem in der Client-zu-Server-Weise beschrieben. Die gleiche Art von Problemen kann jedoch bei der Rückkommunikation vom Server zum Client auftreten. Wenn der Client Unicode-Daten nicht verstehen kann, werden Sie wahrscheinlich Probleme bekommen.

FreeTDS handhabt Unicode für Sie.

Eigentlich erledigt FreeTDS die Dinge für Sie und übersetzt alle Daten in UCS2-Unicode. (Quelle ).

  • Server <--> FreeTDS :UCS2-Daten
  • FreeTDS <--> pyodbc :codierte Strings, codiert in UTF-8 (aus /etc/freetds/freetds.conf )

Ich würde also erwarten, dass Ihre Anwendung ordnungsgemäß funktioniert, wenn Sie UTF-8-Daten an pyodbc übergeben. Tatsächlich wie dieses django-pyodbc-Ticket sagt, django-pyodbc kommuniziert in UTF-8 mit pyodbc, also sollte es Ihnen gut gehen.

FreeTDS 0.82

Allerdings cramm0 sagt, dass FreeTDS 0.82 nicht vollständig fehlerfrei ist und dass es erhebliche Unterschiede zwischen 0.82 und der offiziell gepatchten Version 0.82 gibt, die unter hier . Sie sollten wahrscheinlich versuchen, das gepatchte FreeTDS

zu verwenden

Bearbeitet :Alte Daten entfernt, die nichts mit FreeTDS zu tun hatten, sondern nur für den kommerziellen odbc-Treiber von Easysoft relevant waren. Entschuldigung.