使用 cx_Oracle Cursor.executemany() 插入序列的下一个值
Insert next value of sequence using cx_Oracle Cursor.executemany()
我正在尝试使用 python 中的 cx_oracle 库插入行,其中一个列值是名为 an_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: 无效数字
我确定问题出在序列上,因为如果我用数字替换序列,插入就会成功。谁能告诉我在 table?
中插入行时如何调用序列
我曾尝试使用 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()
在您的 SQL 语句中,您将所有值作为绑定变量传递。这通常很棒!但是 SQL 引擎不会 解释 绑定变量。因此,对于 AJ_ID
列,您并没有像您希望的那样调用序列伪列 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 )
我正在尝试使用 python 中的 cx_oracle 库插入行,其中一个列值是名为 an_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: 无效数字
我确定问题出在序列上,因为如果我用数字替换序列,插入就会成功。谁能告诉我在 table?
中插入行时如何调用序列我曾尝试使用 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()
在您的 SQL 语句中,您将所有值作为绑定变量传递。这通常很棒!但是 SQL 引擎不会 解释 绑定变量。因此,对于 AJ_ID
列,您并没有像您希望的那样调用序列伪列 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 )