SQL Oracle,无序列地插入表中

时间:2012-08-07 20:09:29

标签: sql

我正在使用Oracle 11.2g实例。 我想通过自己生成主键值将行插入表中来了解我所暴露的内容。 我会从某些表中选择SELECT max(pk); 然后使用接下来的100个值作为接下来的100个插入。 是在玩火吗?

上下文是:我有大量的插件要做,它们被分割在由外键链接的几个表上。我试图获得良好的性能,而不是使用PL / SQL。

[编辑]这里有一个看起来像我正在处理的代码示例:

QString query1 = "INSERT INTO table 1 (pk1_id, val) VALUES (pk1_seq.nextval, ?)"
sqlQuery->prepare(query);
sqlQuery->addBindValue(vec_of_values);
sqlQuery->execBatch();

QString query2 = "INSERT INTO table 2 (pk2_id, another_val, pk1_pk1_id) VALUES    (pk2_seq.nextval, ?, ?)"
sqlQuery->prepare(query);
sqlQuery->addBindValue(vec_of_values);

// How do I get the primary keys (hundreds of them)
// from the first insert??
sqlQuery->addBindValue(vec_of_pk1);
sqlQuery->execBatch();

2 个答案:

答案 0 :(得分:0)

您正在暴露自己的性能降低,逻辑错误以及需要维护的额外代码。 Oracle序列针对您的特定目的进行了优化。对于高DML操作,您还可以缓存序列:

ALTER SEQUENCE customers_seq CACHE 100;

答案 1 :(得分:0)

为主表创建序列
使用your_sequence.nextval
插入主表 使用your_sequence.currval

完成对子(依赖)表的插入
create table parent (id integer primary key not null);
create table child (id integer primary key not null, pid integer not null references parent(id));
create sequence parent_seq;
create sequence child_seq;

insert into parent (id) values (parent_seq.nextval);
insert into child (id, pid) values (child_seq.nextval, parent_seq.currval);
commit;

要解释为什么max(id)无法可靠地工作,请考虑以下情形:

  1. 事务1检索max(id)+ 1(产量,比如42)
  2. 事务1插入id = 42
  3. 的新行
  4. 事务2检索max(id)+ 1(也产生42,因为事务1尚未提交)
  5. 交易1提交
  6. Transcation 2插入id = 42
  7. 的新行
  8. 事务2尝试提交并获取唯一的密钥违规
  9. 现在想想当你有很多的交易时会发生什么。你会得到很多的错误。此外,您的插入将变得越来越慢,因为计算max(id)的成本将随着表的大小而增加。

    序列 是解决此问题的唯一理智(即正确,快速和可扩展)方式。

    修改

    如果您对另一个无法应对这种策略的ORM感到震惊(现在几乎所有DBMS都支持它 - 甚至SQL Server现在都有序列),那么您应该可以在客户代码:

    使用select parent_seq.nextval from dual将下一个PK值检索到编程语言中的变量中(这是一种快速,可扩展且正确的检索PK值的方法)。

    如果您可以运行select max(id),还可以运行select parent_seq.nextval from dual。在这两种情况下,只需使用从该select语句中获得的值。