Question

I have the following table, two types based on it, and a function that reads from this table:

CREATE TABLE myTable (
    ID RAW(16) NULL,
    NAME NVARCHAR2(200) NULL,
    ENTITYID RAW(16) NOT NULL
);

CREATE TYPE myRowType AS OBJECT (
    NAME NVARCHAR2(200),
    ENTITYID RAW(16)
);
CREATE TYPE myTableType IS TABLE OF myRowType;

CREATE FUNCTION myFunction(...) RETURN myTableType ...

As you can see, the type myRowType is similar to myTable, but not exactly.

My goal is to insert rows into myTable based on the results of myFunction.

The naive approach would be to just write:

INSERT INTO myTable(ID, NAME, ENTITYID)
    SELECT sys_guid(), NAME, ENTITYID
    FROM TABLE(myFunction(...));

But since myFunction reads from myTable, this leads to the following error:

ORA-04091: table myTable is mutating, trigger/function may not see it

So I have to split the myFunction call from the insert statement. I tried it like this:

DECLARE
    tbl myTableType;
BEGIN
    SELECT myRowType(x.NAME, x.ENTITYID)
        BULK COLLECT INTO tbl
        FROM TABLE(myFunction(...)) x;

    INSERT INTO myTable
        (ID, NAME, ENTITYID)
        SELECT sys_guid(), x.NAME, x.ENTITYID
        FROM tbl x;
END;

But here, Oracle doesn't seem to understand the FROM tbl clause. It shows the error

ORA-00942: table or view does not exist

How can I insert the rows in tbl into myTable?

Was it helpful?

Solution

Since you can't use a locally defined nested table as an argument for TABLE function, maybe you would consider using the FORALL bulk insert? I see you are using Oracle 11g, so you will be able to access fields of myRowType. You would then replace your INSERT from your PL/SQL block with this:

FORALL v_i IN tbl.FIRST..tbl.LAST
  INSERT INTO myTable VALUES (sys_guid(), tbl(v_i).name, tbl(v_i).entityid);

I recommend this great article by Tim Hall: BULK COLLECT & FORALL

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top