Eu tenho um banco de dados Postgresql no qual desejo fazer algumas exclusões em cascata. No entanto, as tabelas não são configuradas com a regra ON DELETE CASCADE. Existe alguma maneira de executar uma exclusão e dizer ao Postgresql para fazer cascata apenas desta vez? Algo equivalente a
DELETE FROM some_table CASCADE;
As respostas para essa pergunta mais antiga fazem parecer que essa solução não existe, mas imaginei que faria essa pergunta explicitamente apenas para ter certeza.
postgresql
Eli Courtwright
fonte
fonte
Respostas:
Não. Para fazer isso apenas uma vez, basta escrever a instrução delete para a tabela que você deseja colocar em cascata.
fonte
Se você realmente deseja o
DELETE FROM some_table CASCADE;
que significa " remover todas as linhas da tabelasome_table
", pode usar emTRUNCATE
vez deDELETE
eCASCADE
sempre é suportado. No entanto, se você deseja usar a exclusão seletiva com umawhere
cláusula, issoTRUNCATE
não é bom o suficiente.USE WITH CARE - Isso eliminará todas as linhas de todas as tabelas que têm uma restrição de chave estrangeira
some_table
e todas as tabelas que têm restrições nessas tabelas, etc.O Postgres suporta
CASCADE
com o comando TRUNCATE :Facilmente, isso é transacional (isto é, pode ser revertido), embora não esteja totalmente isolado de outras transações simultâneas e tenha várias outras advertências. Leia os documentos para obter detalhes.
fonte
Eu escrevi uma função (recursiva) para excluir qualquer linha com base em sua chave primária. Eu escrevi isso porque não queria criar minhas restrições como "ao excluir cascata". Eu queria poder excluir conjuntos complexos de dados (como um DBA), mas não permitir que meus programadores pudessem excluir em cascata a exclusão sem pensar em todas as repercussões. Ainda estou testando essa função, portanto pode haver erros nela - mas não tente se o seu banco de dados tiver chaves primárias de várias colunas (e, portanto, estrangeiras). Além disso, todas as chaves devem poder ser representadas na forma de cadeia, mas podem ser escritas de uma maneira que não tenha essa restrição. De qualquer maneira, eu uso essa função MUITO POUCOSAMENTE, eu dou muito valor aos meus dados para permitir as restrições em cascata de tudo. Basicamente, essa função é passada no esquema, nome da tabela e valor primário (em forma de cadeia), e começará encontrando as chaves estrangeiras nessa tabela e assegurando que os dados não existam - se existir, chama-se recursivamente aos dados encontrados. Ele usa uma matriz de dados já marcados para exclusão para evitar loops infinitos. Teste e informe-me como funciona para você. Nota: é um pouco lento. Eu chamo assim:
select delete_cascade('public','my_table','1');
fonte
IN
operador com sub-seleções em vez de=
(portanto, passo para usar a lógica de conjuntos), isso se tornaria muito mais rápido.Se bem entendi, você poderá fazer o que deseja, eliminando a restrição de chave estrangeira, adicionando uma nova (que irá cascatear), executando suas tarefas e recriando a restrição de chave estrangeira restritiva.
Por exemplo:
Obviamente, você deve abstrair coisas assim em um procedimento, para o bem da sua saúde mental.
fonte
Não posso comentar a resposta de Palehorse, então adicionei minha própria resposta. A lógica do Palehorse está correta, mas a eficiência pode ser ruim com grandes conjuntos de dados.
É mais rápido se você tiver índices em colunas e o conjunto de dados for maior que alguns registros.
fonte
Sim, como outros já disseram, não há um conveniente 'DELETE FROM my_table ... CASCADE' (ou equivalente). Para excluir registros filhos protegidos por chave estrangeira não em cascata e seus ancestrais referenciados, suas opções incluem:
É de propósito que contornar restrições de chave estrangeira não é conveniente, presumo; mas entendo por que, em circunstâncias específicas, você deseja fazer isso. Se é algo que você fará com alguma frequência, e se estiver disposto a desprezar a sabedoria dos DBAs em todos os lugares, convém automatizá-lo com um procedimento.
Eu vim aqui há alguns meses atrás, procurando uma resposta para a pergunta "CASCADE DELETE apenas uma vez" (originalmente feita há mais de uma década!). Eu obtive alguma milhagem da solução inteligente de Joe Love (e da variante de Thomas CG de Vilhena), mas no final meu caso de uso tinha requisitos específicos (manipulação de referências circulares dentro da mesa, por exemplo) que me forçaram a adotar uma abordagem diferente. Essa abordagem acabou se tornando recursivamente_delete (PG 10.10).
Estou usando o recursively_delete na produção há um tempo e agora me sinto (cautelosamente) confiante o suficiente para disponibilizá-lo a outras pessoas que possam acabar aqui procurando idéias. Assim como na solução de Joe Love, ele permite excluir gráficos inteiros de dados como se todas as restrições de chave estrangeira no seu banco de dados fossem momentaneamente definidas para CASCADE, mas oferece alguns recursos adicionais:
fonte
Você pode usar para automatizar isso, você pode definir a restrição de chave estrangeira com
ON DELETE CASCADE
.Cito o manual de restrições de chave estrangeira :
fonte
Peguei a resposta de Joe Love e a reescrevi usando o
IN
operador com sub-selects em vez de=
acelerar a função (de acordo com a sugestão de Hubbitus):fonte
in
operador e as subconsultas.A opção excluir com cascata se aplica apenas a tabelas com chaves estrangeiras definidas. Se você excluir, e ele disser que não pode, porque violaria a restrição de chave estrangeira, a cascata fará com que ele exclua as linhas incorretas.
Se você deseja excluir as linhas associadas dessa maneira, primeiro precisará definir as chaves estrangeiras. Além disso, lembre-se de que, a menos que você o instrua explicitamente para iniciar uma transação ou altere os padrões, ele fará uma confirmação automática, o que pode levar muito tempo para ser limpo.
fonte