我正在尝试改进将元素插入oracle数据库的批处理服务。目前,插入过程中出现性能问题。
现在我的插入字符串是这样的:
INSERT INTO MYTABLE (COL1, COL2, COL3) VALUES (:COL1, :COL2, :COL3);
而字符串的执行类似于:
with connection.cursor() as cursor:
cursor.executemany(sql, list)
直到这里才有异常之处吗?!
但是MYTABLE具有PK列,该列由插入执行时的触发器(从序列表中找出PK)填充。请注意,我将有几个并行进程执行相同的插入,每个进程都访问触发器,从而访问顺序表。
从最初的研究中,我发现可以删除触发器并直接在插入中访问序列表,这是我的问题,如何编写此插入字符串?
类似这样的东西不起作用:
INSERT INTO MYTABLE (ID, COL1, COL2, COL3) VALUES (MYTABLE_SQ.nextval, :COL1, :COL2, :COL3);
也没有(即使以正确的顺序设置了列):
INSERT INTO MYTABLE VALUES (MYTABLE_SQ.nextval, :COL1, :COL2, :COL3);
有什么想法吗?
直接访问序列表
首先,您需要创建SEQUENCE
对象以直接引用它以获得NEXTVAL
值。您不能像问题中提到的那样从序列表中获取它。您使用序列自动递增,而不是将其存储在表中并获取它。对于Pre 12c versions
,SEQUENCE +TRIGGER
是正确的方法。
我不确定您为什么决定首先放置触发器并尝试访问SQL中的序列。因为,您的方法在尝试执行此操作时引入了另一个问题:
INSERT INTO table(col1, col2, col2, col3)
VALUES (sequence_name.NEXTVAL, :2, :3, :4)
而不是:
INSERT INTO table(id, col1, col2, col3)
VALUES (:1, :2, :3, :4)
不同之处在于,您传递的是:name
,而不是绑定变量sequence_name.NEXTVAL
。为了避免这种情况,您可以按照以下方式进行操作:
cursor.execute("select sequence_name.NEXTVAL from dual")
seq_value, = cursor.fetchone() --> assign sequence value then pass as bind variable
INSERT INTO table(id, col2, col3, col4)
VALUES (:seq_value, :2, :3, :4)
为了避免所有这些与序列相关的维护,如果您使用的是Oracle 12c
,请使用IDENTITY COLUMN
。请参阅Identity columns的Oracle文档。
以下是技巧:
DECLARE
ID NUMBER := MYTABLE_SQ.nextval;
BEGIN
INSERT INTO MYTABLE (ID, COL1, COL2, COL3) VALUES (ID, COL1, COL2, COL3);
END;