A instrução DECLARE HANDLER cria uma rotina de tratamento de erro para manipular exceções.
>>-DECLARE--+-CONTINUE-+--HANDLER FOR--| Estado |--Stmt-------->< '-EXIT-----' Estado .-<<-- , --<<------------------------------------------------. V | |------SQLSTATE--+-+-------+--' Text '----------------------+---+--| | '-VALUE-' | '---LIKE--' Text '--+------------------+---' '-ESCAPE--' Text '-'
Você pode declarar rotinas de tratamento em escopos explicitamente declarados (BEGIN...END) e escopos implicitamente declarados (por exemplo, a cláusula ELSE de uma instrução IF). Entretanto, todas as declarações de rotina de tratamento devem ficar juntas no início do escopo, antes de quaisquer outras instâncias.
Se não houver exceções, a presença de rotinas de tratamento não afetará o comportamento ou desempenho de um programa SQL. Se ocorrer uma exceção, o WebSphere Message Broker comparará o estado SQL da exceção com os estados SQL associados a quaisquer rotinas de tratamento relevantes, até que a exceção deixe o nó (exatamente como seria se não houvesse rotinas de tratamento) ou uma rotina de tratamento correspondente seja localizada. Dentro de um escopo, as rotinas de tratamento são procuradas na ordem em que são declaradas; ou seja, da primeira à última. Os escopos são procurados do interno para o externo.
Os valores do estado SQL fornecidos em instruções DECLARE... HANDLER... podem ser comparados diretamente com o estado SQL da exceção ou podem ser comparados usando caracteres curinga. Para comparar os valores de estado diretamente, especifique VALUE ou nenhum operador de condição. Para fazer uma comparação curinga, use os caracteres sublinhado e percentual para representar curingas de caracteres únicos e múltiplos, respectivamente, e especificar o operador LIKE. O método curinga permite que todas as exceções de um tipo geral sejam manipuladas sem ter de listá-las exaustivamente.
Se um manipulador correspondente for localizado, o SQLSTATE e outros registros especiais serão atualizados (de acordo com as regras descritas posteriormente nesta seção) e a instrução do manipulador é processada.
Como a instrução da rotina de tratamento deve ser uma instrução única, geralmente ela é uma instrução composta (como BEGIN...END) contendo várias outras instruções. Não há nenhum comportamento especial associado a essas instruções internas e não há restrições especiais. Elas podem incluir, por exemplo, RETURN, ITERATE ou LEAVE, que afetam as rotinas que as contêm e as construções de loop da mesma maneira como se estivessem contidas no próprio escopo.
As rotinas de tratamento podem conter rotinas de tratamento para exceções que ocorrem dentro da própria rotina de tratamento.
Cada rotina de tratamento possui seus próprios registros especiais SQLCODE, SQLSTATE, SQLNATIVEERROR e SQLERRORTEXT. Eles entram no escopo e seus valores são configurados logo antes da primeira instrução do manipulador ser executada. Eles permanecem válidos até que a última instrução do manipulador tenha sido executada. Como não há transporte de valores SQLSTATE de uma rotina de tratamento para outra, as rotinas de tratamento podem ser gravadas independentemente.
As rotinas de tratamento absorvem as exceções, impedindo que elas cheguem ao nó de entrada e, portanto, fazendo com que a transação seja confirmada em vez ter o rollback efetuado. Uma rotina de tratamento pode utilizar uma instrução RESIGNAL ou THROW para evitar isso.
Consulte Função SQLSTATE para obter uma lista dos SQLSTATES válidos que você pode usar em um HANDLER.
DECLARE retryCount INTEGER 0;
DECLARE afterCount INTEGER 0;
WHILE retryCount <= 10 DO
DECLARE EXIT HANDLER FOR SQLSTATE VALUE 'U11222'
BEGIN
/* This demonstrates how to pass data to the HANDLER in the SQL
special registers */
SET OutputRoot.XMLNSC.Top.WHILE.mySQLCODE = SQLCODE;
SET OutputRoot.XMLNSC.Top.WHILE.mySQLSTATE = SQLSTATE;
SET OutputRoot.XMLNSC.Top.WHILE.mySQLNATIVEERROR = SQLNATIVEERROR;
SET OutputRoot.XMLNSC.Top.WHILE.mySQLERRORTEXT = SQLERRORTEXT;
SET retryCount = retryCount + 1;
/* If we are an EXIT HANDLER, control is now passed to back to the
WHILE statement */
END;
/* In a real scenario this could be a PROPAGATE statement, and the exception
could be thrown by a 'downstream' node. In this case the HANDLER would
normally cope with a wider range of exception, for example, using LIKE '%' */
THROW USER EXCEPTION VALUES( -1, 'U11222', 42, 'error text' );
/* This is the next statement executed if it is a CONTINUE HANDLER */
SET afterCount = afterCount + 1;
END WHILE;
SET OutputRoot.XMLNSC.Top.WHILE.retryCount = retryCount;
SET OutputRoot.XMLNSC.Top.WHILE.afterCount = afterCount;
With EXIT (as above) the output is:
<Top>
<WHILE>
<mySQLCODE>-1</mySQLCODE>
<mySQLSTATE>U11222</mySQLSTATE>
<mySQLNATIVEERROR>42</mySQLNATIVEERROR>
<mySQLERRORTEXT>error text</mySQLERRORTEXT>
<retryCount>11</retryCOUNT>
<afterCount>0</afterCOUNT>
</WHILE>
</Top>
Changing the HANDLER to be CONTINUE (DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE
'U11222') then the output is:
<Top>
<WHILE>
<mySQLCODE>-1</mySQLCODE>
<mySQLSTATE>U11222</mySQLSTATE>
<mySQLNATIVEERROR>42</mySQLNATIVEERROR>
<mySQLERRORTEXT>error text</mySQLERRORTEXT>
<retryCount>11</retryCOUNT>
<afterCount>11</afterCOUNT>
</WHILE>
</Top>
You see the difference in afterCount in the output message.-- Eliminar as tabelas para que possam ser recriadas com a definição mais recente.
-- Se o programa nunca tiver sido executado antes, ocorrerão erros porque
-- não é possível eliminar tabelas que não existem. Ignore-os.
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE LIKE'%' BEGIN END;
PASSTHRU 'DROP TABLE Shop.Customers' TO Database.DSN1;
PASSTHRU 'DROP TABLE Shop.Invoices' TO Database.DSN1;
PASSTHRU 'DROP TABLE Shop.Sales' TO Database.DSN1;
PASSTHRU 'DROP TABLE Shop.Parts' TO Database.DSN1;
END;