我遇到了一些看起来像这样的代码。我知道它将返回自动生成的id,但我不明白的是当我调用此函数时传递游标数据时,如何在列顺序不是时确定要在哪些列中插入哪些值定义
FUNCTION INSERT_ROW(DATA IN OWNER.TABLE%ROWTYPE)
RETURN OWNER.TABLE.ID%TYPE
IS
l_ID OWNER.MY_TABLE.ID%TYPE;
l_Data OWNER.MY_TABLE%ROWTYPE := DATA;
BEGIN
INSERT INTO OWNER.MY_TABLE
VALUES l_Data
RETURNING ID INTO l_ID;
我试图查找很多示例,我只是遇到了像这样定义值的那些示例 INSERT INTO my_table(val2,val3,val4)VALUES(2,3,4)返回val1 INTO val1;
答案 0 :(得分:2)
代码中的insert values语句是带有括号的标准插入值子句的PL / SQL扩展。这是关于此主题的12.2手册中的页面:
OWNER.TABLE%ROWTYPE数据类型定义的记录具有与表相同的列并且顺序相同。您只是将数据以该格式传递给函数,并将其传递给变量,然后传递给insert语句。
答案 1 :(得分:2)
Oracle IS中表的列顺序已定义。查看ALL_TAB_COLUMNS视图 - 有一个COLUMN_ID列,用于定义表中列的顺序。如果SELECT中没有给出字段列表(即SELECT * FROM MY_TABLE),则MY_TABLE中的列将以ALL_TAB_COLUMNS.COLUMN_ID顺序返回。这与在%ROWTYPE变量中排序列的方式相同,而且没有指定字段列表的INSERT需要对字段进行排序。
答案 2 :(得分:0)
RETURNING子句的主要目的是获取派生列的值,该值是在插入过程中生成的值。通常这是从序列派生的技术主键,或者从12c开始是IDENTITY列。
例如:
create table my_table (
val1 number generated as identity primary key
, val2 varchar2(16)
, val3 varchar2(16)
, val4 date)
/
declare
id number;
begin
INSERT INTO my_table (val2, val3, val4)
VALUES ('one', 'test', sysdate)
RETURNING val1 INTO id;
dbms_output.put_line('new id = ' || id);
end;
/
这就是你找到的例子在INSERT投影中指定列的原因:主键的值是自动生成的,所以我们没有必要在代码中为它赋值。
现在,您的函数在其insert语句中使用记录类型。我们不能用IDENTITY列做到这一点。这个变种......
declare
lrec my_table%rowtype;
id number;
begin
lrec.val2 := 'two';
lrec.val3 := 'test again';
lrec.val4 := sysdate;
INSERT INTO my_table
VALUES lrec
RETURNING val1 INTO id;
dbms_output.put_line('new id = ' || id);
end;
/
...将投掷
ORA-32795:无法插入生成的始终标识列
但我们可以使用带有旧式序列的%rowtype
并触发组合:
create table my_table (
val1 number primary key
, val2 varchar2(16)
, val3 varchar2(16)
, val4 date)
/
create sequence my_seq start with 42;
create or replace trigger my_trg
before insert on my_table for each row
begin
:new.val1 := my_seq.nextval;
end;
/
declare
lrec my_table%rowtype;
id number;
begin
lrec.val1 := 1;
lrec.val2 := 'three';
lrec.val3 := 'test again';
lrec.val4 := sysdate;
INSERT INTO my_table
VALUES lrec
RETURNING val1 INTO id;
dbms_output.put_line('new id = ' || id);
end;
/
这是a LiveSQL demo (free Oracle OTN account required, alas)。如果运行它,您将看到触发器覆盖指定的值,val1
列具有序列中的值。