使用select将多行插入表中但是表在Oracle SQL中具有主键

时间:2014-10-30 12:52:51

标签: oracle

我在插入多行时遇到问题,因为列id有主键,而且它是根据序列创建的。

代表:

create table test (
  iD number primary key,
  name varchar2(10)
);


insert into test values (123, 'xxx');
insert into test values (124, 'yyy');
insert into test values (125, 'xxx');
insert into test values (126, 'xxx');

以下语句创建约束violoation错误:

insert into test
(
   select (SELECT MAX (id) + 1 FROM  test) as id,
   name from test
  where name='xxx'
 );

此查询应在表test中插入3行(名称= xxx)。

3 个答案:

答案 0 :(得分:2)

您说您的查询根据序列插入具有主键ID的行。然而,在您的插入/选择中,有select (SELECT MAX (id) + 1 FROM test) as id,显然 基于序列。可能是您没有使用术语"序列"以通常的Oracle方式。

无论如何,你有两种选择......

  1. Create a sequence,例如seq_test_id的起始值为select max(id) from test,并在您的查询中使用它(即seq_test_id.nextval),而不是select max(id)+1 from test
  2. 将实际的子选择修复为nvl((select max(id) from test),0)+rownum而不是(select max(id)+1 from test)
  3. 请注意,但是,当您的代码在多个并发数据库会话中运行时,选项2(以及您的原始解决方案)会给您带来巨大麻烦。因此,强烈建议使用选项1.

答案 1 :(得分:1)

使用

insert into test (
   select (SELECT MAX (id) FROM  test) + rownum as id,
   name from test
  where name='xxx'
 );

作为解决方法。

当然,您应该使用sequences来表示整数主键。

答案 2 :(得分:0)

如果要插入序列生成的ID /主键值,则应使用序列而不是选择最大(ID)+1。

通常这是通过在每个行执行的表上使用触发器来完成的。见下面的示例:

CREATE TABLE "MY_TABLE" 
(   
  "MY_ID" NUMBER(10,0) CONSTRAINT PK_MY_TABLE PRIMARY KEY , 
  "MY_COLUMN" VARCHAR2(100)
);
/ 
CREATE SEQUENCE  "S_MY_TABLE" 
MINVALUE 1 MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 10 NOCACHE  ORDER  NOCYCLE  NOPARTITION ;
/
 CREATE OR REPLACE TRIGGER "T_MY_TABLE" 
  BEFORE INSERT
  ON
  MY_TABLE
  REFERENCING OLD AS OLDEST NEW AS NEWEST
  FOR EACH ROW
    WHEN (NEWEST.MY_ID IS NULL)
DECLARE
   IDNOW NUMBER;
  BEGIN
    SELECT  S_MY_TABLE.NEXTVAL INTO IDNOW FROM DUAL;
    :NEWEST.MY_ID := IDNOW;
  END;

/
ALTER TRIGGER "T_MY_TABLE" ENABLE;
/
insert into MY_TABLE (MY_COLUMN) values ('DATA1');
insert into MY_TABLE (MY_COLUMN) values ('DATA2');
insert into MY_TABLE (MY_ID, MY_COLUMN) values (S_MY_TABLE.NEXTVAL, 'DATA3');
insert into MY_TABLE (MY_ID, MY_COLUMN) values (S_MY_TABLE.NEXTVAL, 'DATA4');
insert into MY_TABLE (MY_COLUMN) values ('DATA5');
/
select * from MY_TABLE;