获取错误cx_oracle.databaseerror:ora-01008:在合并语句中尝试绑定列表的值时,并非所有变量绑定

发布于 2025-02-02 04:48:49 字数 4298 浏览 1 评论 0原文

我从最近几个小时开始敲打头,但找不到根本原因。经历了多篇文章,但没有运气。

我正在尝试合并熊猫数据框架中存储的值。 以下是我通过下面代码将数据范围转换为列表的代码,

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.5 cx_oracle版本:7.3.0 目标数据库:Oracle数据库19C Enterprise Edition版本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]

I am banging my head from last few hours but unable to find the root cause. went through multiple articles but no luck.

I am trying to merge the values which are stored inside a pandas dataframe.
Below is the code where I am converting the dataframe into list

merchantinfo_lst = appenddata.values.tolist()

Through below code I am trying to merge data into the target 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])

I am getting cx_Oracle.DatabaseError: ORA-01008: not all variables bound but all the value are present in the list and all the column are present in the target table.
No matter what I try, I am not able to resolve the issue.

Python version: 2.7.5
cx_Oracle version: 7.3.0
Target database : Oracle Database 19c Enterprise Edition Release 19.0.0.0.0

Table structure

    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 code

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()

Output

    /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]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

辞取 2025-02-09 04:48:49

问题在于您是按位置绑定的,而不是按名称绑定。因此,您需要每个绑定变量位置的条目。值:2在您的SQL语句的第一部分中需要一个值和值:2在您的SQL语句的最后一部分中也需要一个值! (有关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)在使用薄模式时会对这种事情有更好的错误消息(请参阅文档有关更多详细信息)。可能值得尝试与该驱动程序的示例来找出问题的根源。

附带说明,最好在插入多行时使用opecutemany(),而不是在列表中迭代并重复调用execute()。性能的差异可能会引人注目,尤其是对于大量行!

The problem is that you are binding by position, not by name. So you need an entry for every bind variable position. The value :2 in the first part of your SQL statement needs a value and the value :2 in the last part of your SQL statement also needs a value! (And so on for every bind variable mentioned in your SQL statement -- 20 of them). If you don't want to do that you can bind by name instead (and supply a dictionary of parameters).

One other possibility that may work is to perform a "query" of all of the parameters, as in this:

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, ...)

That way you only have one place where the bind variables are required instead of two (for some of them).

The new Python driver released a couple of days ago (python-oracledb) has better error messages for this sort of thing when using thin mode (see the documentation for more details). It may be worth trying your example with that driver to find out the source of the issue.

On a side note, it is better to use executemany() when inserting multiple rows instead of iterating through the list and calling execute() repeatedly. The difference in performance can be striking, especially for large numbers of rows!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文