sql >> Database teknologi >  >> RDS >> Sqlserver

bruge pyodbc på linux til at indsætte unicode eller utf-8 tegn i et nvarchar mssql felt

Jeg kan huske, at jeg havde den slags dumme problemer med at bruge odbc-drivere, selvom det dengang var en kombination af java+oracle.

Kernen er, at odbc-driveren tilsyneladende koder forespørgselsstrengen, når den sendes til DB. Selvom feltet er Unicode, og hvis du angiver Unicode, lader det i nogle tilfælde ikke til at have nogen betydning.

Du skal sikre dig, at det, der sendes af driveren, har samme kodning som din database (ikke kun server, men også database). Ellers får du selvfølgelig funky karakterer, fordi enten klienten eller serveren blander tingene sammen ved kodning/eller afkodning. Har du nogen idé om det tegnsæt (kodepunkt som MS vil sige), som din server bruger som standard til afkodning af data?

Samling har intet at gøre med dette problem :)

Se den MS-side for eksempel. For Unicode-felter bruges sortering kun til at definere sorteringsrækkefølgen i kolonnen, ikke for at angive, hvordan dataene opbevares.

Hvis du gemmer dine data som Unicode, er der en unik måde at repræsentere dem på, det er formålet med Unicode:ingen grund til at definere et tegnsæt, der er kompatibelt med alle de sprog, du skal bruge :)

Spørgsmålet her er "hvad sker der, når jeg giver data til serveren, der ikke er Unicode?". For eksempel:

  • Når jeg sender en UTF-8-streng til serveren, hvordan forstår den det så?
  • Når jeg sender en UTF-16-streng til serveren, hvordan forstår den det så?
  • Når jeg sender en Latin1-streng til serveren, hvordan forstår den det så?

Fra serverperspektivet er alle disse 3 strenge kun en strøm af bytes. Serveren kan ikke gætte den kodning, som du kodede dem i. Hvilket betyder, at du vil får problemer, hvis din odbc-klient ender med at sende bytestrings (en kodet streng) til serveren i stedet for at sende unicode data:hvis du gør det, vil serveren bruge en foruddefineret kodning (det var mit spørgsmål:hvilken kodning vil serveren bruge? Da det ikke er gæt, skal det være en parameterværdi), og hvis strengen var blevet kodet ved hjælp af en anden kodning, dzing , vil data blive beskadiget.

Det er nøjagtigt det samme som at gøre 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')

Bare prøv det. Det er sjovt. Den afkodede streng formodes at være "Hey, mit navn er André", men er "Hey, mit navn er Andrテゥ". é bliver erstattet af japansk テゥ

Derfor mit forslag:du skal sikre dig, at pyodbc er i stand til at sende dataene direkte som Unicode. Hvis pyodbc ikke gør dette, vil du få uventede resultater.

Og jeg beskrev problemet på klient til server måde. Men den samme slags problemer kan opstå, når der kommunikeres tilbage fra serveren til klienten. Hvis klienten ikke kan forstå Unicode-data, vil du sandsynligvis få problemer.

FreeTDS håndterer Unicode for dig.

Faktisk tager FreeTDS sig af tingene for dig og oversætter alle data til UCS2 unicode. (Kilde ).

  • Server <--> FreeTDS :UCS2-data
  • FreeTDS <--> pyodbc :kodede strenge, kodet i UTF-8 (fra /etc/freetds/freetds.conf )

Så jeg forventer, at din applikation fungerer korrekt, hvis du sender UTF-8-data til pyodbc. Faktisk som denne django-pyodbc-billet stater, kommunikerer django-pyodbc i UTF-8 med pyodbc, så du burde have det fint.

FreeTDS 0,82

Men cramm0 siger, at FreeTDS 0.82 ikke er fuldstændig fejlfri, og at der er væsentlige forskelle mellem 0.82 og den officielle patchede 0.82-version, der kan findes her . Du skal nok prøve at bruge den patchede FreeTDS

Redigeret :fjernede gamle data, som ikke havde noget at gøre med FreeTDS, men kun var relevante for Easysofts kommercielle odbc-driver. Undskyld.



  1. Python/Django MySQL Datetime-håndtering og tidszone

  2. hvordan man beregner det samlede antal lørdage og søndage mellem to datoer i mysql

  3. Gruppér efter kolonne og flere rækker i en række flere kolonner

  4. Gem PL/pgSQL-output fra PostgreSQL til en CSV-fil