à l'aide de pyodbc sur linux pour insérer unicode ou utf-8, les caractères d'un type nvarchar mssql champ
Je suis en utilisant Ubuntu 9.04
J'ai installé le package suivant les versions:
unixodbc and unixodbc-dev: 2.2.11-16build3
tdsodbc: 0.82-4
libsybdb5: 0.82-4
freetds-common and freetds-dev: 0.82-4
J'ai configuré /etc/unixodbc.ini
comme ceci:
[FreeTDS]
Description = TDS driver (Sybase/MS SQL)
Driver = /usr/lib/odbc/libtdsodbc.so
Setup = /usr/lib/odbc/libtdsS.so
CPTimeout =
CPReuse =
UsageCount = 2
J'ai configuré /etc/freetds/freetds.conf
comme ceci:
[global]
tds version = 8.0
client charset = UTF-8
J'ai attrapé pyodbc révision 31e2fae4adbf1b2af1726e5668a3414cf46b454f
de http://github.com/mkleehammer/pyodbc
et installé à l'aide de "python setup.py install
"
J'ai une machine windows avec Microsoft SQL Server 2000 installé sur mon réseau local, et l'écoute sur l'adresse ip locale 10.32.42.69. J'ai une base de données vide créé avec le nom "Commun". J'ai de l'utilisateur "sa" mot de passe "secret" avec plein de privilèges.
Je suis en utilisant le code python suivant la configuration de la connexion:
import pyodbc
odbcstring = "SERVER=10.32.42.69;UID=sa;PWD=secret;DATABASE=Common;DRIVER=FreeTDS"
con = pyodbc.connect(s)
cur = con.cursor()
cur.execute('''
CREATE TABLE testing (
id INTEGER NOT NULL IDENTITY(1,1),
name NVARCHAR(200) NULL,
PRIMARY KEY (id)
)
''')
con.commit()
Tout ŒUVRES jusqu'à ce point. J'ai utilisé sql server Enterprise Manager sur le serveur et la nouvelle table est là.
Maintenant, je veux insérer des données sur la table.
cur = con.cursor()
cur.execute('INSERT INTO testing (name) VALUES (?)', (u'something',))
Qui tombe en panne!! Voici l'erreur que je reçois:
pyodbc.Error: ('HY004', '[HY004] [FreeTDS][SQL Server]Invalid data type
(0) (SQLBindParameter)'
Depuis mon client est configuré pour utiliser l'UTF-8, j'ai pensé que je pourrais résoudre par le codage des données en UTF-8. Ce qui fonctionne, mais, ensuite, je reviens étrange de données:
cur = con.cursor()
cur.execute('DELETE FROM testing')
cur.execute('INSERT INTO testing (name) VALUES (?)', (u'somé string'.encode('utf-8'),))
con.commit()
# fetching data back
cur = con.cursor()
cur.execute('SELECT name FROM testing')
data = cur.fetchone()
print type(data[0]), data[0]
Qui ne donne pas d'erreur, mais les données retournées ne sont pas les mêmes données envoyées! J'obtiens:
<type 'unicode'> somé string
Qui est, pyodbc de ne pas accepter une unicode objet directement, mais il renvoie unicode objets de dos pour moi! Et l'encodage est mélangé!
Maintenant, pour la question:
Je veux le code pour insérer des données unicode dans un NVARCHAR et/ou NTEXT champ. Quand j'ai une requête en arrière, je veux les mêmes données que j'ai inséré.
Qui peuvent être en configurant le système différemment, ou par l'utilisation d'une fonction wrapper capable de convertir correctement les données de/vers l'unicode lors de l'insertion ou de la récupération de
Qui ne demande pas beaucoup, est-il?
Vous devez vous connecter pour publier un commentaire.
Je me souviens d'avoir ce genre de problèmes stupides à l'aide de pilotes odbc, même si cette fois, c'était un java+oracle combinaison.
La base, c'est que le pilote odbc apparemment codant pour la chaîne de requête lors de l'envoi à la DB. Même si le champ est de l'Unicode, et si vous fournissez Unicode, dans certains cas, il ne semble pas à la matière.
Vous devez vous assurer que ce qui est envoyé par le pilote qui a le même encodage que votre Base de données (non seulement le serveur, mais aussi de la base de données). Sinon, bien sûr, vous obtenez funky caractères, soit parce que le client ou le serveur est un mélange de choses lors de l'encodage/ou de décodage. Avez-vous une idée de ce jeu de caractères (codepoint que MS comme pour dire) que votre serveur utilise comme valeur par défaut pour le décodage des données?
Classement n'a rien à voir avec ce problème 🙂
Voir que MME page par exemple. Pour les champs Unicode, le classement est uniquement utilisé pour définir l'ordre de tri dans la colonne, pas pour spécifier la façon dont les données sont stockées.
Si vous stockez vos données en Unicode, il y a une façon Unique de le représenter, c'est le but de l'Unicode: pas besoin de définir un jeu de caractères compatible avec toutes les langues que vous allez utiliser 🙂
La question ici est "ce qui se passe quand je donne des données vers le serveur qui est pas Unicode?". Par exemple:
À partir du serveur de point de vue, l'ensemble de ces 3 chaînes sont seulement un flux d'octets. Le serveur ne peut pas deviner l'encodage dans lequel vous avez encodé eux. Ce qui signifie que vous sera rencontrez des problèmes si votre client odbc finit par l'envoi d' bytestrings (une chaîne codée) sur le serveur au lieu de les envoyer unicode de données: si vous le faites, le serveur va utiliser un encodage prédéfini (c'était ma question: quel codage le serveur va utiliser? Depuis qu'il est pas de deviner, il doit être la valeur d'un paramètre), et si la chaîne a été codé à l'aide d'un codage différent, dzing, les données corrompus.
C'est exactement pareil que de faire en Python:
Il suffit de l'essayer. C'est le fun. La chaîne décodée est censé être "Hey mon nom est André", mais est "Hey mon nom est Andrテゥ". é est remplacé par le Japonais テゥ
D'où ma suggestion: vous devez vous assurer que pyodbc est capable d'envoyer directement les données au format Unicode. Si pyodbc omet de le faire, vous obtiendrez des résultats inattendus.
Et que j'ai décrit le problème dans le Serveur vers le Client moyen. Mais le même genre de questions peuvent se poser lors de la communication depuis le Serveur vers le Client. Si le Client ne peut pas comprendre de données Unicode, vous obtiendrez probablement des ennuis.
FreeTDS gère l'Unicode pour vous.
En fait, FreeTDS prend soin des choses pour vous et traduit toutes les données à UCS2 unicode. (Source).
/etc/freetds/freetds.conf
)Donc je m'attends à votre application de fonctionner correctement si vous transmettez des données UTF-8 pour pyodbc. En fait, comme ce django-pyodbc billet unis, django-pyodbc communique en UTF-8 avec pyodbc, de sorte que vous devriez être bien.
FreeTDS 0.82
Cependant, cramm0 dit que FreeTDS 0.82 n'est pas complètement sans bugs, et qu'il existe d'importantes différences entre 0,82 et l'officiel patché 0.82 version qui peut être trouvé ici. Vous devriez probablement essayer d'utiliser le patché FreeTDS
Édité: supprimé les anciennes données, qui n'avait rien à voir avec FreeTDS mais n'est pertinente que pour Easysoft commercial pilote odbc. Désolé.
- Je utiliser UCS-2 pour interagir avec SQL Server, pas en UTF-8.
Correction: j'ai changé la .freetds.conf entrée de sorte que le client utilise l'UTF-8
Maintenant, lier les valeurs beau travail pour codé en UTF-8 cordes.
Le pilote convertit de manière transparente entre l'UCS-2, utilisé pour le stockage sur le dataserver côté et de l'UTF-8 chaînes de donnée/pris de la part du client.
C'est avec pyodbc 2.0 sur Solaris 10 running Python 2.5 et FreeTDS freetds-0.82.1.dev.20081111 et SQL Server 2008
Voici le résultat de la table de test (j'ai dû les mettre manuellement dans un tas de données de test en passant par le Management Studio)
J'ai été en mesure de mettre certains dans des points de code unicode directement dans la table de Gestion de Studio par le "Modifier" Top 200 "des lignes de dialogue" et en entrant les chiffres hexadécimaux pour le point de code unicode, puis en appuyant sur Alt-X
J'ai eu le même problème lorsque vous essayez de lier unicode paramètre:
'[HY004] [FreeTDS][SQL Server]Invalid type de données (0) (SQLBindParameter)'
Je l'ai résolu par la mise à niveau de freetds à la version 0.91.
- Je utiliser pyodbc 2.1.11. J'ai du mettre cette patch pour le faire fonctionner avec unicode, sinon je recevais une corruption de la mémoire des erreurs de temps en temps.
Êtes-vous sûr que c'est INSÉRER à l'origine du problème, de ne pas le lire?
Il y a un bug ouvert sur pyodbc Problème de l'extraction de NTEXT et de données NVARCHAR.