CodeGym /Cursos /SQL SELF /Usando ON DELETE CASCADE e ON UPDATE...

Usando ON DELETE CASCADE e ON UPDATE RESTRICT

SQL SELF
Nível 19 , Lição 2
Disponível

Imagina que você criou um banco de dados com uma tabela de clientes (customers) e outra de pedidos (orders) relacionada a ela. Só que aí bate a dúvida: o que fazer se um cliente for removido da tabela customers? Os pedidos desse cliente também devem ser apagados ou vão ficar "órfãos", apontando pra um cliente que nem existe mais? E se você quiser mudar o ID do cliente? É aí que entram as operações em cascata (CASCADE) e as restrições (RESTRICT) pra controlar o comportamento do banco.

ON DELETE CASCADE é um esquema que apaga automaticamente os registros relacionados quando você deleta um registro da tabela principal. Ou seja, se você deletar um cliente, todos os pedidos ligados a ele também vão embora.

Funciona assim: quando você coloca ON DELETE CASCADE na definição da foreign key, o banco "saca" que o registro relacionado tem que ser apagado junto.

Exemplo

Vamos supor que temos duas tabelas: customers e orders. Os clientes (customers) podem fazer vários pedidos (orders), ou seja, é uma relação ONE-TO-MANY. Queremos que, quando um cliente for deletado, todos os pedidos dele também sejam apagados.

-- Criando a tabela de clientes
CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

-- Criando a tabela de pedidos com foreign key apontando pra tabela de clientes
CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE,
    order_date DATE NOT NULL
);

Inserindo dados nas tabelas

-- Inserindo dados na tabela de clientes
INSERT INTO customers (name) VALUES ('Ivan'), ('Anna');

-- Inserindo dados na tabela de pedidos
INSERT INTO orders (customer_id, order_date) VALUES
(1, '2023-10-01'),
(1, '2023-10-02'),
(2, '2023-10-03');

Tabela orders:

order_id customer_id order_date
1 1 2023-10-01
2 1 2023-10-02
3 2 2023-10-03

Deletando um cliente e vendo o que rola

-- Deletando o cliente com ID 1
DELETE FROM customers WHERE customer_id = 1;

-- Conferindo o que sobrou na tabela de pedidos
SELECT * FROM orders;
order_id customer_id order_date
3 2 2023-10-03

Como dá pra ver, os pedidos ligados ao cliente deletado também foram apagados.

Restringindo alterações: ON UPDATE RESTRICT

ON UPDATE RESTRICT serve pra impedir que você altere um valor na tabela principal se tiver registro na tabela filha apontando pra ele. É tipo um "escudo" que barra mudanças que podem bagunçar a integridade dos dados.

Como funciona? Quando você coloca ON UPDATE RESTRICT, o banco não deixa atualizar a chave na tabela principal se ela estiver sendo usada na tabela filha.

Exemplo

Vamos usar as mesmas tabelas customers e orders, mas agora vamos colocar a restrição de update na foreign key.

-- Recriando a tabela de pedidos com restrição de update
DROP TABLE orders;

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id) ON UPDATE RESTRICT,
    order_date DATE NOT NULL
);

Tentando atualizar o ID do cliente

-- Tentando mudar o ID do cliente de 2 pra 5
UPDATE customers 
SET customer_id = 5 
WHERE customer_id = 2;

Resultado:

ERROR:  update or delete on table "customers" violates foreign key constraint
DETAIL:  Key (customer_id)=(2) is still referenced from table "orders".

Como você viu, o banco deu erro porque mudar a chave ia quebrar a ligação entre as tabelas.

Mais detalhes sobre UPDATE e suas tretas eu conto no próximo nível :P

Juntando ON DELETE CASCADE e ON UPDATE RESTRICT

Claro que dá pra misturar operações em cascata (CASCADE) e restrições (RESTRICT). Por exemplo, você pode configurar pra apagar automaticamente os dados relacionados quando deletar o registro principal (ON DELETE CASCADE), mas bloquear a alteração do ID dele (ON UPDATE RESTRICT) pra evitar confusão.

Exemplo

Vamos criar de novo a tabela de pedidos, agora usando os dois esquemas:

DROP TABLE orders;

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)
        ON DELETE CASCADE
        ON UPDATE RESTRICT,
    order_date DATE NOT NULL
);

Agora:

  • Se você deletar um cliente, todos os pedidos dele vão ser apagados.
  • Se tentar mudar o ID do cliente, vai tomar erro.

Por que isso é importante na vida real?

Usar CASCADE e RESTRICT é muito importante em sistemas grandes com várias tabelas relacionadas. Por exemplo:

Num e-commerce, o cliente pode ter pedidos. Se o cliente quiser deletar o perfil, você não vai querer deixar pedidos na base que não apontam pra ninguém. É aí que ON DELETE CASCADE salva o rolê.

Ao mesmo tempo, você pode querer evitar mudanças acidentais em chaves únicas pra não quebrar as relações entre as tabelas. Pra isso, ON UPDATE RESTRICT é perfeito.

2
Tarefa
SQL SELF, nível 19, lição 2
Bloqueado
Criação de tabelas com `ON DELETE CASCADE`
Criação de tabelas com `ON DELETE CASCADE`
2
Tarefa
SQL SELF, nível 19, lição 2
Bloqueado
Adicionando a restrição `ON UPDATE RESTRICT`
Adicionando a restrição `ON UPDATE RESTRICT`
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION