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

usando pyodbc su Linux per inserire caratteri unicode o utf-8 in un campo nvarchar mssql

Ricordo di aver avuto questo tipo di stupidi problemi usando i driver odbc, anche se quella volta era una combinazione java+oracle.

La cosa fondamentale è che il driver odbc apparentemente codifica la stringa di query quando la invia al DB. Anche se il campo è Unicode e se fornisci Unicode, in alcuni casi non sembra avere importanza.

È necessario assicurarsi che ciò che viene inviato dal driver abbia la stessa codifica del database (non solo server, ma anche database). Altrimenti, ovviamente ottieni caratteri stravaganti perché il client o il server stanno mescolando le cose durante la codifica/o la decodifica. Hai idea del charset (codepoint come dice MS) che il tuo server sta usando come predefinito per la decodifica dei dati?

Il confronto non ha nulla a che fare con questo problema :)

Vedi quella pagina MS Per esempio. Per i campi Unicode, le regole di confronto vengono utilizzate solo per definire l'ordinamento nella colonna, non per specificare come vengono archiviati i dati.

Se memorizzi i tuoi dati come Unicode, c'è un modo unico per rappresentarli, questo è lo scopo di Unicode:non è necessario definire un set di caratteri compatibile con tutte le lingue che utilizzerai :)

La domanda qui è "cosa succede quando fornisco dati al server che non sono". Unicode?". Ad esempio:

  • Quando invio una stringa UTF-8 al server, come la capisce?
  • Quando invio una stringa UTF-16 al server, come la capisce?
  • Quando invio una stringa Latin1 al server, come la capisce?

Dal punto di vista del server, tutte queste 3 stringhe sono solo un flusso di byte. Il server non può indovinare la codifica in cui li hai codificati. Ciò significa che farai ottenere problemi se il tuo client odbc finisce per inviare stringhe di byte (una stringa codificata) al server invece di inviare unicode data:se lo fai, il server utilizzerà una codifica predefinita (questa era la mia domanda:quale codifica utilizzerà il server? Poiché non è indovinato, deve essere un valore di parametro) e se la stringa era stata codificata utilizzando un codifica diversa, dzing , i dati verranno danneggiati.

È esattamente simile a come 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')

Provalo. È divertente. La stringa decodificata dovrebbe essere "Hey, mi chiamo André", ma è "Hey, mi chiamo Andrテゥ". é viene sostituito dal giapponese テゥ

Da qui il mio suggerimento:devi assicurarti che pyodbc sia in grado di inviare direttamente i dati come Unicode. Se pyodbc non riesce a farlo, otterrai risultati imprevisti.

E ho descritto il problema nel modo Client to Server. Ma lo stesso tipo di problemi può sorgere quando si comunica dal server al client. Se il Cliente non è in grado di comprendere i dati Unicode, probabilmente avrai problemi.

FreeTDS gestisce Unicode per te.

In realtà, FreeTDS si occupa delle cose per te e traduce tutti i dati in UCS2 unicode. (Fonte ).

  • Server <--> FreeTDS:dati UCS2
  • FreeTDS <--> pyodbc :stringhe codificate, codificate in UTF-8 (da /etc/freetds/freetds.conf )

Quindi mi aspetto che la tua applicazione funzioni correttamente se passi i dati UTF-8 a pyodbc. Infatti, come questo biglietto django-pyodbc afferma, django-pyodbc comunica in UTF-8 con pyodbc, quindi dovresti stare bene.

FreeTDS 0.82

Tuttavia, cramm0 afferma che FreeTDS 0.82 non è completamente privo di bug e che ci sono differenze significative tra 0.82 e la versione ufficiale 0.82 con patch che può essere trovata qui . Probabilmente dovresti provare a usare FreeTDS con patch

Modificato :rimosso i vecchi dati, che non avevano nulla a che fare con FreeTDS ma erano rilevanti solo per il driver odbc commerciale Easysoft. Scusa.