使用cx\U Oracle游标插入序列的下一个值

2024-04-18 12:01:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用python中的cx_oracle库插入行,其中一个列值是名为a_aj_s的序列中的下一个值

我创建了一个函数来执行此操作,名为insert_into_columns,对此函数的调用如下所示:

self.insert_into_columns('AN_JOB',
                         ('AJ_ID','AJ_JOBNAME', 'AJ_DESCRIPTION', 'AJ_CD_JOB_TYPE', 'AJ_CD_DATABASE','AJ_CD_JOB_STATUS', 'AJ_USR_ID', 'AJ_CREATE_DATE', 'AJ_EQUIP_COMPS_FLAG'),
                         [ ('an_aj_s.nextval', 'QlikManual_3', 'First Manually entered Test Job', 2, 0, 1  ,6 , dt.today().date(),  1)])

其中参数为: insert_into_columns({Table Name}, {Columns to insert}, {row of values to insert}

调用函数时,我得到一个错误无效号码: cx_Oracle.DatabaseError:ORA-01722:无效数字

我确信问题在于序列,因为如果我用一个数字替换序列,插入就成功了。有人能告诉我在表中插入行时如何调用序列吗

我曾尝试使用cur.setinputsizes()设置输入大小,但似乎不起作用

其他信息:

我的函数生成的SQL语句如下所示:

INSERT INTO AN_JOB (AJ_ID,AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) VALUES ( :1, :2, :3, :4, :5, :6, :7, :8, :9 )

生成语句的实际python函数如下所示:

 def insert_into_columns(self, table_name, columns, rows):
    sql = "INSERT INTO {table_name} ({column_names}) VALUES ({column_args} )"
    args_str = ''
    col_str  = ''
    for col_id in range(1, len(columns) + 1):
        args_str += ' :' + str(col_id)
        col_str += columns[col_id - 1]
        if col_id < len(columns):
            args_str += ','
            col_str += ','

    sql = sql.format(table_name=table_name, column_names =col_str,  column_args=args_str)
    print('Inserting rows into specified columns...')
    print(sql)

    with self.conn.cursor() as cur:
        cur.executemany(sql, rows)
        self.conn.commit()

Tags: columns函数selfidsqltableargscd
1条回答
网友
1楼 · 发布于 2024-04-18 12:01:28

在SQL语句中,将所有值作为绑定变量传递。这通常是伟大的!但是绑定变量不是由SQL引擎解释的。因此,对于AJ_ID列,您并没有像希望的那样调用sequence pseudocolumn an_aj_s.nextval,而是传递一个varchar2字符串'an_aj_s.nextval'。Oracle需要的是一个数字,而不是字符串,因此会出现ORA-01722错误

您需要修改函数,以便:

INSERT INTO AN_JOB (AJ_ID,AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) 
VALUES ( :1, :2, :3, :4, :5, :6, :7, :8, :9 )

您正在生成以下内容:

INSERT INTO AN_JOB (AJ_ID,AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) 
VALUES ( an_aj_s.nextval, :2, :3, :4, :5, :6, :7, :8, :9 )

这有意义吗?有很多方法可以改变你的函数来做到这一点,但是你还没有解释你的其他用例,所以我不想建议任何一种

或者,您可能会发现在Oracle端创建一个序列触发器更容易做到这一点。关于SO(like this)有很多例子

CREATE OR REPLACE TRIGGER an_job_id_trigger
BEFORE INSERT ON an_job
FOR EACH ROW
  WHEN (new.ID IS NULL)
BEGIN
  :new.ID := an_aj_s.nextval;
END;
/

这样,您就可以完全从插入中省去ID列,触发器将处理它:

INSERT INTO AN_JOB (AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) 
VALUES (:1, :2, :3, :4, :5, :6, :7, :8 )

相关问题 更多 >