Python Cx_Oracle;Как я могу выполнить вставку SQL, используя список в качестве параметра - PullRequest
0 голосов
/ 07 февраля 2019

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

Вместо того чтобы проходить через несколько операторов execute (насколько я знаю, это возможно), я нашел эту функцию cx_Oracle, которая предположительно может выполнять все с помощью одного оператора и параметра списка.(Это также позволяет избежать неуклюжего форматирования оператора SQL перед передачей параметров) Но я думаю, что мне нужно изменить свой список перед передачей его в качестве параметра.Просто не знаю, как.

Я ссылался на эту веб-страницу: https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html

ids = getIDs()
print(ids)

[('12345',), ('24567',), ('78945',), (' 65423 ',)]

sql = """insert into scheme.newtable
     select id, data1, data2, data3
     from scheme.oldtable
      where id in (%s)"""
cursor.prepare(sql)
cursor.executemany(None, ids)

Я ожидал, что SQL-оператор будет выполняться следующим образом:

Вставить в sche.newtable select id,data1, data2, data3 из sche.oldtable где id in ('12345', '24567', '78945', '65423')

Вместо этого я получаю следующую ошибку: ORA-01036: недопустимоимя / номер переменной

Редактировать: я обнаружил этот StackOverflow: Как я могу выполнить пакетную вставку в базу данных Oracle с использованием Python? Я обновил свой код, чтобы подготовить оператор до этого, и обновилсписок элементов для кортежей, и я все еще получаю ту же ошибку.

Ответы [ 2 ]

0 голосов
/ 27 апреля 2019

использование временной таблицы для сохранения идентификаторов (пакетная вставка)

cursor.prepare('insert into temp_table values (:1)')
dictList = [{'1': x} for x in ids]
cursor.executemany(None, dictList)

, а затем вставка выбранного значения в newtable

sql="insert into scheme.newtable (selectid, data1, data2, data3 from scheme.oldtable inner join temp_table on scheme.oldtable.id = temp_table.id)"
cursor.execut(sql,connection)

сценарий создания временной таблицы в oracle

CREATE GLOBAL TEMPORARY TABLE temp_table
(
  ID  number
);
commit

Надеюсь, это полезно.

0 голосов
/ 07 февраля 2019

Вы используете executemany() для пакетного DML, например, когда вы хотите вставить большое количество значений в таблицу в качестве эффективного эквивалента выполнения нескольких операторов вставки.Есть примеры cx_Oracle, обсуждаемые в https://blogs.oracle.com/opal/efficient-and-scalable-batch-statement-execution-in-python-cx_oracle

Однако то, что вы делаете с

insert into scheme.newtable
     select id, data1, data2, data3
     from scheme.oldtable
      where id in (%s)

- это совсем другое: вы пытаетесь выполнить один оператор INSERT, используя несколько значений в предложении IN,Для этого вы должны использовать обычный execute().

Поскольку Oracle хранит данные привязки отличными от SQL, вы не можете передать несколько значений одному параметру связывания, поскольку данные обрабатываются как одна сущность SQL,не список значений.Вы можете использовать %s синтаксис подстановки строк, который у вас есть, но он открыт для атак SQL-инъекций.

Существуют различные общие методы, общие для языковых интерфейсов Oracle, см. https://oracle.github.io/node-oracledb/doc/api.html#sqlwherein для решений, которые можно переписать в синтаксис Python.

...