The main purpose of the RETURNING clause is to obtain the value of a derived column, a value which is generated during the insert process. Usually this is a technical primary key derived from a sequence, or since 12c an IDENTITY column.
So for instance:
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;
/
This is why the examples you found specify columns in the INSERT projection: the value of the primary key is generated automatically, so there's no point in us assigning it a value in our code.
Now your function uses a record type in its insert statement. We can't do that with IDENTITY columns. This variant ...
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;
/
... will hurl
ORA-32795: cannot insert into a generated always identity column
But we can use a %rowtype
with the old-fashioned sequence and trigger combo:
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;
/
Here is a LiveSQL demo (free Oracle OTN account required, alas). If you run it you will see that the trigger overrides the assigned value and the val1
column has the value from the sequence.