sql >> Database >  >> RDS >> Sqlserver

pyodbc op linux gebruiken om unicode- of utf-8-tekens in een nvarchar mssql-veld in te voegen

Ik kan me herinneren dat ik dit soort stomme problemen had met het gebruik van odbc-stuurprogramma's, zelfs als het destijds een java+oracle-combinatie was.

Het belangrijkste is dat het odbc-stuurprogramma blijkbaar de queryreeks codeert wanneer deze naar de DB wordt verzonden. Zelfs als het veld Unicode is en als u Unicode opgeeft, lijkt het in sommige gevallen niet uit te maken.

U moet ervoor zorgen dat wat door het stuurprogramma wordt verzonden, dezelfde codering heeft als uw database (niet alleen de server, maar ook de database). Anders krijg je natuurlijk funky karakters omdat de client of de server dingen door elkaar haalt bij het coderen/of decoderen. Heb je enig idee van de charset (codepunt zoals MS dat graag zegt) die je server als standaard gebruikt voor het decoderen van gegevens?

Collatie heeft niets te maken met dit probleem :)

Zie die MS-pagina bijvoorbeeld. Voor Unicode-velden wordt sortering alleen gebruikt om de sorteervolgorde in de kolom te definiëren, niet om aan te geven hoe de gegevens worden opgeslagen.

Als u uw gegevens opslaat als Unicode, is er een unieke manier om deze weer te geven, dat is het doel van Unicode:u hoeft geen tekenset te definiëren die compatibel is met alle talen die u gaat gebruiken :)

De vraag hier is "wat gebeurt er als ik gegevens aan de server geef die niet zijn?" Unicode?". Bijvoorbeeld:

  • Als ik een UTF-8-string naar de server stuur, hoe wordt deze dan begrepen?
  • Als ik een UTF-16-string naar de server stuur, hoe wordt deze dan begrepen?
  • Als ik een Latin1-string naar de server stuur, hoe wordt deze dan begrepen?

Vanuit het perspectief van de server zijn al deze 3 strings slechts een stroom van bytes. De server kan de codering waarin u ze heeft gecodeerd niet raden. Wat betekent dat u zal problemen krijgen als uw odbc-client uiteindelijk bytesstrings verstuurt (een gecodeerde string) naar de server in plaats van unicode te sturen data:als je dat doet, zal de server een vooraf gedefinieerde codering gebruiken (dat was mijn vraag:welke codering zal de server gebruiken? Aangezien het niet gissen is, moet het een parameterwaarde zijn), en als de string was gecodeerd met een verschillende codering, dzing , gegevens worden beschadigd.

Het is precies hetzelfde als doen 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')

Probeer het gewoon. Het is leuk. De gedecodeerde string zou "Hey my name is André" moeten zijn, maar is "Hey my name is Andrテゥ". é wordt vervangen door Japans テゥ

Vandaar mijn suggestie:je moet ervoor zorgen dat pyodbc de gegevens rechtstreeks als Unicode kan verzenden. Als pyodbc dit niet doet, krijg je onverwachte resultaten.

En ik beschreef het probleem op de manier van Client naar Server. Maar dezelfde soort problemen kunnen optreden bij het terug communiceren van de server naar de client. Als de klant de Unicode-gegevens niet begrijpt, krijgt u waarschijnlijk problemen.

FreeTDS verwerkt Unicode voor u.

Eigenlijk regelt FreeTDS de zaken voor u en vertaalt alle gegevens naar UCS2 unicode. (Bron ).

  • Server <--> FreeTDS:UCS2-gegevens
  • FreeTDS <--> pyodbc :gecodeerde tekenreeksen, gecodeerd in UTF-8 (van /etc/freetds/freetds.conf )

Dus ik zou verwachten dat uw toepassing correct werkt als u UTF-8-gegevens doorgeeft aan pyodbc. In feite, zoals dit django-pyodbc-ticket staten, django-pyodbc communiceert in UTF-8 met pyodbc, dus het zou goed moeten komen.

FreeTDS 0,82

Echter, cramm0 zegt dat FreeTDS 0.82 niet volledig bugvrij is en dat er significante verschillen zijn tussen 0.82 en de officiële gepatchte 0.82-versie die gevonden kan worden hier . U moet waarschijnlijk proberen de gepatchte FreeTDS

. te gebruiken

Bewerkt :oude gegevens verwijderd, die niets met FreeTDS te maken hadden, maar alleen relevant waren voor de commerciële odbc-driver van Easysoft. Sorry.



  1. 2 manieren om niet-numerieke waarden in SQLite te retourneren

  2. Waarom wordt de uitvoeringstijd van de opgeslagen procedure in Oracle aanzienlijk verlengd, afhankelijk van hoe deze wordt uitgevoerd?

  3. RAC installeren voor een database met gegevensbestanden

  4. eenvoudige sql-query, resultaten combineren en delen