I want to return the primary key from an oracle merge query. I'm using a single statement to insert if not exist and I don't want to use procedure or function to do so..
this is the sample query
merge into myTable e
using (select :empname name from dual) s
on (UPPER(TRIM(e.empname)) = UPPER(TRIM(s.name)))
when not matched then insert (empname)
values (s.name)
and I need to get another primary key field of the myTable. the primary key is inserted using sequence and trigger
I tried adding RETURNING empID into :empId
but it gives error
No, PK is not mandatory to run successfully a MERGE statement.
Merge is just like any other DML and will require a commit or rollback as any other DML statement at the end of the transaction.
Use the MERGE statement to select rows from one or more sources for update or insertion into a table or view. You can specify conditions to determine whether to update or insert into the target table or view. This statement is a convenient way to combine multiple operations.
The MERGE statement tries to compare the source table with the target table based on a key field and then do some of the processing. The MERGE statement actually combines the INSERT, UPDATE, and the DELETE operations altogether.
There's a problem.
Merge Into
doesn't support Returning Into
, so that won't work.To solve it:
sql%rowcount
return 0 after the update, perform the insert instead.UPPER(TRIM(name))
) to find the record that was updated. You can try this. You will need to declare a package to capture your id, otherwise it will not be visible to the SQL statement and you will get a error:
pls-00231: function name may not be used in SQL
So, first create the package with functions to capture and then later access the ID from the merge statement:
CREATE OR REPLACE PACKAGE CaptureId
AS
FUNCTION SaveId(newId IN NUMBER) RETURN NUMBER;
FUNCTION GetId RETURN NUMBER;
END;
CREATE OR REPLACE PACKAGE BODY CaptureId
AS
capturedId NUMBER(10);
FUNCTION SaveId(newId IN NUMBER) RETURN NUMBER IS
BEGIN
capturedId := newId;
RETURN capturedId;
END;
FUNCTION GetId RETURN NUMBER IS
BEGIN
RETURN capturedId;
END;
END;
Given a simple table and sequence generator defined as:
CREATE TABLE EMPLOYEE
(
EMPLOYEE_ID NUMBER(10) NOT NULL,
FIRST_NAME VARCHAR2(120) NOT NULL,
LAST_NAME VARCHAR2(120) NOT NULL,
CONSTRAINT PK_EMPLOYEE PRIMARY KEY (EMPLOYEE_ID) ENABLE
);
CREATE SEQUENCE SEQ_EMPLOYEE;
You can then use the package in an anonymous block with your merge statement to capture the id and return it. Note that this is a very simple example and it will not work with array-bound variables unless you rework the package to capture the IDs into a table type. If I get a chance, I may try to put together an example that shows this.
BEGIN
MERGE INTO EMPLOYEE USING (SELECT CaptureId.SaveId(:myInputId) AS EMPLOYEE_ID,
:myFirstName as FIRST_NAME,
:myLastName as LAST_NAME
FROM DUAL) B
ON (A.EMPLOYEE_ID = B.EMPLOYEE_ID)
WHEN NOT MATCHED THEN
INSERT (EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME)
VALUES (CaptureId.SaveId(SEQ_EMPLOYEE.NEXTVAL),
B.FIRST_NAME,
B.LAST_NAME)
WHEN MATCHED THEN
UPDATE SET A.FIRST_NAME= B.FIRST_NAME,
A.LAST_NAME= B.LAST_NAME;
SELECT CaptureId.GetId INTO :myOutputId FROM DUAL;
END;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With