0

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!

4

1 回答 1

1

来自 Oracle 之前的 SQL Server 环境,我可以理解这种困惑。Oracle 不使用BEGIN TRANSACTION。相反,会为您隐式启动事务。

因此,我相信在您的情况下 SET TRANSACTION NAME 不是您想要做的,请参阅 SET TRANSACTION

我建议从您的包中删除回滚代码并将其放在 C# 中。提交应该是调用者的责任。在 C# 中使用事务来保证在成功执行包时提交事务。

理想情况下,您的包结构应该更像这样。

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;
于 2013-09-28T04:36:40.883 回答