Oracle: Fastest way to UPSERT and return the last affected Row ID in oracle for large data sets

StackOverflow https://stackoverflow.com/questions/16965848

Domanda

This table schema in question is here: Oracle SQL: Selecting a single row with the latest date between multiple columns

I'm working with a table that has over 5 million entries. What is the fastest and most accurate way to upsert to this table AND return the last upserted row id using a stored procedure?

Most of what I've read recommends using the merge statement for upserts. However, merge doesn't support returning into.

In our table, we have the CREATE_DATE, CREATE_USER, UPDATE_DATE, and UPDATE_USER fields that are updated as expected. My thought was to create a stored procedure that returned the id of the row that has the latest date between those two columns and where the respective user data was equal to the current user data. This is what the people who answered the referring question helped me with (thanks!).

However, I'm concerned about the combined execution time vs other methods, as well as the huge gaps created in sequences due to merging. Calling a separate statement simply to get the id also seems a bit inefficient. However, almost everything I've read says that merge is much faster than the pre-merge upsert statements.

Note that these are being called through a c#/asp web application. Any help is appreciated :)

edit

Below is an example of the stored procedure I'm using for the Upsert. Note that the CREATE_DATE and UPDATE_DATE columns are updated with triggers.

create or replace
PROCEDURE     P_SAVE_EXAMPLE_TABLE_ROW
(
    pID IN OUT EXAMPLE_TABLE.ID%type,
    --Other row params here
    pUSER IN EXAMPLE_TABLE.CREATE_USER%type,

    pPLSQLErrorNumber OUT NUMBER, 
    pPLSQLErrorMessage OUT VARCHAR2
)
AS
BEGIN
MERGE INTO USERS_WORKGROUPS_XREF USING dual ON (ID=pID)
    WHEN NOT MATCHED THEN
        INSERT (--OTHER COLS--, CREATE_USER) VALUES (--OTHER COLS--, pUSER)
    WHEN MATCHED THEN
        UPDATE SET
            --OTHER COLS--
            UPDATE_USER=pUSER
        WHERE ID=pID;
    EXCEPTION
        WHEN OTHERS THEN
        pID := 0;
        pPLSQLErrorNumber := SQLCODE;
        pPLSQLErrorMessage := SUBSTR(SQLERRM, 1, 256);
        RETURN;

    -- STATEMENT TO RETURN LAST AFFECTED ID INTO pID GOES HERE
END;
È stato utile?

Soluzione

If you're trying to return the maximum value of a sequence-generated PK on the table then I'd just run a "Select max(id) .." directly afterwards. If other sessions are also modifying the table then maybe reading the currval of the sequence would be better.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top