得到错误cx_Oracle.数据库错误:ORA-01008:不是所有的变量绑定时,试图绑定一个列表的值在合并语句.<



过去几个小时我一直在敲我的头,但找不到根本原因。我看了很多篇文章,但是没有运气。

我正在尝试合并存储在pandas数据框中的值。下面是我将数据帧转换为list

的代码
merchantinfo_lst = appenddata.values.tolist()

通过下面的代码,我试图合并数据到目标表。

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:不是所有的变量绑定,但所有的值都存在于列表中,所有的列都存在于目标表中。不管我怎么努力,我都解决不了这个问题。

Python版本:2.7.5cx_Oracle版本:7.3.0目标数据库:Oracle database 19c Enterprise Edition Release 19.0.0.0.0

表结构
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)在使用瘦模式时对这类事情有更好的错误消息(请参阅文档了解更多详细信息)。也许值得尝试使用该驱动程序的示例来找出问题的根源。

顺便说一句,在插入多行时最好使用executemany(),而不是遍历列表并反复调用execute()。性能上的差异可能是惊人的,特别是对于大量的行!

最新更新