Eu tenho duas tabelas no banco de dados MySQL- 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 CASCADE
eON DELETE CASCADE
Minha tabela pai
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
Minha pergunta é: Qual é a diferença entre as seguintes consultas sql.
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;
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;
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;
Existem erros nas consultas? O que essas consultas (1,2 e 3) significam? São iguais???
Um tópico muito bom sobre este assunto pode ser encontrado aqui e também aqui . O guia definitivo para o MySQL é, obviamente, a documentação, que pode ser encontrada aqui .
No padrão SQL 2003 existem 5 ações referenciais diferentes:
Para responder a pergunta:
CASCATA
ON DELETE CASCADE
significa que, se o registro pai for excluído, todos os registros filhos também serão excluídos. Isso 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 usandoTRIGGER
s. (No entanto, veja advertência nos comentários abaixo).ON UPDATE CASCADE
significa que se a chave primária pai for alterada, o valor filho também será alterado para refletir isso. Mais uma vez, na minha opinião, não é uma grande ideia. Se você estiver alterandoPRIMARY KEY
s com alguma regularidade (ou até mesmo!), há algo errado com seu design. Novamente, veja os comentários.ON UPDATE CASCADE ON DELETE CASCADE
significa que, se vocêUPDATE
ORDELETE
o pai, a alteração será em cascata para o filho. Isso é o equivalente aAND
ing os resultados das duas primeiras declarações.RESTRINGIR
RESTRICT
significa que qualquer tentativa de excluir e/ou atualizar o pai falhará gerando um erro. Este é o comportamento padrão no caso de uma ação referencial não ser especificada explicitamente.SEM AÇÃO
NO ACTION
: Do manual . Uma palavra-chave do SQL padrão. No MySQL, equivalente aRESTRICT
. O MySQL Server rejeita a operação de exclusão ou atualização para a tabela pai se houver um valor de chave estrangeira relacionado na tabela referenciada. Alguns sistemas de banco de dados têm verificações adiadas eNO ACTION
é uma verificação adiada. No MySQL, as restrições de chave estrangeira são verificadas imediatamente, entãoNO ACTION
é o mesmo queRESTRICT
.DEFINIR NULO
SET NULL
- novamente do manual. Exclua ou atualize a linha da tabela pai e defina a coluna ou colunas de chave estrangeira na tabela filha comoNULL
. Esta não é a melhor das idéias IMHO, principalmente porque não há como "viajar no tempo" - ou seja, olhar para as tabelas filhas e associar registros comNULL
s com o registro pai relevante -CASCADE
ou useTRIGGER
s para preencher tabelas de log para rastrear mudanças (mas, veja comentários).CONJUNTO PADRÃO
SET DEFAULT
. Ainda outra parte (potencialmente muito útil) do padrão SQL que o MySQL não se incomodou em implementar! Permite que o desenvolvedor especifique um valor para definir a(s) coluna(s) de chave estrangeira em um UPDATE ou DELETE. O InnoDB e o NDB rejeitarão as definições de tabela com umaSET DEFAULT
cláusula.Como mencionado acima, você deve gastar algum tempo olhando a documentação, aqui .
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:
E há pelo menos um registro
child
comparent_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:
E há pelo menos um registro
child
comparent_id = 1
, 2) falhará; nos casos 1) e 3), todos os registros comparent_id = 1
são apagados.3) está sintaticamente correto.
A documentação completa pode ser encontrada no manual .
Não tenho reputação suficiente para comentar as respostas anteriores. Então pensei em elaborar um pouco.
1) ON DELETE CASCADE significa que se o registro pai for excluído, todos os registros filho de referência também serão excluídos. O padrão ON UPDATE é RESTRICT, o que significa que o UPDATE no registro pai falhará.
2) A ação ON DELETE tem como padrão RESTRICT, o que significa que a DELETE no registro pai falhará. ON UPDATE CASCADE atualizará todos os registros filho 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 filhas) - a experiência diz a) se os IDs forem números de sequência gerados automaticamente, NÃO os use como chaves estrangeiras. Em vez disso, use alguma outra chave pai exclusiva. b) se os IDs forem GUIDs, não há problema em usá-los como chaves estrangeiras. Você verá a sabedoria nesta sugestão ao exportar e importar os registros ou copiar registros 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.