2016-08-23 7 views
2

Я пытаюсь вставить данные, которые я извлекал из Интернета в SQL-сервер db, а соответствующие столбцы таблицы db настроены как nvarchar(max).Вставка данных escape-последовательности unicode на SQL-сервер db (pyodbc)

Тестирование это в оболочке Python:

dbargs={'DATABASE': '<mydbname>', 
'DRIVER': '{FreeTDS}', 
'PORT': '1433', 
'PWD': '<mypass>', 
'SERVER': '<server>', 
'UID': '<myusername>'} 

import pyodbc 
cnxn = pyodbc.connect(**dbargs) 
cursor = cnxn.cursor() 

insert_cmd="INSERT INTO c_master (run_id, product_name) VALUES (?,?)" 

Тогда

cursor.execute(insert_cmd, (274, u'test naméâôóòöë')) 

прекрасно работает, однако

cursor.execute(insert_cmd, (274, u'test \u2019d')) 

вызывает ошибку

ProgrammingError: ('42000', "[42000] [FreeTDS][SQL Server]Incorrect syntax near ','. (102) (SQLExecDirectW)") 

Я нахожу, что я очищаю данные последнего типа и генерирую ошибки, когда пытаюсь вставить его, как указано выше, в db в моем конвейере писателя.

Каков правильный способ обработки таких данных?

(я использую FreeTDS, UnixODBC, MSSQL Server, pyodbc)

FreeTDS и UnixODBC конф:

/etc/odbc.init:

[myserver] 
Driver = FreeTDS 
Description =Myserver MSSQL database 
# Servername corresponds to the section in freetds.conf 
Servername=myserver 
Database = mydbname 
TDS_Version = 7.0 

/и т.д./odbcinst.ini:

[ODBC] 
Trace = Yes 
TraceFile = /tmp/odbcsql.log 
ForceTrace = Yes 
Pooling = Yes 

[FreeTDS] 
Description = TDS driver (Sybase/MS SQL) 
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so 
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so 
CPTimeout = 120 
CPReuse = 

/etc/freetds/freetds.conf:

[global] 
tds version = 7.0 


dump file = /var/log/freetds.log 
debug flags = 0xffff 

# timeout = 10 
# connect timeout = 10 

text size = 64512 


[myserver] 
host = <myserverip> 
port = 1433 
tds version = 7.0 
dump_file = /var/log/freetds.log 
client charset = UTF-8 

Я также добавил TDSDUMP = "/ Var/Журнал/freetds.log" в/и т.д./окружающей среды и/и т.д./профиль. Хотя странно, я все еще не вижу журнал freetds.

+0

Howdy, несколько вопросов. Вы используете Python 2 или Python 3? Чтобы правильно использовать Unicode, вам также нужно будет пройти по «TDS_Version» к строке подключения - выполняете ли вы это в определении DSN? – FlipperPA

+0

Python 2.7. Я установил TDS_Versionin /etc/odbc.ini. Я обновлю свой вопрос, чтобы включить эти confs сейчас. – fpghost

+0

Глядя на /tmp/freetds.log, кажется, показывает версию 4.2, несмотря на мою конфигурацию. Думаю, это может быть проблемой! Любые идеи, почему мой conf не дает мне версию 7.0? – fpghost

ответ

2

Вам необходимо передать TDS_Version в качестве части строки подключения. Вы соединяетесь с полной строкой соединения, которая обходит DSN, если вы передаете полное имя сервера в качестве СЕРВЕР в объявлении connect(). Если вы хотите подключиться к DSN, вам необходимо предоставить DSNUID/PWD), а не SERVER и PORT.

Я передал запрос тянуть, чтобы лучше объяснить TDS версии FreeTDS здесь: (! Как вы видели) https://github.com/FreeTDS/freetds/pull/71

по умолчанию версии TDS используется, если не предусмотрен не поддерживает Unicode.Предполагая, что вы используете SQL Server 2005 или более поздней версии, если вы используете:

  • FreeTDS 1,0: использование TDS_Version 7,4
  • FreeTDS 0,95: использование TDS_Version 7,3
  • FreeTDS 0,91: использование TDS_Version 7,2

Удачи!

+0

Я понимаю, что вы говорите об обходе DSN, но почему он не уважает глобальную версию freedns.conf «tds version»? – fpghost

+0

Это хороший вопрос; Я честно не знаю, но я подозреваю, что он попадает только в файл, если вы используете DSN. – FlipperPA

0

Я подозреваю, что вам необходимо настроить подключение FreeTDS для распознавания клиентской кодировки, которая будет использоваться для ваших операторов вставки.

В ODBC я не знаю, как объявить кодировку для отдельных параметров. Все текстовые и символьные данные SQL интерпретируются в соответствии с одной конфигурацией соединения с клиентским кодированием.

Вы также можете задать параметр среды TDSDUMP и посмотреть данные, отправленные на ваш сервер. Если вы этого не достигнете, попробуйте журнал ODBC.

+0

Ну, мой freetds conf настроен как версия 7.0 и клиентская кодировка = UTF-8. Как я уже сказал, большинство unicode обрабатываются по умолчанию, похоже, что это строки unicode escape, такие как 'u '\ u2019'' – fpghost

+0

Итак, я думаю, что это вещь Python:« литералы в Unicode »не определяют строки, закодированные как UTF- 8. Если вы явно конвертируете свой литерал в тип кодировки Unicode, все будет хорошо. –