Advantage SQL Engine
The TRY construct is used for exception handling and resource cleanup.
Syntax
TRY
statement_block
[catch_clauses]
[catchall_clause]
[finally_clause]
END TRY | END | ENDTRY;
catch_clauses ::= CATCH error_class statement_block
[catch_clauses]
catchall_clause ::= CATCH ALL statement_block
finally_clause ::= FINALLY statement_block
Description
The TRY construct provides a general mechanism for handling exceptions that are raised either intentionally by the script, or unintentionally due to a runtime error.
The statements in the TRY statement_block are executed. If there is no exception during the execution of all statements in the block, execution continues to the finally_clause if one is present; otherwise, the execution continues with the statement after the END [TRY] clause.
If an exception is raised while executing the statements in the statement_block, the script execution engine will set the __errcode, __errclass, and the __errtext system variables and execution immediately jumps to the catch_clauses if there is one. Each CATCH error_class clause is examined sequentially for a match. If the error_class of a CATCH clause matches the __errclass variable of the exception, the statement_block for the CATCH will be executed. Once the CATCH clause is executed or if there is no CATCH clause, executing jumps to the finally_clause if there is one.
The catchall_clause can be used to handle any exception regardless of the __errclass. Since the CATCH clauses, if present, are always placed in front of the catchall_clause, the catchall_clause will only be executed if an exception has not been handled. In effect, the CATCH clauses may be implemented using just a catchall_clause and the IF … ELSEIF … END IF in the statement block of the catchall_clause.
The statement:
TRY
…
CATCH a
stmtblock_a
CATCH b
stmtblock_b
END TRY;
is equivalent to:
TRY
…
CATCH ALL
IF __errclass = 'a' THEN
Stmtblock_a
ELSEIF __errclass = 'b' THEN
stmtblock_b
ELSE
RAISE;
END IF;
END TRY;
Runtime errors not raised by an explicit RAISE statement will have the exception class ‘ADS_SCRIPT_EXCEPTION’ and have the error code and error message corresponding to the error.
The TRY statement may be used to catch exceptions raised during recursive execution of stored procedures or triggers.
The finally_clause of a TRY statement will always be executed regardless of errors or other execution branch statements, such as LEAVE, LOOP and RETURN.
If none of the catch_clauses, the catchall_clause, or the finally_clause is present, an exception will be raised with error code 2219.
Example 1
// A sample script to create a new table. If there is an existing
// table with the same name, drop that table and re-create the
// table
TRY
CREATE TABLE #Test( id integer, name char( 20 ) );
CATCH ADS_SCRIPT_EXCEPTION
// Only do something if the error code indicates
// table already exists
IF __errcode = 2010 THEN
DROP TABLE #Test;
CREATE TABLE #Test( id integer, name char( 20 ) );
ELSE
RAISE; // re-raise the exception
END IF;
END TRY;
Example 2
// Create a new temporary table for storing intermediate data.
// Use the finally block to ensure that the temporary table
// is deleted after usage
DECLARE totalCnt Integer; nameCnt Integer; avgCnt Double;
DECLARE cursor1 CURSOR;
// Use SELECT … INTO … to create the temporary table
SELECT lastname, count(*) cnt INTO #temp
FROM employees
GROUP BY lastname;
// Use TRY … FINALLY … to ensure the #temp is deleted
TRY
totalCnt = 0;
nameCnt = 0;
OPEN cursor1 AS SELECT * FROM #Temp;
// Use a TRY … FINALLY … to ensure the cursor is closed
TRY
WHILE FETCH cursor1 DO
totalCnt = totalCnt + cursor1.cnt;
nameCnt = nameCnt + 1;
END WHILE;
FINALLY
// Ensure the cursor is closed
CLOSE cursor1;
END TRY;
// Don’t calculate the avg if the nameCnt is zero to
// avoid division by zero error
// Although return is used, the FINALLY block will still
// be executed.
IF nameCnt = 0 THEN
RETURN;
END IF;
// Calculate the average count for each name
avgCnt = totalCnt / nameCnt;
FINALLY
DROP TABLE #Temp;
END;