2015-03-31 17 views
3

Я довольно новичок в Python и на самом деле не взаимодействовал с SQL Server и XML Parsing до этого текущего проекта (возможно, даже не лучший подход). Короче говоря, моя ИТ-команда очень хорошо зарегистрирована, и мне нужно получить данные в таблице песочницы (анализируется из XML).Python/pypyODBC: Вставка строки с использованием строковых и NULL

Существует сегмент XML, который содержит атрибуты [xx] 001 - [xx] 025. Не все эти атрибуты включены для каждого XML, который я буду анализировать. Поэтому я повторяю цикл всех возможных атрибутов и добавляю результаты в список. Поскольку не все атрибуты находятся в каждом XML, я могу нести никаких типов, пытаясь представить их. Не проблема, пока не приступите к созданию моей инструкции вставки SQL, в которой они мне нужны, конвертированы в NULL. Вероятно, есть очень простой способ справиться с этим, но мой статус новичка препятствует моему прогрессу. Соответствующие фрагменты кода следуют ...

Возможно, есть лучший способ сделать это в целом? Я обеспокоен тем, что sqlList может получить только большой размер, прежде чем я удалю предел.

#this list contains Nones 
sqlList = (", ".join(map(repr,appendedList))) 

#the Nones are an issue when I get to here 
curs.execute("USE Sandbox INSERT INTO myTable VALUES (%s)" % (sqlList)) 
curs.commit() 

Вот пример того, что sqlList выглядит следующим образом:

'20_2014', '20_2014_3/25/2015 2:01 PM', 'FBR', 'A', '0', '0', '3', '1', '134', None, None, '0', None, '0', '0', '0', '0', '0', None, None, '2', None, None, None, None 

Я получаю следующее сообщение об ошибке:

pypyodbc.ProgrammingError: ('42S22', "[42S22] [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'None'.") 

ответ

5

В целом все равно хотелось бы знать, является ли это «правильным» способом для этого.

Ваше решение еще Dynamic SQL, который всегда страдает от

  • вопросов инъекций SQL (например, то, что если одна из строк содержит апостроф?)
  • типа жонглирования (например, None -> NULL, как в вашем вопросе),
  • того, чтобы использовать правильные разделители для буквальных значений (строки, даты и т.д.)

Все эти проблемы исчезают, если вы используете параметризованный запрос . В этом примере для ясности используются только 2 атрибута (вместо 25 в вашем вопросе), но принцип точно такой же. Обратите внимание, что мне не нужно ничего делать, чтобы обрабатывать значения None, чтобы они вставлялись как NULL.

import pypyodbc 
myData = [ 
    (1, 'foo'), 
    (2, None), 
    (3, 'bar'), 
    ] 
connStr = """ 
DSN=myDb_SQLEXPRESS; 
""" 
cnxn = pypyodbc.connect(connStr) 
crsr = cnxn.cursor() 
sql = """ 
INSERT INTO myTable VALUES (?, ?) 
""" 
for dataRow in myData: 
    print(dataRow) 
    crsr.execute(sql, dataRow) 
cnxn.commit() 
crsr.close() 
cnxn.close() 

Выход консоли ...

(1, 'foo') 
(2, None) 
(3, 'bar') 

... и три строки вставляются в таблицу правильно, в том числе во втором ряду на NULL (Нет).

+0

Got it. Имеет смысл сделать так. Спасибо, что ответили на вторичный/затяжной вопрос! – m3m5rr

+2

Хороший ответ.Вы также можете удалить цикл 'for' и использовать' crsr.executemany (sql, myData) '. – philshem

0

Никогда не возражаете. См. Ниже:

#this string contains Nones 
sqlList = (", ".join(map(repr,appendedList))) 

#this converts Nones to NULLs 
sqlList = sqlList.replace("None", "NULL") 

#all good now 
curs.execute("USE Sandbox INSERT INTO myTable VALUES (%s)" % (sqlList)) 
curs.commit() 

В целом хотелось бы знать, является ли это «правильным» способом для этого.

Смежные вопросы