sql >> Databasteknik >  >> RDS >> Sqlserver

använda pyodbc på linux för att infoga unicode- eller utf-8-tecken i ett nvarchar mssql-fält

Jag kan minnas att jag hade den här typen av dumma problem med att använda odbc-drivrutiner, även om det den gången var en kombination av java+oracle.

Kärnan är att odbc-drivrutinen tydligen kodar frågesträngen när den skickas till DB. Även om fältet är Unicode, och om du tillhandahåller Unicode, verkar det i vissa fall inte spela någon roll.

Du måste se till att det som skickas av drivrutinen har samma kodning som din databas (inte bara server utan även databas). Annars får du förstås läckra tecken eftersom antingen klienten eller servern blandar ihop saker vid kodning/eller avkodning. Har du någon aning om teckenuppsättningen (kodpunkt som MS vill säga) som din server använder som standard för avkodning av data?

Sortering har ingenting att göra med det här problemet :)

Se den MS-sidan till exempel. För Unicode-fält används sortering endast för att definiera sorteringsordningen i kolumnen, inte för att ange hur data lagras.

Om du lagrar din data som Unicode finns det ett unikt sätt att representera det, det är syftet med Unicode:du behöver inte definiera en teckenuppsättning som är kompatibel med alla språk du ska använda :)

Frågan här är "vad händer när jag ger data till servern som inte är Unicode?". Till exempel:

  • När jag skickar en UTF-8-sträng till servern, hur förstår den det?
  • När jag skickar en UTF-16-sträng till servern, hur förstår den det?
  • När jag skickar en Latin1-sträng till servern, hur förstår den det?

Ur serverperspektivet är alla dessa 3 strängar bara en ström av byte. Servern kan inte gissa i vilken kodning du kodade dem. Vilket betyder att du kommer får problem om din odbc-klient slutar med att skicka bytestringar (en kodad sträng) till servern istället för att skicka unicode data:om du gör det kommer servern att använda en fördefinierad kodning (det var min fråga:vilken kodning kommer servern att använda? Eftersom det inte är gissningar måste det vara ett parametervärde), och om strängen hade kodats med en annan kodning, dzing , kommer data att skadas.

Det är exakt likadant som att göra i 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')

Bara prova det. Det är kul. Den avkodade strängen är tänkt att vara "Hey, my name is André", men är "Hey my name is Andrテゥ". é ersätts av japanska テゥ

Därav mitt förslag:du måste se till att pyodbc kan skicka data direkt som Unicode. Om pyodbc inte lyckas med detta får du oväntade resultat.

Och jag beskrev problemet på klient till server sätt. Men samma typ av problem kan uppstå när man kommunicerar tillbaka från servern till klienten. Om klienten inte kan förstå Unicode-data kommer du sannolikt att hamna i problem.

FreeTDS hanterar Unicode åt dig.

Egentligen tar FreeTDS hand om saker åt dig och översätter all data till UCS2 unicode. (Källa ).

  • Server <--> FreeTDS:UCS2-data
  • FreeTDS <--> pyodbc :kodade strängar, kodade i UTF-8 (från /etc/freetds/freetds.conf )

Så jag förväntar mig att din applikation fungerar korrekt om du skickar UTF-8-data till pyodbc. Faktum är att denna django-pyodbc-biljett stater, django-pyodbc kommunicerar i UTF-8 med pyodbc, så du borde klara dig.

FreeTDS 0.82

Men cramm0 säger att FreeTDS 0.82 inte är helt felfri, och att det finns betydande skillnader mellan 0.82 och den officiella patchade 0.82-versionen som kan hittas här . Du bör förmodligen försöka använda den korrigerade FreeTDS

Redigerad :tog bort gamla data, som inte hade något att göra med FreeTDS utan bara var relevanta för Easysofts kommersiella odbc-drivrutin. Förlåt.



  1. Hur man aktiverar SSL-anslutning på MySQL-server i Windows

  2. Hur läser och uppdaterar jag SQLite-databas med ListView i Android?

  3. [Laravel]:SQLSTATE[3F000]:Ogiltigt schemanamn

  4. Det är möjligt att anropa funktioner i ett annat schema inifrån plv8-funktioner?