【问题标题】:Inserts with executemany and partialy parametrized lists带有 executemany 和部分参数化列表的插入
【发布时间】:2020-09-06 21:41:05
【问题描述】:

我正在尝试改进将元素插入 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);

有什么想法吗?

【问题讨论】:

  • 您收到的完整错误信息是什么? Oracle SQL 允许像在 INSERT 语句中那样引用序列。

标签: python sql oracle sequence cx-oracle


【解决方案1】:

直接访问序列表

首先,您需要创建SEQUENCE 对象以直接引用它以获取NEXTVAL 值。正如您在问题中提到的,您无法从序列表中获取它。您使用序列自动递增,而不是将其存储在表中并获取它。对于Pre 12c versionsSEQUENCE +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)

不同之处在于,您传递的是sequence_name.NEXTVAL,而不是绑定变量:name。为避免这种情况,您可以这样做:

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。请参阅 Oracle 文档以获取 Identity columns

【讨论】:

  • “直接访问序列表”的意思是我想避免触发,仅此而已。
  • 那么正如我所建议的,您需要绑定它或事先获取它并作为绑定变量传递,如答案所示。您的 Oracle 版本是多少?
【解决方案2】:

以下方法可以解决问题:

DECLARE
    ID NUMBER := MYTABLE_SQ.nextval;
BEGIN
    INSERT INTO MYTABLE (ID, COL1, COL2, COL3) VALUES (ID, COL1, COL2, COL3);
END;

【讨论】:

    猜你喜欢
    • 2013-10-09
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    相关资源
    最近更新 更多