Diferença entre On Delete Cascade e On Update Cascade no mysql


45

Eu tenho duas tabelas em MySQL database- parent, child. Estou tentando adicionar referências de chave estrangeira à minha tabela filho com base na tabela pai. Existe alguma diferença significativa entre ON UPDATE CASCADEeON DELETE CASCADE

My Parent Table

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

Minha pergunta é: Qual é a diferença entre as seguintes consultas sql.

  1. ON DELETE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON DELETE CASCADE
    ) ENGINE=INNODB;
  2. ON UPDATE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON UPDATE CASCADE
    ) ENGINE=INNODB;
  3. ON UPDATE CASCADE ON DELETE CASCADE

    CREATE TABLE child (
            id INT, 
            parent_id INT,
            INDEX par_ind (parent_id),
            FOREIGN KEY (parent_id) 
                REFERENCES parent(id)
                ON UPDATE CASCADE ON DELETE CASCADE
        ) ENGINE=INNODB;

Há algum erro nas consultas? O que essas consultas (1,2 e 3) significam? Eles são iguais ???


1
ps <nitpick> para completar, o que você está falando acima são instruções DDL (Data Definition Language) , e não consultas. Geralmente, uma consulta é considerada DML (SELECT, INSERT, UPDATE, DELETE) da linguagem de manipulação de dados </nitpick>
Vérace

Outro ps novamente por completude, eu me perguntava qual era o padrão. Então, eu criei um filho sem atualização ou exclusão. O que acontece é que você não pode atualizar nem excluir um pai que tenha um filho dependente. Isso faz todo o sentido, no entanto MySQL nem sempre é um modelo dessa característica particular :-)
Verace

Respostas:


64

Um tópico muito bom sobre esse assunto pode ser encontrado aqui e também aqui . O guia definitivo para o MySQL é, obviamente, a documentação, encontrada aqui .

No padrão SQL 2003, existem 5 ações referenciais diferentes:

  1. CASCATA
  2. RESTRINGIR
  3. SEM AÇÃO
  4. SET NULL
  5. CONJUNTO PADRÃO

Para responder à pergunta:

  1. CASCATA

    • ON DELETE CASCADEsignifica que, se o registro pai for excluído, qualquer registro filho também será excluído. Esta não é uma boa ideia na minha opinião. Você deve acompanhar todos os dados que já estiveram em um banco de dados, embora isso possa ser feito usando TRIGGERs. (No entanto, veja ressalva nos comentários abaixo).

    • ON UPDATE CASCADEsignifica que, se a chave primária pai for alterada, o valor filho também será alterado para refletir isso. Novamente, na minha opinião, não é uma ótima idéia. Se você está mudando PRIMARY KEYs com alguma regularidade (ou mesmo!), Há algo errado com seu design. Mais uma vez, veja os comentários.

    • ON UPDATE CASCADE ON DELETE CASCADEsignifica que, se você UPDATE OU DELETE o pai, a alteração é transmitida em cascata ao filho. Isso é o equivalente ANDaos resultados das duas primeiras declarações.

  2. RESTRINGIR

    • RESTRICTsignifica que qualquer tentativa de excluir e / ou atualizar o pai falhará ao gerar um erro. Esse é o comportamento padrão no caso de uma ação referencial não ser especificada explicitamente.

      Para um ON DELETEou ON UPDATEque não é especificado, a ação padrão é sempre RESTRICT`.

  3. SEM AÇÃO

    • NO ACTION: A partir do manual do . Uma palavra-chave do SQL padrão. No MySQL, equivalente a RESTRICT. O MySQL Server rejeita a operação de exclusão ou atualização da tabela pai se houver um valor de chave estrangeira relacionado na tabela referenciada. Alguns sistemas de banco de dados possuem verificações adiadas e NO ACTIONé uma verificação adiada. No MySQL, restrições de chave estrangeira são verificadas imediatamente, NO ACTIONo mesmo acontece com RESTRICT.
  4. SET NULL

    • SET NULL- novamente a partir do manual. Exclua ou atualize a linha da tabela pai e defina a coluna ou colunas da chave estrangeira na tabela filho como NULL. Esta não é a melhor das idéias IMHO, principalmente porque não há como "viajar no tempo" - ou seja, olhar de volta para as tabelas filho e associar registros com NULLs ao registro pai relevante - CASCADEou use TRIGGERs para preencher as tabelas de log para rastrear mudanças (mas, veja comentários).
  5. CONJUNTO PADRÃO

    • SET DEFAULT. Mais uma parte (potencialmente muito útil) do padrão SQL que o MySQL não se deu ao trabalho de implementar! Permite que o desenvolvedor especifique um valor para o qual definir a (s) coluna (s) de chave estrangeira em um UPDATE ou DELETE. O InnoDB e o NDB rejeitarão as definições da tabela com uma SET DEFAULTcláusula.

Como mencionado acima, você deve passar algum tempo olhando a documentação aqui .


8
Gosto da sua resposta completa, mas não concordo com esta afirmação. "Você deve acompanhar todos os dados que já estiveram em um banco de dados" - isso depende muito do design e dos objetivos do banco de dados. Por exemplo, uma definição de receita (não estou falando de comida - mais como configurações de sistemas) quando a definição de receita é excluída, não faz sentido manter os filhos associados dessa receita - que apenas incham o banco de dados sem motivo. Também trabalho em tabelas para sistemas de máquinas - não preciso mais dos dados; processo e se livrar dele. Fora isso, sua resposta é fantástica.
StixO

2
semelhante ao @StixO Gosto mais desta resposta, mas não concordo com a alteração da chave primária. Definitivamente, existem projetos nos quais isso seria uma má idéia, mas quando você entra em um banco de dados distribuído, pode ser muito desejável que as chaves primárias sejam livres para serem reatribuídas sem perder a identidade de um registro.
Garet Claborn

"Não é uma boa ideia para mim. Você deve acompanhar todos os dados que já estiveram em um banco de dados." - Não sei se entendi o seu ponto. Se você estiver em cascata 'ao excluir', já decidiu que precisa excluir algo. Se você decidir nunca excluir nada, nada ocorrerá em cascata. O benefício de ter isso é que, no seu aplicativo, você pode ter certeza de que, ao procurar um registro com um ID estrangeiro, sabe que ele estará lá e que não haverá linhas órfãs inchando seu banco de dados, caso decida excluir alguma coisa.
Jeff Ryan

A lógica aqui é bastante defeituosa em alguns lugares, e mais ainda em nosso novo mundo GDPR. Eu concordo com a noção de que, se as chaves primárias estão mudando, pode ser um sinal de algo errado.
Chuck Le Butt

Se você estiver alterando PRIMARY KEYs com alguma regularidade (ou até mesmo!), Há algo errado com seu design. Você quer dizer que ON UPDATE CASCADE altera o valor da chave ou o nome da chave?
Billal Begueradj 04/03

8

Essas duas são ações a serem executadas, respectivamente, quando o registro referenciado na tabela pai altera seu ID e quando é excluído.

Se você executar:

UPDATE parent SET id = -1 WHERE id = 1;

E há pelo menos um registro childcom parent_id = 1, 1) falhará; nos casos 2) e 3), todos os registros com parent_id = 1 são atualizados para parent_id = -1.

Se você executar:

DELETE FROM parent WHERE id = 1;

E há pelo menos um registro childcom parent_id = 1, 2) falhará; nos casos 1) e 3), todos os registros com parent_id = 1são excluídos.

3) está sintaticamente correto.

A documentação completa pode ser encontrada no manual .


6

Não tenho reputação suficiente para comentar as respostas anteriores. Então pensei em elaborar um pouco.

1) EM EXCLUIR CASCADE significa que, se o registro pai for excluído, qualquer registro filho de referência também será excluído. O padrão ON UPDATE é RESTRICT, o que significa que a atualização no registro pai falhará.

2) A ação ON DELETE assume como padrão RESTRICT, o que significa que DELETE no registro pai falhará. ON UPDATE O CASCADE atualizará todos os registros filhos de referência quando o registro pai for atualizado.

3) Veja as ações CASCADE em 1) e 2) acima.

Ao usar IDs de registro pai como chaves estrangeiras (em tabelas filho) - a experiência diz que a) se os IDs são números de sequência gerados automaticamente, NÃO os use como chaves estrangeiras. Use outra chave pai exclusiva. b) se os IDs são GUIDs, não há problema em usá-los como chaves estrangeiras. Você verá a sabedoria desta sugestão ao exportar e importar os registros ou copiá-los para outro banco de dados. É muito complicado lidar com números de sequência gerados automaticamente durante a migração de dados quando eles são referenciados como chaves estrangeiras.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.