Pergunta

Em MSSQL 2005 Eu só atingiu a mensagem de erro infame:

Apresentando EXTERNA CHAVE restrição XXX em YYY tabela pode causar ciclos ou vários caminhos em cascata. Especificar ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modificar outras restrições FOREIGN KEY.

Agora, StackOverflow tem vários tópicos sobre esta mensagem de erro, então eu já tenho a solução (no meu caso eu vou ter que usar triggers), mas estou curioso para saber porque é que há um problema em tudo .

Pelo que entendi, existem basicamente dois cenários que eles querem evitar - um ciclo e vários caminhos. Um ciclo seria onde duas tabelas têm em cascata chaves estrangeiras para o outro. OK, um ciclo pode se estender por várias mesas também, mas este é o caso básico e será mais fácil de analisar.

Vários caminhos seria quando TableA tem chaves estrangeiras para TableB e TableC e TableB também tem uma chave estrangeira para TableC. Mais uma vez -. Este é o caso básico mínimo

Eu não consigo ver quaisquer problemas que poderiam surgir quando um registro iria ficar excluído ou atualizado em qualquer uma dessas tabelas. Claro, você pode precisar de consultar as mesmas múltiplas mesa vezes para ver quais registros precisam de atualização / apagar, mas é que realmente um problema? É este um problema de desempenho?

Em outros tópicos para que as pessoas ir tão longe quanto a etiqueta utilizando cascatas como " arriscado" e afirmam que " resolver caminhos em cascata é um problema complexo ". Por quê? Onde está o risco? Onde está o problema?

Foi útil?

Solução

Você tem uma tabela filho com 2 caminhos em cascata do mesmo pai:. Um "delete", um "nulo"

O que tem precedência? O que você espera depois? etc

Nota:. Um gatilho é o código e pode adicionar um pouco de inteligência ou condições para uma cascata

Outras dicas

A razão por que proíbem usando delete cascade tem a ver com desempenho e bloqueio. Sim, não é tão ruim quando você excluir um registro, mas mais cedo ou mais tarde você vai precisar excluir um grande grupo de registros e seu banco de dados será chega a um impasse.

Se você está excluindo registros suficientes, SQL Server pode escalar para um bloqueio de tabela e ninguém pode fazer nada com a mesa até que esteja terminado.

Nós recentemente mudou-se um de nossos clientes para o seu próprio servidor. Como parte do negócio também, então tive que apagar todos os registros desse cliente formar o nosso servidor original. Excluindo todas as suas informações em lotes (de modo a não causar problemas com outros usuários) levou um par de meses. Se tivéssemos cascata conjunto de apagar-se, o banco de dados teria sido inacessível para os outros clientes por um longo tempo como milhões de registros foram excluídos em uma transação e centenas de mesas estavam trancadas até que a transação foi feito.

Eu também podia ver um cenário onde um impasse pode ter ocorrido na utilização de exclusão em cascata porque não temos controle sobre o fim do caminho cascata teria tomado e nosso banco de dados é um pouco denormalized com clientid aparecendo na maioria das mesas. Então, se ele trancou a uma tabela que tinha uma chave estrangeira também para uma terceira tabela, bem como a tabela de cliente que estava em um caminho differnt, ele possivelmente não poderia verificar que a tabela, a fim de excluir da terceira tabela, porque isso é tudo uma transação e os bloqueios não seria libertado até que foi feito. Então, possivelmente, não teria vamos configurar exclusões em cascata se ele viu a possibilidade de criar impasses na transação.

Outra razão para evitar exclusões em cascata é que às vezes a existência de um registro filho é motivo suficiente para não excluir o registro pai. Por exemplo, se você tem uma tabela de clientes e que o cliente tem tido ordens no passado, você não deseja excluir dele e perder a informação sobre a ordem real.

Considere uma tabela de funcionários:

CREATE TABLE Employee
(
    EmpID   INTEGER NOT NULL PRIMARY KEY,
    Name    VARCHAR(40) NOT NULL,
    MgrID   INTEGER NOT NULL REFERENCES Employee(EmpID) ON DELETE CASCADE
);

INSERT INTO Employees(     1, "Bill",   1);
INSERT INTO Employees(    23, "Steve",  1);
INSERT INTO Employees(234212, "Helen", 23);

Agora, suponha que se aposenta Bill:

DELETE FROM Employees WHERE Name = "Bill";

Ooooppps; todos acabou demitido!

[ Nós podemos debater se os detalhes da sintaxe estão corretas; o conceito está, eu acho. ]

Eu acho que o problema é que quando você faz um caminho "ON DELETE CASCADE" eo outro "ON DELETE RESTRINGIR", ou "NENHUMA AÇÃO" o resultado (o resultado) é unpredicable. Depende de qual apagar-trigger (este também é um gatilho, mas você não tem que construir a si mesmo) será executado em primeiro lugar.

Eu concordo com isso cascatas ser "arriscado" e deve ser evitado. (Eu pessoalmente prefiro cascata as alterações manualmente em vez que ter sql server automaticamente cuidar deles). Esta é também porque, mesmo se o servidor SQL excluídos milhões de linhas, a saída ainda iria aparecer como

(1 linha (s) afectado)

Eu acho que se deve ou não usar um ON opção DELETE CASCADE é uma questão do modelo de negócio que você está implementando. Uma relação entre dois objectos de visita pode ser ou um simples "associação", em que ambas as extremidades da relação estão relacionados, mas de outra forma objectos independentes do ciclo de vida dos quais são diferentes e controlada por outras lógicas. Há, no entanto, também relacionamentos "agregação", onde um objeto pode realmente ser visto como o "pai" ou "dono" de uma "criança" ou "detalhe" objeto. Existe a noção ainda mais forte de uma relação de "composição", em que um objecto apenas existe na forma de uma composição de um número de peças. No caso "associação", você geralmente não irá declarar uma restrição CASCADE ON DELETE. Para agregações ou composições, no entanto, o CASCADE ON DELETE ajuda a mapear seu modelo de negócios para o banco de dados com mais precisão e de forma declarativa. É por isso que me incomoda que o MS SQL Server restringe o uso de esta opção para um único caminho cascata. Se não estou enganado, muitos outros sistemas de banco de dados SQL amplamente utilizado não impor tais restrições.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top