Getting the error cx_Oracle.DatabaseError: ORA-01008: not all variables bound while trying to bind the value of a list in a merge statement
Getting the error cx_Oracle.DatabaseError: ORA-01008: not all variables bound while trying to bind the value of a list in a merge statement
最近几个小时我一直在苦思冥想,但找不到根本原因。浏览了多篇文章,但没有运气。
我正在尝试合并存储在 pandas 数据框中的值。
下面是我将数据框转换为列表的代码
merchantinfo_lst = appenddata.values.tolist()
通过下面的代码,我试图将数据合并到目标中 table。
sql ='merge into bi.merchant_info_test ';
sql+=' using dual';
sql+=' on ( ATRANS_ID = :2 )';
sql+=' when matched then update set MERCHANT_INFO = :15, MESSAGE_PARAM = :16, PUBLISH_DATE = :13' ;
sql+=' when not matched then insert( ADDRESS,ATRANS_ID,CITY_NAME,COUNTRY_CODE,LATITUDE,LONGITUDE,MERCHANT_CATEGORY_CODE,MERCHANT_DESCRIPTOR,MERCHANT_ID,';
sql+=' MERCHANT_NAME,PHONE_NUMBER,POSTAL_CODE,PUBLISH_DATE,STATE_PROVINCE_CODE,MERCHANT_INFO,MESSAGE_PARAM )';
sql+=' values( :1, :2, :3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16 )';
for i in range(len(merchantinfo_lst)):
cur.execute(sql,merchantinfo_lst[i])
我收到 cx_Oracle.DatabaseError: ORA-01008: 并非所有变量都已绑定,但所有值都存在于列表中并且所有列都存在于目标 table 中。
无论我尝试什么,我都无法解决问题。
Python版本:2.7.5
cx_Oracle版本:7.3.0
目标数据库:Oracle Database 19c 企业版 Release 19.0.0.0.0
Table结构
Name Null? Type
---------------------- -------- --------------
ATRANS_ID NOT NULL RAW(36 BYTE)
MERCHANT_ID VARCHAR2(20)
MERCHANT_DESCRIPTOR VARCHAR2(100)
MERCHANT_NAME VARCHAR2(100)
ADDRESS VARCHAR2(250)
CITY_NAME VARCHAR2(100)
STATE_PROVINCE_CODE VARCHAR2(4)
POSTAL_CODE VARCHAR2(10)
COUNTRY_CODE VARCHAR2(10)
LATITUDE VARCHAR2(20)
LONGITUDE VARCHAR2(20)
PHONE_NUMBER VARCHAR2(15)
MERCHANT_CATEGORY_CODE VARCHAR2(6)
MERCHANT_INFO VARCHAR2(250)
MESSAGE_PARAM VARCHAR2(2000)
PUBLISH_DATE DATE
Python代码
def table_merge(data_frame,uname,passwd,oracle_dsn):
merchantinfo = pd.DataFrame()
transidinfo = pd.DataFrame()
ora_con = oracle_conn(uname,passwd,oracle_dsn)
cur = ora_con.cursor()
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
appenddata['MERCHANT_INFO'] = appenddata['MERCHANT_NAME']+ ' ' +appenddata['CITY_NAME']+ ' '+appenddata['STATE_PROVINCE_CODE']+ ' ' +appenddata['COUNTRY_CODE']+ ' ' +appenddata['POSTAL_CODE']
appenddata['MESSAGE_PARAM'] = appenddata['MERCHANT_ID']+ '|' + appenddata['MERCHANT_INFO']
appenddata['PUBLISH_DATE'] = dt_string
merchantinfo_lst = appenddata.values.tolist()
print('printing list')
print(merchantinfo_lst)
sql ='merge into bi.merchant_info_test ';
sql+=' using dual';
sql+=' on ( ATRANS_ID = :2 )';
sql+=' when matched then update set MERCHANT_INFO = :15, MESSAGE_PARAM = :16, PUBLISH_DATE = :13' ;
sql+=' when not matched then insert( ADDRESS,ATRANS_ID,CITY_NAME,COUNTRY_CODE,LATITUDE,LONGITUDE,MERCHANT_CATEGORY_CODE,MERCHANT_DESCRIPTOR,MERCHANT_ID,';
sql+=' MERCHANT_NAME,PHONE_NUMBER,POSTAL_CODE,PUBLISH_DATE,STATE_PROVINCE_CODE,MERCHANT_INFO,MESSAGE_PARAM )';
sql+=' values( :1, :2, :3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16 )';
for i in range(len(merchantinfo_lst)):
cur.execute(sql,merchantinfo_lst[i])
cur.close()
ora_con.commit()
ora_con.close()
输出
/home/kkant/microservice-poc % python consumer.py
printing list
[[u'dummy_address', u'123456789', u'dummy_city', u'91', u'', u'', u'2345', u'dummy', u'123', u'dummy_merchant', u'1234567890', u'123456', '27/05/2022 11:32:22', u'', u'dummy_merchant dummy_city 91 123456', u'123|dummy_merchant dummy_city 91 123456'], [u'dummy_address', u'1234567455', u'dummy_city', u'91', u'', u'', u'2345', u'dummy', u'456', u'dummy_merchant', u'1234567890', u'123456', '27/05/2022 11:32:22', u'', u'dummy_merchant dummy_city 91 123456', u'456|dummy_merchant dummy_city 91 123456']]
Traceback (most recent call last):
File "consumer.py", line 102, in <module>
table_merge(appenddata)
File "consumer.py", line 71, in table_merge
cur.execute(sql,merchantinfo_lst[i])
cx_Oracle.DatabaseError: ORA-01008: not all variables bound
[enter image description here][1]
问题是您是按位置绑定的,而不是按名称绑定的。因此,您需要为每个绑定变量位置创建一个条目。 SQL 语句第一部分中的值 :2 需要一个值,SQL 语句最后一部分中的值 :2 也需要一个值! (依此类推 SQL 语句中提到的每个绑定变量——其中 20 个)。如果你不想这样做,你可以改为按名称绑定(并提供参数字典)。
另一种可行的方法是对所有参数执行“查询”,如下所示:
merge into bi.merchant_info_test target
using select :1 as x, :2, as y, :3 as z, ... from dual source
on target.atrans_id = source.atrans_id
when matched then update set merchant_info = source.merchant_info ...
when not matched then insert (ADDRESS, ...) values (source.address, ...)
这样一来,您只有一个地方需要绑定变量,而不是两个地方(对于其中一些)。
几天前发布的新 Python 驱动程序 (python-oracledb) 在使用精简模式时针对此类事件提供了更好的错误消息(有关详细信息,请参阅 documentation ).可能值得用该驱动程序尝试您的示例以找出问题的根源。
附带说明一下,插入多行时最好使用 executemany(),而不是遍历列表并重复调用 execute()。性能差异可能非常显着,尤其是对于大量行!
最近几个小时我一直在苦思冥想,但找不到根本原因。浏览了多篇文章,但没有运气。
我正在尝试合并存储在 pandas 数据框中的值。 下面是我将数据框转换为列表的代码
merchantinfo_lst = appenddata.values.tolist()
通过下面的代码,我试图将数据合并到目标中 table。
sql ='merge into bi.merchant_info_test ';
sql+=' using dual';
sql+=' on ( ATRANS_ID = :2 )';
sql+=' when matched then update set MERCHANT_INFO = :15, MESSAGE_PARAM = :16, PUBLISH_DATE = :13' ;
sql+=' when not matched then insert( ADDRESS,ATRANS_ID,CITY_NAME,COUNTRY_CODE,LATITUDE,LONGITUDE,MERCHANT_CATEGORY_CODE,MERCHANT_DESCRIPTOR,MERCHANT_ID,';
sql+=' MERCHANT_NAME,PHONE_NUMBER,POSTAL_CODE,PUBLISH_DATE,STATE_PROVINCE_CODE,MERCHANT_INFO,MESSAGE_PARAM )';
sql+=' values( :1, :2, :3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16 )';
for i in range(len(merchantinfo_lst)):
cur.execute(sql,merchantinfo_lst[i])
我收到 cx_Oracle.DatabaseError: ORA-01008: 并非所有变量都已绑定,但所有值都存在于列表中并且所有列都存在于目标 table 中。 无论我尝试什么,我都无法解决问题。
Python版本:2.7.5 cx_Oracle版本:7.3.0 目标数据库:Oracle Database 19c 企业版 Release 19.0.0.0.0
Table结构
Name Null? Type
---------------------- -------- --------------
ATRANS_ID NOT NULL RAW(36 BYTE)
MERCHANT_ID VARCHAR2(20)
MERCHANT_DESCRIPTOR VARCHAR2(100)
MERCHANT_NAME VARCHAR2(100)
ADDRESS VARCHAR2(250)
CITY_NAME VARCHAR2(100)
STATE_PROVINCE_CODE VARCHAR2(4)
POSTAL_CODE VARCHAR2(10)
COUNTRY_CODE VARCHAR2(10)
LATITUDE VARCHAR2(20)
LONGITUDE VARCHAR2(20)
PHONE_NUMBER VARCHAR2(15)
MERCHANT_CATEGORY_CODE VARCHAR2(6)
MERCHANT_INFO VARCHAR2(250)
MESSAGE_PARAM VARCHAR2(2000)
PUBLISH_DATE DATE
Python代码
def table_merge(data_frame,uname,passwd,oracle_dsn):
merchantinfo = pd.DataFrame()
transidinfo = pd.DataFrame()
ora_con = oracle_conn(uname,passwd,oracle_dsn)
cur = ora_con.cursor()
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
appenddata['MERCHANT_INFO'] = appenddata['MERCHANT_NAME']+ ' ' +appenddata['CITY_NAME']+ ' '+appenddata['STATE_PROVINCE_CODE']+ ' ' +appenddata['COUNTRY_CODE']+ ' ' +appenddata['POSTAL_CODE']
appenddata['MESSAGE_PARAM'] = appenddata['MERCHANT_ID']+ '|' + appenddata['MERCHANT_INFO']
appenddata['PUBLISH_DATE'] = dt_string
merchantinfo_lst = appenddata.values.tolist()
print('printing list')
print(merchantinfo_lst)
sql ='merge into bi.merchant_info_test ';
sql+=' using dual';
sql+=' on ( ATRANS_ID = :2 )';
sql+=' when matched then update set MERCHANT_INFO = :15, MESSAGE_PARAM = :16, PUBLISH_DATE = :13' ;
sql+=' when not matched then insert( ADDRESS,ATRANS_ID,CITY_NAME,COUNTRY_CODE,LATITUDE,LONGITUDE,MERCHANT_CATEGORY_CODE,MERCHANT_DESCRIPTOR,MERCHANT_ID,';
sql+=' MERCHANT_NAME,PHONE_NUMBER,POSTAL_CODE,PUBLISH_DATE,STATE_PROVINCE_CODE,MERCHANT_INFO,MESSAGE_PARAM )';
sql+=' values( :1, :2, :3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16 )';
for i in range(len(merchantinfo_lst)):
cur.execute(sql,merchantinfo_lst[i])
cur.close()
ora_con.commit()
ora_con.close()
输出
/home/kkant/microservice-poc % python consumer.py
printing list
[[u'dummy_address', u'123456789', u'dummy_city', u'91', u'', u'', u'2345', u'dummy', u'123', u'dummy_merchant', u'1234567890', u'123456', '27/05/2022 11:32:22', u'', u'dummy_merchant dummy_city 91 123456', u'123|dummy_merchant dummy_city 91 123456'], [u'dummy_address', u'1234567455', u'dummy_city', u'91', u'', u'', u'2345', u'dummy', u'456', u'dummy_merchant', u'1234567890', u'123456', '27/05/2022 11:32:22', u'', u'dummy_merchant dummy_city 91 123456', u'456|dummy_merchant dummy_city 91 123456']]
Traceback (most recent call last):
File "consumer.py", line 102, in <module>
table_merge(appenddata)
File "consumer.py", line 71, in table_merge
cur.execute(sql,merchantinfo_lst[i])
cx_Oracle.DatabaseError: ORA-01008: not all variables bound
[enter image description here][1]
问题是您是按位置绑定的,而不是按名称绑定的。因此,您需要为每个绑定变量位置创建一个条目。 SQL 语句第一部分中的值 :2 需要一个值,SQL 语句最后一部分中的值 :2 也需要一个值! (依此类推 SQL 语句中提到的每个绑定变量——其中 20 个)。如果你不想这样做,你可以改为按名称绑定(并提供参数字典)。
另一种可行的方法是对所有参数执行“查询”,如下所示:
merge into bi.merchant_info_test target
using select :1 as x, :2, as y, :3 as z, ... from dual source
on target.atrans_id = source.atrans_id
when matched then update set merchant_info = source.merchant_info ...
when not matched then insert (ADDRESS, ...) values (source.address, ...)
这样一来,您只有一个地方需要绑定变量,而不是两个地方(对于其中一些)。
几天前发布的新 Python 驱动程序 (python-oracledb) 在使用精简模式时针对此类事件提供了更好的错误消息(有关详细信息,请参阅 documentation ).可能值得用该驱动程序尝试您的示例以找出问题的根源。
附带说明一下,插入多行时最好使用 executemany(),而不是遍历列表并重复调用 execute()。性能差异可能非常显着,尤其是对于大量行!