Eu tenho uma tabela B
com uma chave estrangeira para tabela A
. Eu quero DELETE
algumas linhas na tabela B
e também quero DELETE
suas linhas pai na tabela A
. No entanto, os critérios de exclusão são baseados na tabela B
. As linhas na tabela A
não podem ser excluídas primeiro porque a referência na tabela B
restringe a exclusão, mas também preciso obter as chaves das A
linhas para excluir em B
.
Aqui está um SQLFiddle com uma estrutura de tabela de exemplo: http://sqlfiddle.com/#!4/f156c/4/0 .
Minha primeira inclinação foi tentar salvar as chaves SELECT
inserindo-as de B
em uma variável e, em seguida, usá -las em DELETE
de A
.
DECLARE
A_ID_TO_DELETE DBMS_SQL.NUMBER_TABLE;
BEGIN
SELECT A_ID BULK COLLECT INTO A_ID_TO_DELETE
FROM (SELECT A_ID
FROM B
WHERE LENGTH(B_DATA) > 4
);
DELETE FROM B
WHERE LENGTH(B_DATA) > 4;
DELETE FROM A
WHERE A_ID IN A_ID_TO_DELETE;
END;
/
Mas isso só dá um PLS-00382: expression is of wrong type
erro. O erro em si vem DELETE
do A
; Eu sei disso porque se eu comentar, o bloco será executado.
Como posso contornar o expression is of wrong type
erro ou qual é outra maneira de abordar isso?
Versão do Oracle: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
(Sim, estou bem ciente de quantos anos isso tem. A escolha do banco de dados do cliente, não nossa.)
Tente assim,
As restrições de chave estrangeira no Oracle são definidas (por padrão) como
NON DEFERRABLE
o que significa que a restrição é verificada sempre no final das instruções. Existem mais duas maneiras de definir uma restrição:DEFERRABLE INITIALLY DEFERRED
Se você tiver a restrição definida (ou modificá-la agora) como
DEFERRABLE INITIALLY DEFERRED
, então a verificação da restrição acontecerá no final das transações. Portanto, isso funcionaria para você (mas também modificaria como a restrição é verificada em todas as outras transações).DEFERRABLE INITIALLY IMMEDIATE
Se você definir como
DEFERRABLE
(obtém o padrão deINITIALLY IMMEDIATE
), ainda será verificado no final das instruções, mas poderá ser adiado. Assim, você pode optar por definir todas as restrições dentro de uma transação comSET CONSTRAINTS ALL DEFERRED;
e isso funcionaria bem:Teste no SQL-Fiddle
Mais detalhes sobre restrições em Oracle docs: Constraints and Managing Integrity Constraints