Используя cx_Oracle, я пытаюсь использовать скрипт Python для выполнения команды sql, используя переменные связывания «plat» и «tick». При попытке выполнить эту команду выдает ошибку «ORA-24373: указана неверная длина для оператора».
Для отладки я сделал вызов SQL через Oracle (не Python), используя те же аргументы, что и мой скрипт (plat=1234567, tick='ABCDE'), и все заработало, как и ожидалось. Я попытался передать параметры как в виде словаря, так и в виде отдельных именованных переменных, но оба раза я получил одну и ту же ошибку.
Я попытался изменить значения на более низкие («1» и «A»), но даже это «недопустимая длина».
updateRecords.py
import os
import cx_Oracle
# For security reasons I cannot show my 'create_connection()' function,
# but suffice to say I have tested it and it works as desired.
...
#Setup:
WORKING_PATH = os.path.dirname(os.path.abspath(__file__))
SQL_PATH = os.path.join(WORKING_PATH, 'sql')
cnnSB = create_connection()
cnnSB_cursor = cnnSB.cursor()
...
fetchComp = open(os.path.join(SQL_PATH, 'fetchRecentEntry.sql'), 'r')
for x in range(0, 5):
cnnSB_cursor.execute(fetchComp.read(), {"plat":'A', "tick":1}) # ERROR LINE
fetchRecentEntry.sql
select *
from MFS_PCIINCEXTFUNDBYPLAT
where PLATFORM = :plat
and TICKER = :tick
and STARTDATE = (select max(STARTDATE) from MFS_PCIINCEXTFUNDBYPLAT
where PLATFORM = :plat
and TICKER = :tick)
Приведенный выше фрагмент приводит к следующему сообщению об ошибке:
File "updateRecords.py", line 297, in main
cnnSB_cursor.execute(fetchComp.read(), plat='A', tick=1)
cx_Oracle.DatabaseError: ORA-24373: invalid length specified for statement
Другие вещи, которые я проверил:
-Мой fetchComp.read() ДЕЙСТВИТЕЛЬНО возвращает желаемый код
-Передача переменных в качестве объекта dict НЕ изменяет сообщение об ошибке.
Я нашел решение: Проблема возникает из-за того, что .read() называется внутри петли. В результате он правильно прочитает файл в первый раз, но в последующих циклах будет читать только null/EOF.
Чтобы исправить это, все, что мне нужно было сделать, это установить sql.read() в переменную до цикла и использовать эту переменную вместо вызова .read() с каждым циклом.
Пример:
sql = fetchComp.read()
for index, testRow in testDF.iterrows():
cnnSB_cursor.execute(sql, tick=testRow[1], plat=testRow[0])
compDF = pd.DataFrame(cnnSB_cursor.fetchall())
У меня это "работает" (я получаю ORA-942 - было бы хорошо, если бы вы привели полный тестовый пример, дали версии и информацию об операционной системе). Вы можете проверить окончание строки и проблемы с набором символов.