Search code examples
sqloracle-databasestored-proceduresoutput-parameter

returning output parameter from Oracle stored proc


I am trying to set the value of the output parameter thirdPartyId, but I am getting an error saying missing or invalid option at the set thirdPartyId statement.

PROCEDURE usp_insert_user(  userType VARCHAR2,
                                logonId VARCHAR2,
                                title VARCHAR2,
                                firstName VARCHAR2,
                                middleName VARCHAR2,
                                lastName VARCHAR2,
                                comments VARCHAR2,
                                thirdPartyId OUT number) AS
      begin
        set thirdPartyId := select max(third_party_id) + 1 from third_party_user_temp;
        insert into THIRD_PARTY_USER_TEMP
            (Third_party_id,web_logon_id,prsn_type_cd,prsn_title_nm,
            prsn_first_nm,prsn_mdl_nm,prsn_last_nm,addtnl_third_party_txt)
            VALUES(thirdPartyId,logonId,upper(userType),title,
            firstName,middleName,lastName,comments)
        ;
    end usp_insert_user;

What is the right way to do this?

Thanks!

Update: Is this any safer?

insert into THIRD_PARTY_USER_TEMP
        (Third_party_id,web_logon_id,prsn_type_cd,prsn_title_nm,
        prsn_first_nm,prsn_mdl_nm,prsn_last_nm,addtnl_third_party_txt)
        VALUES((select max(third_party_id) + 1 from third_party_user_temp),logonId,upper(userType),title,
        firstName,middleName,lastName,comments)
        returning third_party_id into thirdPartyId

Solution

  • You can do this:

    select max(third_party_id) + 1 into thirdPartyId from third_party_user_temp;
    

    This may be subject to contention problems if two people can run this at the same time - both could end up with the same new thirdPartyId. You can look at sequences to avoid this.


    If you define a sequence called, say, thirdPartyIdSeq, you can do this:

    PROCEDURE usp_insert_user(  userType VARCHAR2,
                                    logonId VARCHAR2,
                                    title VARCHAR2,
                                    firstName VARCHAR2,
                                    middleName VARCHAR2,
                                    lastName VARCHAR2,
                                    comments VARCHAR2,
                                    thirdPartyId OUT number) AS
          begin
            insert into THIRD_PARTY_USER_TEMP
                (Third_party_id,web_logon_id,prsn_type_cd,prsn_title_nm,
                prsn_first_nm,prsn_mdl_nm,prsn_last_nm,addtnl_third_party_txt)
                VALUES(third_party_id_seq.nextval,logonId,upper(userType),title,
                firstName,middleName,lastName,comments)
            returning third_party_id into thirdPartyId;
        end usp_insert_user;
    

    This uses the sequence to generate the next ID, and the returning clause populates your OUT parameter.

    You can also avoid the procedure and do the ID generation in a trigger, again using the sequence. There are a lot of examples of this approach around, not least on this site.

    CREATE OR REPLACE TRIGGER third_party_user_temp_bi
    BEFORE INSERT ON third_party_user_temp
    FOR EACH ROW
    BEGIN
        SELECT thirdPartyIdSeq.NEXTVAL
        INTO   :new.third_party_id
        FROM   dual;
    END;
    /
    

    Your insert then doesn't need to specify the ID to be used.