You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Python中使用executemany执行Oracle带返回值的INSERT语句遇阻求助

问题描述

早上好,我正尝试在Python中执行带返回值的INSERT INTO ... RETURNING SQL语句,希望使用executemany方法,但目前我的代码无法运行,恳请各位提供帮助,谢谢。

建表SQL

CREATE TABLE TABLE1
(    
    F1 NUMBER(*,0) GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1, 
    F2 NUMBER(*,0) NOT NULL ENABLE, 
    CONSTRAINT "TABLE1_PK" PRIMARY KEY ("F1")
)

我的Python代码

import cx_Oracle

def makeCxDSNLessConnection(src):
    return cx_Oracle.connect(user=sUser, password=sPass ,dsn=src)
def tempDoit():
    oraCon = makeCxDSNLessConnection('EPAT')
    cur = oraCon.cursor()
    thislist=list()
    thisOut = cur.var(int)
    cur.execute("TRUNCATE TABLE TABLE1")
    for i in range(1000000):
        thislist.append((i,))
    cur.executemany("INSERT INTO TABLE1(F2) VALUES(:1) RETURNING F1 INTO :2", thislist, thisOut )
    oraCon.commit()
    while True:
        rows = cur.fetchmany(100)
        if not rows:
            break
        for row in rows:
            print(row)  

解决方案

你的代码存在两个核心问题:

  • executemany绑定输出变量的方式错误:使用RETURNING子句配合executemany时,输出变量需要作为每个插入参数组的一部分传入,而非单独作为第三个参数。
  • 错误使用fetchmany获取返回值:executemany执行带RETURNING的语句后,自增ID会直接存储在输出变量中,无需通过游标fetch方法获取。

修正后的完整代码

import cx_Oracle

# 请替换为实际的数据库账号密码
sUser = "your_username"
sPass = "your_password"

def makeCxDSNLessConnection(src):
    return cx_Oracle.connect(user=sUser, password=sPass, dsn=src)

def tempDoit():
    oraCon = makeCxDSNLessConnection('EPAT')
    cur = oraCon.cursor()
    
    cur.execute("TRUNCATE TABLE TABLE1")
    
    total_records = 1000000
    # 创建输出变量,指定数组大小匹配插入记录数
    thisOut = cur.var(int, arraysize=total_records)
    
    # 构造包含输入参数和输出变量的参数列表
    thislist = [(i, thisOut) for i in range(total_records)]
    
    # 执行批量插入
    cur.executemany("INSERT INTO TABLE1(F2) VALUES(:1) RETURNING F1 INTO :2", thislist)
    
    oraCon.commit()
    
    # 从输出变量中提取所有返回的F1值
    returned_ids = thisOut.getvalue()
    for f1_val in returned_ids:
        print(f1_val)
    
    cur.close()
    oraCon.close()

tempDoit()

关键优化说明

  • 输出变量数组大小:必须设置arraysize为批量插入的记录数,确保能容纳所有返回的自增ID。
  • 内存优化:如果插入百万级数据,直接构造超大列表会占用大量内存,建议分批次插入(比如每1万条一批),示例如下:
def tempDoit():
    oraCon = makeCxDSNLessConnection('EPAT')
    cur = oraCon.cursor()
    
    cur.execute("TRUNCATE TABLE TABLE1")
    
    total_records = 1000000
    batch_size = 10000  # 每次插入1万条,降低内存占用
    
    for start in range(0, total_records, batch_size):
        end = min(start + batch_size, total_records)
        thisOut = cur.var(int, arraysize=batch_size)
        # 构造当前批次的参数列表
        thislist = [(i, thisOut) for i in range(start, end)]
        
        cur.executemany("INSERT INTO TABLE1(F2) VALUES(:1) RETURNING F1 INTO :2", thislist)
        
        # 获取当前批次的返回ID
        returned_ids = thisOut.getvalue()
        for f1_val in returned_ids:
            if f1_val is not None:
                print(f1_val)
    
    oraCon.commit()
    cur.close()
    oraCon.close()

内容的提问来源于stack exchange,提问作者Z T Minhas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:53:01