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

And*_*ers 6 oracle plsql identity-column rowtype oracle12c

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

CREATE TABLE foo (
  id   NUMBER  GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  bar  NUMBER
)
Run Code Online (Sandbox Code Playgroud)

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

DECLARE
  x foo%ROWTYPE;
BEGIN
  x.bar := 3;
  INSERT INTO foo VALUES x;
END;
Run Code Online (Sandbox Code Playgroud)

但是,它给了我这个错误:

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

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

文章建议,只有这样才能够使用%ROWTYPE是切换到GENERATED BY DEFAULT ON NULL.有没有其他方法可以解决这个问题?

Mat*_*eak 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;    
Run Code Online (Sandbox Code Playgroud)


Wer*_*eit 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;
Run Code Online (Sandbox Code Playgroud)