sql >> Databáze >  >> RDS >> Sqlserver

pomocí pyodbc na linuxu k vložení znaků unicode nebo utf-8 do pole nvarchar mssql

Pamatuji si, že jsem měl s použitím ovladačů odbc takové hloupé problémy, i když to tehdy byla kombinace java+oracle.

Základní věcí je, že ovladač odbc zjevně kóduje řetězec dotazu při jeho odesílání do DB. I když je pole Unicode, a pokud zadáte Unicode, v některých případech se zdá, že na tom nezáleží.

Musíte zajistit, aby to, co posílá ovladač, mělo stejné kódování jako vaše databáze (nejen server, ale i databáze). Jinak samozřejmě získáte funky postavy, protože klient nebo server při kódování/nebo dekódování směšují věci. Máte nějakou představu o znakové sadě (kódový bod, jak rád říká MS), kterou váš server používá jako výchozí pro dekódování dat?

Řazení nemá s tímto problémem nic společného :)

Viz tuto stránku MS například. U polí Unicode se řazení používá pouze k definování pořadí řazení ve sloupci, nikoli k určení způsobu uložení dat.

Pokud svá data ukládáte jako Unicode, existuje jedinečný způsob, jak je reprezentovat, to je účel Unicode:není třeba definovat znakovou sadu, která je kompatibilní se všemi jazyky, které budete používat :)

Otázka zde zní:„co se stane, když serveru poskytnu data, která nejsou Unicode?". Například:

  • Jak tomu rozumí, když na server pošlu řetězec UTF-8?
  • Když na server pošlu řetězec UTF-16, jak mu rozumí?
  • Jak tomu rozumí, když na server pošlu řetězec Latin1?

Z pohledu serveru jsou všechny tyto 3 řetězce pouze proudem bajtů. Server nemůže uhodnout kódování, ve kterém jste je zakódovali. Což znamená, že budete mít potíže, pokud váš klient odbc skončí odesíláním bytestringů (zakódovaný řetězec) na server namísto odesílání unicode data:pokud tak učiníte, server použije předdefinované kódování (to byla moje otázka:jaké kódování server použije? Protože to není hádání, musí to být hodnota parametru), a pokud byl řetězec zakódován pomocí jiné kódování, dzing , data se poškodí.

Je to úplně podobné jako v Pythonu:

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')

Jen to zkus. Je to zábava. Dekódovaný řetězec má být „Hej, jmenuji se André“, ale je „Hej, jmenuji se Andrテゥ“. é je nahrazeno japonským テゥ

Proto můj návrh:musíte zajistit, aby pyodbc mohl odesílat data přímo jako Unicode. Pokud to pyodbc nedokáže, získáte neočekávané výsledky.

A problém jsem popsal způsobem Client to Server. Ale stejný druh problémů může nastat při zpětné komunikaci ze serveru na klienta. Pokud klient nerozumí datům Unicode, pravděpodobně se dostanete do problémů.

FreeTDS za vás zpracovává Unicode.

Ve skutečnosti se FreeTDS o věci postará za vás a převede všechna data do UCS2 unicode. (Zdroj ).

  • Server <--> FreeTDS :Data UCS2
  • FreeTDS <--> pyodbc :zakódované řetězce, zakódované v UTF-8 (z /etc/freetds/freetds.conf )

Takže bych očekával, že vaše aplikace bude fungovat správně, pokud předáte data UTF-8 do pyodbc. Ve skutečnosti jako tento lístek django-pyodbc stavy, django-pyodbc komunikuje v UTF-8 s pyodbc, takže byste měli být v pořádku.

FreeTDS 0,82

Nicméně cramm0 říká, že FreeTDS 0.82 není zcela bez chyb a že mezi 0.82 a oficiální opravenou verzí 0.82 jsou významné rozdíly, které lze nalézt zde . Pravděpodobně byste měli zkusit použít opravený FreeTDS

Upraveno :odstranila stará data, která neměla nic společného s FreeTDS, ale byla relevantní pouze pro komerční odbc ovladač Easysoft. Promiň.



  1. Vrácení výsledků dotazu na základě dnešního data v SQL (MySQL) část 2

  2. PHP přiřadí příkaz select k rozevíracímu seznamu hodnot

  3. Návrat časové razítko s připraveným výpisem

  4. Jaký je rozdíl mezi neopakovatelným čtením a fantomovým čtením?