使用cx_Oracle executemany执行删除时,如何在无匹配记录时报错?
解决方案
方法1:检查总删除行数
通过对比批量删除的总行数和待删除记录数,判断是否存在缺失的记录:
STNSchemaConnection = cx_oracle.connect(self._oracleUserNameSTN, self._oraclePasswordSTN, cx_oracle.makedsn(self._oracleServer, self._oraclePort, self._oracleSID)) STNSchemaCursor = STNSchemaConnection.cursor() STNSchemaCursor.prepare(deleteSqlString) STNSchemaCursor.executemany(None, dataToDump) # 验证删除行数是否匹配 if STNSchemaCursor.rowcount != len(dataToDump): STNSchemaConnection.rollback() raise ValueError(f"存在不存在的记录:实际删除 {STNSchemaCursor.rowcount} 条,预期删除 {len(dataToDump)} 条") STNSchemaConnection.commit()
cursor.rowcount会返回批量操作中总共删除的行数。如果这个数值小于dataToDump的长度,说明至少有一条记录不存在,此时回滚事务并抛出错误。
方法2:用PL/SQL块逐行验证
如果需要精准定位缺失的记录,可以将删除语句改为PL/SQL块,在每次删除后检查是否成功:
修改deleteSqlString为:
BEGIN DELETE FROM SCHEMA.TABLE_NAME WHERE SOURCE_SYS = :array_val_1 AND CONTRACT_NUM = :array_val_2; IF SQL%ROWCOUNT = 0 THEN RAISE_APPLICATION_ERROR(-20001, '记录不存在:SOURCE_SYS=' || :array_val_1 || ', CONTRACT_NUM=' || :array_val_2); END IF; END;
然后在Python中捕获异常并回滚:
STNSchemaConnection = cx_oracle.connect(self._oracleUserNameSTN, self._oraclePasswordSTN, cx_oracle.makedsn(self._oracleServer, self._oraclePort, self._oracleSID)) STNSchemaCursor = STNSchemaConnection.cursor() deleteSqlString = """ BEGIN DELETE FROM SCHEMA.TABLE_NAME WHERE SOURCE_SYS = :array_val_1 AND CONTRACT_NUM = :array_val_2; IF SQL%ROWCOUNT = 0 THEN RAISE_APPLICATION_ERROR(-20001, '记录不存在:SOURCE_SYS=' || :array_val_1 || ', CONTRACT_NUM=' || :array_val_2); END IF; END; """ try: STNSchemaCursor.prepare(deleteSqlString) STNSchemaCursor.executemany(None, dataToDump) STNSchemaConnection.commit() except cx_oracle.DatabaseError as e: STNSchemaConnection.rollback() raise
当某条记录不存在时,PL/SQL块会抛出自定义错误,包含缺失记录的主键信息,此时Python捕获异常并回滚整个事务。
方法对比
- 方法1:性能更优,仅需一次批量操作后做一次校验,但无法知道具体哪条记录缺失。
- 方法2:能明确指出缺失的记录,但每条记录都要执行PL/SQL逻辑,性能略低,适合需要精准错误信息的场景。
内容的提问来源于stack exchange,提问作者Karthik
相关产品推荐
相关产品推荐

