Python / pypyODBC: вставка строки с использованием строк и значений NULL

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

Есть сегмент XML, который содержит атрибуты с [xx]001 по [xx]025. Не все эти атрибуты включены для каждого XML, который я буду анализировать. Поэтому я перебираю цикл всех возможных атрибутов и добавляю результаты в список. Поскольку не все атрибуты содержатся в каждом XML, я могу использовать noneTypes, пытаясь представить каждый из них. Не проблема до тех пор, пока не получится создать свой оператор вставки 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'.")

2 ответа

Решение

В общем, все еще хотел бы знать, если это "правильный" способ сделать это.

Ваше решение по-прежнему динамический 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 (Нет) во второй строке.

Не берите в голову. Увидеть ниже:

#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()

В общем, все еще хотел бы знать, если это "правильный" способ сделать это.

Другие вопросы по тегам