Question

I am new to Oracle PL/SQL and am trying to adjust from SQL Server with C# to a Oracle custom web application using PL/SQL for multiple layers of the application.

I currectly am having issues with rolling back a transaction. Since I am using to writing reusable code, I have written my PL/SQL code using packages and methods within those classes. My update procedure first completes validation and if validated successfully, calls a succession of various package methods to complete the save. Unfortunately, my rollback in the EXCEPTION portion of the update procedure does not rollback everything when the Rollback function is called. I'm at a loss as to why it is doing this. My basic code (although not exact due to legal issues) is as follows:

PROCEDURE SaveApplicationData(
variableName                  IN VARCHAR2 DEFAULT NULL,
--...
seq_id OUT INT )
AS
BEGIN
SET TRANSACTION NAME 'Transaction Name';

  --Save initial program record
  SaveNewRecord(variableName, seq_id);
  IF (seq_id != 0) THEN
    --If saved successfully, seq_id represents record ID
    package_class.secondarySaveMethod(variableName, seq_id);
    second_package_class.anotherSaveMethod(variableName, seq_id);  

END IF;

  COMMIT;
  htp.p('Sequence ID: ' || seq_id);
  htp.p('Saved the record"' || programName || '" successfully!');
EXCEPTION
WHEN OTHERS THEN
 utilityPackage.rollbacktransaction;
END SaveApplicationData;

The utilityPackage.rollbacktransaction includes a ROLLBACK as well as the custom error exception handling package used by our organization.

Essentially, it will roll back the section that causes the error, but as soon as it rolls the section back, it continues with the rest of the transaction (and does not roll back previously executed blocks of code).

Please let me know if this does not make sense - and thank you in advance for your help!

Was it helpful?

Solution

Coming from a SQL Server environment before Oracle I can understand the confusion. Oracle does not use a BEGIN TRANSACTION. Instead, a transaction is implicitly started for you.

Thus, I believe in your case SET TRANSACTION NAME is not what you are looking to do, see SET TRANSACTION.

I recommend removing the rollback code from your package and placing it in C#. It should be the responsibility of the caller to commit. Use a transaction in C# to guarantee the the transaction is committed upon successful execution of the package(s).

Ideally, your package structure should look more like this.

declare
  ex_custom EXCEPTION;
  PRAGMA EXCEPTION_INIT( ex_custom, -20001 );
begin
  --Save initial program record
  SaveNewRecord(variableName, seq_id);
  IF (seq_id != 0) THEN
    --If saved successfully, seq_id represents record ID
    package_class.secondarySaveMethod(variableName, seq_id);
    second_package_class.anotherSaveMethod(variableName, seq_id);  
  ELSE
     -- seq_id invalid throw an exception
     RAISE_APPLICATION_ERROR(-20001,'Custom error')
  END IF;

  htp.p('Sequence ID: ' || seq_id);
  htp.p('Saved the record"' || programName || '" successfully!');
EXCEPTION
WHEN ex_custom THEN
  -- if needed we log it
  utility.log_exception;
  -- Raise it for the client to handle
  raise;
END SaveApplicationData;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top