Quando usar "ON UPDATE CASCADE"

420

Uso "ON DELETE CASCADE" regularmente, mas nunca uso "ON UPDATE CASCADE", pois não tenho tanta certeza de que situação será útil.

Para fins de discussão, vamos ver algum código.

CREATE TABLE parent (
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
);

CREATE TABLE child (
    id INT NOT NULL AUTO_INCREMENT, parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
);

Para "ON DELETE CASCADE", se um pai com um idfor excluído, um registro em filho com parent_id = parent.idserá excluído automaticamente. Isso não deve ser problema.

  1. Isso significa que "ON UPDATE CASCADE" fará a mesma coisa quando ido pai for atualizado?

  2. Se (1) for verdadeiro, significa que não há necessidade de usar "ON UPDATE CASCADE" se parent.idnão for atualizável (ou nunca será atualizado) como quando está AUTO_INCREMENTou sempre está definido para ser TIMESTAMP. Isso está certo?

  3. Se (2) não for verdade, em que outro tipo de situação devemos usar "ON UPDATE CASCADE"?

  4. E se eu (por algum motivo) atualizar o arquivo child.parent_idcomo algo inexistente, ele será excluído automaticamente?

Bem, eu sei que algumas das perguntas acima podem ser testadas programaticamente para entender, mas também quero saber se alguma delas depende ou não de um fornecedor de banco de dados.

Por favor, mostre alguma luz.

NawaMan
fonte
1
Veja também: stackoverflow.com/questions/6894162/…
Xiè Jìléi

Respostas:

468

É verdade que, se sua chave primária for apenas um valor de identidade incrementado automaticamente, você não terá uso real para ON UPDATE CASCADE.

No entanto, digamos que sua chave primária seja um código de barras UPC de 10 dígitos e, devido à expansão, é necessário alterá-la para um código de barras UPC de 13 dígitos. Nesse caso, ON UPDATE CASCADE permitiria alterar o valor da chave primária e quaisquer tabelas que tenham referências de chave estrangeira ao valor serão alteradas de acordo.

Em referência ao item 4, se você alterar o ID filho para algo que não existe na tabela pai (e você tiver integridade referencial), deverá receber um erro de chave estrangeira.

C-Pound Guru
fonte
6
Só tinha de usar ON UPDATE CASCADE-me para atualizar as chaves primárias em uma tabela velha que não usam uma chave de auto-incrementada
BlueRaja - Danny Pflughoeft
86
  1. Sim, significa que, por exemplo, se você fizer UPDATE parent SET id = 20 WHERE id = 10todos os filhos, os parent_id de 10 também serão atualizados para 20

  2. Se você não atualizar o campo ao qual a chave estrangeira se refere, essa configuração não será necessária

  3. Não consigo pensar em outro uso.

  4. Você não pode fazer isso, pois a restrição de chave estrangeira falharia.

Zed
fonte
29

Eu acho que você acertou em cheio!

Se você seguir as práticas recomendadas de design de banco de dados e sua chave primária nunca for atualizável (o que eu acho que sempre deve ser o caso), você nunca precisará realmente da ON UPDATE CASCADEcláusula.

Zed afirmou que, se você usar uma chave natural (por exemplo, um campo regular da tabela do banco de dados) como chave primária, poderá haver certas situações em que você precisará atualizar suas chaves primárias. Outro exemplo recente seria o ISBN (International Standard Book Numbers), que passou de 10 para 13 dígitos + caracteres há pouco tempo.

Este não é o caso se você optar por usar chaves substitutas (por exemplo, geradas artificialmente pelo sistema) como sua chave primária (que seria minha escolha preferida em todas as ocasiões, exceto as mais raras).

Portanto, no final: se sua chave primária nunca muda, você nunca precisa da ON UPDATE CASCADEcláusula.

Marc

marc_s
fonte
O que são chaves "artificialmente geradas pelo sistema"? UUIDs?
HPWD 10/01/19
1
@HPWD: apenas uma chave "artificial" (um valor que não é baseado nem é derivado de seus dados reais) que é gerado pelo sistema - pode ser um GUID, um INT ou um BIGINT - ou qualquer coisa realmente - não importa. A questão é: esse valor não está relacionado aos seus próprios dados reais - e o sistema está gerando esse valor automaticamente para você.
21418 Marc Marsh
@ marc-s obrigado por dedicar um tempo para escrever isso. Sua resposta fez todo o sentido.
HPWD 16/01/19
2
Uma tabela de coluna única com chaves naturais é uma alternativa boa e limpa para enums na minha opinião (pelo menos nos tipos de banco de dados MySQL). Por exemplo, considere uma tabela colorscom linhas blue, purple, yellow, e uma mesa productscom uma product_colorcoluna, sendo FK'ed à colorsmesa. Isso restringe as opções como uma enumeração, mas, diferentemente de um número inteiro com auto incremento, não requer uma junção para obter o nome da cor. Nesse caso, on update cascadeé uma boa ideia, se você decidir que purpledeve ser chamado violet.
okdewit
18

Há alguns dias, tive um problema com os gatilhos e descobri que isso ON UPDATE CASCADEpode ser útil. Veja este exemplo (PostgreSQL):

CREATE TABLE club
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE band
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE concert
(
    key SERIAL PRIMARY KEY,
    club_name TEXT REFERENCES club(name) ON UPDATE CASCADE,
    band_name TEXT REFERENCES band(name) ON UPDATE CASCADE,
    concert_date DATE
);

Na minha edição, eu tive que definir algumas operações adicionais (trigger) para atualizar a tabela do show. Essas operações tiveram que modificar o nome do clube e o nome da banda. Eu era incapaz de fazê-lo, por causa de referência. Não consegui modificar os shows e depois lidar com as mesas de clubes e bandas. Eu também não poderia fazer o contrário. ON UPDATE CASCADEfoi a chave para resolver o problema.

Ariel Grabijas
fonte
3
Bom comentário. Acho que na atualização em cascata também é útil, em qualquer caso, você precisa alterar seu ID. Também concordo com os outros que essa mudança não deve ser tão típica. Por exemplo, no caso de você citar, acho que em grandes volumes de dados, talvez relacionar chaves estrangeiras usando campos de texto possa não resultar no desempenho mais rápido do mecanismo de banco de dados. Observe que, se a relação estrangeira na mesa de concerto usa club.SERIAL e a banda.SERIAL, as alterações no nome não afetam a relação entre as tabelas. No entanto, acho que ON UPDATE CASCADE é uma ótima ferramenta para solucionar emergências. Atenciosamente
David L
4
Este é um design questionável que contribui para um exemplo bastante artificial. Qual é o ponto de manter duas SERIALcolunas clube bandcomo chaves primárias, se você faz referência names em vez de chave primária de cada tabela?
sm
Em resumo, isso é útil se você estiver duplicando o campo de outra tabela e precisar que ele esteja atualizado.
Kamil Tomšík 7/08
4

Meu comentário se refere principalmente ao ponto 3: sob que circunstâncias o ON UPDATE CASCADE é aplicável se estivermos assumindo que a chave pai não é atualizável? Aqui está um caso.

Estou lidando com um cenário de replicação no qual vários bancos de dados de satélite precisam ser mesclados com um mestre. Cada satélite está gerando dados nas mesmas tabelas, portanto, a mesclagem das tabelas com o mestre leva a violações da restrição de exclusividade. Estou tentando usar o ON UPDATE CASCADE como parte de uma solução na qual incremento novamente as chaves durante cada mesclagem. ON UPDATE CASCADE deve simplificar esse processo automatizando parte do processo.

ted.strauss
fonte
3

É uma excelente pergunta, eu tive a mesma pergunta ontem. Pensei nesse problema, especificamente PESQUISADO, se existisse algo como "ON UPDATE CASCADE" e, felizmente, os designers do SQL também pensaram nisso. Concordo com Ted.strauss e também comentei o caso de Noran.

Quando eu o usei? Como Ted apontou, quando você está tratando vários bancos de dados ao mesmo tempo, e a modificação em um deles, em uma tabela, tem qualquer tipo de reprodução no que Ted chama de "banco de dados via satélite", não pode ser mantida com o original. ID e, por qualquer motivo, você deve criar um novo, caso não possa atualizar os dados do antigo (por exemplo, devido a permissões ou caso esteja procurando rapidez em um caso tão efêmero que não merece o respeito absoluto e absoluto pelas regras totais de normalização, simplesmente porque será uma utilidade de vida muito curta)

Então, eu concordo em dois pontos:

(A.) Sim, muitas vezes um design melhor pode evitá-lo; MAS

(B.) Nos casos de migrações, replicação de bancos de dados ou solução de emergências, é uma GRANDE FERRAMENTA que felizmente estava lá quando fui pesquisar se existia.

David L
fonte