Python oracledb调用Oracle存储过程无更新效果问题求助
问题排查与解决思路
1. 事务未提交(最可能的核心原因)
oracledb默认不会自动提交事务,即便存储过程执行成功,数据修改仅存在于当前会话的事务中,并未持久化到数据库。而SQL Developer通常会自动提交执行的语句,所以你复制生成的SQL到工具中能生效。
解决方法:
在调用存储过程的代码后添加事务提交操作:
# 调用存储过程后执行提交 connection.commit()
无论debug模式是否开启,都需要执行这一步。
2. 参数传递的隐形风险(推荐优化方向)
虽然你看到生成的SQL和SQL Developer一致,但手动拼接带引号的参数容易引发隐藏问题,同时存在SQL注入风险。建议重构存储过程使用绑定变量:
create or replace procedure update_reported_delta( update_tbl_name in varchar2, update_key_col in varchar2, update_key_vals in varchar2 ) AUTHID CURRENT_USER AS sql_cmd varchar(32767); BEGIN sql_cmd:= 'UPDATE ' || update_tbl_name || ' SET DELTA_REPORTED = ''Y'' WHERE '|| update_key_col ||' in (:key_vals) AND DELTA_REPORTED IS NULL'; execute immediate sql_cmd using update_key_vals; END;
Python调用时,参数直接传原值(无需额外加单引号):
params_list = ['my_tbl', 'my_id_col', 'MY_ID_VAL']
3. 会话权限与上下文验证
确认Python连接数据库的用户和SQL Developer使用的用户权限完全一致,包括是否激活了相同角色、是否存在行级安全策略(RLS)限制Python会话的更新操作。
可在Python中执行以下语句验证:
cursor.execute("SELECT USER FROM DUAL") print(f"Current user: {cursor.fetchone()[0]}") cursor.execute("SELECT PRIVILEGE FROM USER_SYS_PRIVS WHERE PRIVILEGE = 'UPDATE ANY TABLE'") print(f"Update privilege: {cursor.fetchall()}")
4. 直接验证受影响行数
修改存储过程添加输出参数,查看实际更新的行数,排除数据本身不匹配的情况:
create or replace procedure update_reported_delta( update_tbl_name in varchar2, update_key_col in varchar2, update_key_vals in varchar2, out_affected_rows out number ) AUTHID CURRENT_USER AS sql_cmd varchar(32767); BEGIN sql_cmd:= 'UPDATE ' || update_tbl_name || ' SET DELTA_REPORTED = ''Y'' WHERE '|| update_key_col ||' in ('||update_key_vals||') AND DELTA_REPORTED IS NULL'; execute immediate sql_cmd; out_affected_rows := SQL%ROWCOUNT; dbms_output.put_line('Affected rows: ' || out_affected_rows); END;
Python调用时捕获输出参数:
params_list = ['my_tbl', 'my_id_col', "'MY_ID_VAL'", 0] cursor.callproc(procedure_name, params_list) print(f"Stored procedure affected rows: {params_list[3]}")
内容的提问来源于stack exchange,提问作者Maeaex1
相关产品推荐
相关产品推荐

