Como usar RESTRICT para chave estrangeira no mysql?

11

Na estrutura do banco de dados de

  CREATE TABLE Country (
  name varchar(40) NOT NULL,
  PRIMARY KEY  (name)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE City (
  name varchar(40) NOT NULL,
  PRIMARY KEY  (name)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE Map (
  country varchar(40) NOT NULL,
  city varchar(100) NOT NULL,
  PRIMARY KEY  (country,city),
  FOREIGN KEY (country) REFERENCES Country (name) ON DELETE CASCADE,
  FOREIGN KEY (city) REFERENCES City (name) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Espero excluir o pai Citydeixando o valor correspondente no filho intacto por esses três comandos iguais

  FOREIGN KEY (city) REFERENCES City (name) ON DELETE NO ACTION
  FOREIGN KEY (city) REFERENCES City (name) ON DELETE RESTRICT
  FOREIGN KEY (city) REFERENCES City (name)

Mas ao usar NO ACTIONOU RESTRICTou omitir ON DELETE. O MySQL não me permite excluir da coluna pai com este erro:

ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails 
('test'.'Map', CONSTRAINT 'Map_ibfk_2' FOREIGN KEY ('city') REFERENCES 'City'('name')
 ON DELETE RESTRICT

Onde eu estou errado? Não é responsabilidade do SQL NO ACTIONexcluir o pai e deixar o filho órfão?

Googlebot
fonte

Respostas:

13

De acordo com a documentação do MySQL sobre DELETE RESTRICT

• RESTRITO: Rejeita a operação de exclusão ou atualização da tabela pai. Especificar RESTRICT (ou NO ACTION) é o mesmo que omitir a cláusula ON DELETE ou ON UPDATE.

Quanto a SEM AÇÃO

• SEM AÇÃO: Uma palavra-chave do SQL padrão. No MySQL, equivalente a RESTRICT. O InnoDB 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, as restrições de chave estrangeira são verificadas imediatamente, então NO ACTION é o mesmo que RESTRICT.

DELETE RESTRICT protege os pais da exclusão, não os filhos.

RolandoMySQLDBA
fonte
5

Se você deseja excluir o pai e deixar o filho, provavelmente está desejando a ON DELETE SET NULLopção:

SET NULL: exclua ou atualize a linha da tabela pai e defina a coluna ou colunas da chave estrangeira na tabela filha como NULL. As cláusulas ON DELETE SET NULL e ON UPDATE SET NULL são suportadas.

Se você especificar uma ação SET NULL, certifique-se de não ter declarado as colunas na tabela filha como NOT NULL.

Há muito "não" nessa última frase, portanto, verifique se o parent_id pode ser NULL.

Veja também esta pergunta relacionada: Qual é o objetivo de SET NULL em excluir / atualizar restrições de chaves estrangeiras?

Ao definir uma chave estrangeira, você disse ao banco de dados para não aceitar entradas na tabela filho que não possuem um valor correspondente no pai.

Derek Downey
fonte