Как решить для pyodbc.ProgrammingError: второй параметр для executemany не должен быть пустым

#oracle #python-3.7 #pyodbc

#Oracle #python-3.7 #pyodbc

Вопрос:

Привет, у меня возникла проблема с передачей данных из одной базы данных в другую. Я создал список, используя поле в таблице в базе данных msql, использовал этот список для запроса и таблицы oracle db (используя начальный список в операторе where для фильтрации результатов) Затем я загружаю результаты запроса обратно в базу данных msql.

Программа выполняется в течение первых нескольких итераций, но затем выдает ошибку со следующей ошибкой ( Трассировка (последний последний вызов): File «C:/Users/1/PycharmProjects/DataExtracts/BuyerGroup.py «, строка 67, в файле insertIntoMSDatabase(idString) «C:/Users/1/PycharmProjects/DataExtracts/BuyerGroup.py «, строка 48, в insertIntoMSDatabase mycursor.executemany(sql, val) pyodbc.ProgrammingError: второй параметр для executemany не должен быть пустым.)

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

 # import libraries
import cx_Oracle
import pyodbc
import logging
import time
import re
import math
import numpy as np

logging.basicConfig(level=logging.DEBUG)

conn = pyodbc.connect('''Driver={SQL Server Native Client 11.0};
                         Server='servername';
                         Database='dbname';
                         Trusted_connection=yes;''')
b = conn.cursor()
dsn_tns = cx_Oracle.makedsn('Hostname', 'port', service_name='name')
conn1 = cx_Oracle.connect(user=r'uid', password='pwd', dsn=dsn_tns)
c = conn1.cursor()

beginTime = time.time()

bind = (b.execute('''select distinct field1
                     from [server].[db].[dbo].[table]'''))
print('MSQL table(s) queried, List Generated')

# formats ids for sql string
def surroundWithQuotes(id):
    return "'"   re.sub(",|s$", "", str(id))   "'"

def insertIntoMSDatabase(idString):
    osql = '''SELECT distinct field1, field2
                FROM Database.Table
                WHERE field2 is not null and field3 IN ({})'''.format(idString)
    c.execute(osql)
    claimsdata = c.fetchall()
    print('Oracle table(s) queried, Data Pulled')

    mycursor = conn.cursor()
    sql = '''INSERT INTO [dbo].[tablename] 
                (
                 [fields1]
                ,[field2]
                )
            VALUES (?,?)'''

    val = claimsdata
    mycursor.executemany(sql, val)
    conn.commit()

ids = []
formattedIdStrings = []

# adds all the ids found in bind to an iterable array
for row in bind:
    ids.append(row[0])

# splits the ids[] array into multiple arrays < 1000 in length
batchedIds = np.array_split(ids, math.ceil(len(ids) / 1000))

# formats the value inside each batchedId to be a string
for batchedId in batchedIds:
    formattedIdStrings.append(",".join(map(surroundWithQuotes, batchedId)))

# runs insert into MS database for each batch of IDs
for idString in formattedIdStrings:
    insertIntoMSDatabase(idString)

print("MSQL table loaded, Data inserted into destination")

endTime = time.time()

print("Program Time Elapsed: ",endTime-beginTime)

conn.close()
conn1.close()
 

Комментарии:

1. SQL Server != Oracle

2. Похоже, вам нужно проверить, является ли val (a.k.a. claimsdata ) пустым списком (как это произошло бы, если бы SELECT не возвращал строк), и не вызывать .executemany() , если это так.

3. В дополнение к другим предложениям, с помощью cx_Oracle попробуйте использовать переменные привязки, чтобы остановить атаки безопасности SQL-инъекций, к которым может быть уязвима ваша конкатенация строк (а привязки также могут повысить производительность), см. Раздел Привязка нескольких значений к предложению SQL WHERE IN . И настройте передачу данных с помощью arraysize и prefetchrows, см. Настройка производительности выборки .

4. я ввел тест, как предложил @GordThompson, и он решил проблему, если len(val) < 1: conn.commit() else: mycursor.executemany(sql, val) conn.commit()

Ответ №1:

mycursor.executemany(sql, val)

pyodbc.ProgrammingError: второй параметр для executemany не должен быть пустым.

Перед вызовом .executemany() вам необходимо убедиться, что val это не пустой список (как было бы в случае, если .fetchall() вызывается оператор SELECT, который не возвращает строк), например,

 if val:
    mycursor.executemany(sql, val)