4

我在 Oracle 中有两个表,作业和参考。

我想在两个表中插入一条新记录,并使用从序列生成的键。就像是:

insert into (
select j.jobid, j.fileid, j.jobname, r.reffileid 
from job j
inner join reference r on j.jobid=r.jobid)
values (jobidsequence.nextval, 4660, 'name', 4391);

当然,这会导致:

ORA-01776: cannot modify more than one base table through a join view

有没有办法在不使用 PL/SQL 的情况下做到这一点?我非常喜欢只使用 SQL 来完成它。

4

4 回答 4

11

insert all您可以为此使用多表插入语法的副作用:

insert all
into job (jobid, fileid, jobname)
values (jobidsequence.nextval, fileid, jobname)
into reference (jobid, reffileid)
values (jobidsequence.nextval, reffileid)
select  4660 as fileid, 'name' as jobname, 4391 as reffileid
from dual;

2 rows inserted.

select * from job;

     JOBID     FILEID JOBNAME  
---------- ---------- ----------
        42       4660 name       

select * from reference;

     JOBID  REFFILEID
---------- ----------
        42       4391 

SQL 小提琴

从限制:

您不能在多表插入语句的任何部分指定序列。多表插入被视为单个 SQL 语句。因此,对 NEXTVAL 的第一次引用会生成下一个数字,并且语句中的所有后续引用都返回相同的数字。

显然我在values从句中使用了一个序列,所以第一句话似乎不太准确;但你不能在select零件中使用它。(我不是 100% 确定它是否可以values在所有版本中使用,但是文档无论如何都有点误导,并且自相矛盾)。

所以我利用了这样一个事实,因为它是一个语句,所以两个引用nextval得到相同的数字,正如第三句所说,所以两个表中使用了相同的序列值。

于 2013-06-12T07:36:00.520 回答
2

您可以使用jobidsequence.currval来获取序列的当前值(在一个会话事务中,即直到COMMITnextval之前调用,直到您nextval再次调用)。

请参阅:Oracle 管理员手册:管理序列

于 2013-06-12T07:36:29.243 回答
0

更简单的方法..

    begin
      insert into job (
        col1,
        ...
        coln)
      select
        col1,
        ....
        coln
      from
        tableA
    <condition>;

      insert into job2 (
        col1,
        ...
        coln)
      select
        col1,
        ....
        coln
      from
        tableB
    <condition>;

    End;
于 2013-06-12T07:38:59.630 回答
0

试试这样:

PROCEDURE ADD_CAMPAIGN (
                          configXML IN CLOB
                        ) IS 
        vn_CAMPAIGNID number;
BEGIN
   vn_CAMPAIGNID := CAMPAIGN_SEQUENCE.NEXTVAL;

  INSERT INTO CAMPAIGN_INFO (campaign_id,name,start_date,period,handset_statu,bscs_service_id)
  VALUES(vn_CAMPAIGNID ,
  XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/name/text()').getStringVal() ,
  TO_DATE(XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/startDate/text()').getStringVal()) ,
  XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/period/text()').getNumberVal() ,
  XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/handsetStatu/text()').getStringVal(),
  XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/bscsServiceID/text()').getNumberVal()

  );
  INSERT INTO PROMO_INFO(CAMPAIGN_ID,NAME) 
    VALUES(vn_CAMPAIGNID,
    XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/promoName/text()').getStringVal());

 INSERT INTO UTILITY_INFO(CAMPAIGN_ID,NAME)
     VALUES(vn_CAMPAIGNID,
     XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/utilityName/text()').getStringVal())  ;

 INSERT   INTO FREE_UNIT_INFO(CAMPAIGN_ID,NAME) 
     VALUES(vn_CAMPAIGNID,
     XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/packageName/text()').getStringVal()) ;

   INSERT INTO HANDSET_INFO(HANDSET_ID,NAME,CAMPAIGN_ID)
     VALUES(HANDSET_SEQUENCE.NEXTVAL,
     XMLTYPE(configXML).EXTRACT('/campaign/campaignInfo/handsetName/text()').getStringVal(),
     vn_CAMPAIGNID);



END ADD_CAMPAIGN;
于 2016-09-01T13:24:52.020 回答