Удалить триггер вместо ON DELETE CASCADE, чтобы избежать множественных каскадных путей?

Следующее определение таблицы:

   CREATE TABLE Customers( id INT NOT NULL PRIMARY KEY, name [varchar](50) )

    CREATE TABLE Orders ( id INT NOT NULL PRIMARY KEY, 
                          customer INT FOREIGN KEY 
                          REFERENCES Customers(id) ON DELETE CASCADE )

    CREATE TABLE OrderDetails ( id INT NOT NULL PRIMARY KEY, 
                                order INT FOREIGN KEY REFERENCES Orders(id) ON DELETE CASCADE, 
                                customer INT FOREIGN KEY REFERENCES Customers(id) ON DELETE CASCADE  )

невозможно на сервере sql, потому что существует несколько каскадных путей.

Я подумал, давайте создадим OrderDetails без ON DELETE CASCADE в столбце order и посмотрим, можно ли обеспечить ссылочную целостность при удалении заказа с помощью триггера, содержащего:

DELETE FROM OrderDetails
    FROM Deleted d
    INNER JOIN OrderDetails od
    ON od.order = d.id

Триггер срабатывает после удаления в Orders, поэтому это невозможно (оператор DELETE конфликтует с ограничением REFERENCE).

Я считаю, что проблема заключается в дизайне модели, а ссылка из OrderDetails на Customers — это плохой дизайн. Однако в противном случае можно было бы создать OrderDetails для заказов, принадлежащих разным клиентам.

Два вопроса:

  • какой лучший дизайн модели?
  • тем не менее можно ли использовать триггер?

РЕДАКТИРОВАТЬ: я удалил ссылку из OrderDetails на Customers, это не имеет никакого смысла. Это решает все вопросы.


person Gerard    schedule 28.06.2010    source источник


Ответы (2)


Я бы избежал этой проблемы, вообще не помещая Customer в OrderDetails, так как это происходит от присоединения к Orders.

В нынешнем виде даже с внешним ключом ничто не мешает клиенту в OrderDetails отличаться от клиента в Orders.

Кроме того, вы действительно хотите каскадное удаление для этого? Предположительно бизнесу потребуется некоторая запись исторических заказов.

person Martin Smith    schedule 28.06.2010
comment
Я не понял существующего несоответствия - я сразу потерял аппетит к триггерам и изменил дизайн. - person Gerard; 28.06.2010

Конечно, это неправильно и не имеет смысла иметь CustomerId в OrderDetails. Это дало бы вам своего рода транзитивную зависимость.
Кроме того, в зависимости от вашей реальной модели никогда не должно быть разрешено удалять Клиента, если к нему относится какой-либо Заказ. Вам следует планировать либо логическое значение, либо поле даты, например DeadCustomer :/

Для структуры:
Клиенты: идентификатор, имя и т. д.
Заказ: OrderId, OrderDate, CustID...
OrderDetails: OrderId, ProductId, Quant, UnitPrice...
Товары: ProductId, Description , Статус, Цена за единицу...

person Patrick Honorez    schedule 28.06.2010
comment
Ваш ответ имеет смысл. Однако я не пытался удалить Клиента, а Заказ. - person Gerard; 28.06.2010