如何在使用标识列插入Oracle表时使用%ROWTYPE?

时间:2015-11-12 15:37:38

标签: oracle plsql oracle12c identity-column rowtype

我有一个Oracle 12c数据库,其中包含一个包含标识列的表:

CREATE TABLE foo (
  id   NUMBER  GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  bar  NUMBER
)

现在我想使用PL / SQL插入表中。由于实际上表格有很多列,我使用%ROWTYPE

DECLARE
  x foo%ROWTYPE;
BEGIN
  x.bar := 3;
  INSERT INTO foo VALUES x;
END;

然而,它给了我这个错误:

  

ORA-32795:无法插入生成的始终标识列
  ORA-06512:第5行

由于代码可读性和可维护性非常好,我不想停止使用%ROWTYPE。由于我在任何情况下都不想允许除自动生成的ID以外的任何内容,因此我不想解除GENERATED ALWAYS限制。

This文章表明,能够使用%ROWTYPE的唯一方法是切换到GENERATED BY DEFAULT ON NULL。没有其他方法可以解决这个问题吗?

3 个答案:

答案 0 :(得分:6)

我唯一可以想到的是,因为您在12c上创建了标识列INVISIBLE,就像下面的代码一样。

问题在于它使%ROWTYPE 使用 id变得更加困难,但它是可行的。

当然,它也可能会混淆使用你桌子的其他人看不到主键!

我不认为我会这样做,但它 是你问题的答案,因为这是值得的。

DROP TABLE t;

CREATE TABLE t ( id number invisible generated always as identity, 
                 val varchar2(30));

insert into t (val) values ('A');                 

DECLARE

  record_without_id t%rowtype;
  CURSOR c_with_id IS SELECT t.id, t.* FROM t;
  record_with_id c_with_id%rowtype;

BEGIN
  record_without_id.val := 'C';
  INSERT INTO t VALUES record_without_id;

  -- If you want ID, you must select it explicitly
  SELECT id, t.* INTO record_with_id FROM t WHERE rownum = 1;

  DBMS_OUTPUT.PUT_LINE(record_with_id.id || ', ' || record_with_id.val);
END;
/

SELECT id, val FROM t;    

答案 1 :(得分:5)

您可以创建视图并插入其中:

CREATE OR REPLACE VIEW V_FOO AS
SELECT BAR -- all columns apart from virtual columns
FROM foo;

DECLARE
   x V_FOO%ROWTYPE;
BEGIN
   x.bar := 3;
   INSERT INTO V_FOO VALUES x;
END;

答案 2 :(得分:3)

我认为混合使用以前的答案-使用带有不可见标识列的视图-是完成此任务的最佳方法:

create table foo (id number generated always as identity primary key, memo varchar2 (32))
;
create or replace view fooview (id invisible, memo) as select * from foo
; 
<<my>> declare 
    r fooview%rowtype;   
    id number;
begin
    r.memo := 'first row';
    insert into fooview values r
    returning id into my.id
    ;
    dbms_output.put_line ('inserted '||sql%rowcount||' row(s) id='||id);  
end;
/
  

插入1行id = 1