не понимаю, как работает триггер

#sql #sql-server #ssms

#sql #sql-сервер #ssms

Вопрос:

Триггер должен реагировать на удаление строки из таблицы поставщиков, если в таблице есть какие-то поставки от этого поставщика, триггер должен отменить удаление. Этот код позволяет удалять как поставщиков с поставками, так и поставщиков без поставок:

 CREATE TRIGGER SuppliersDeleteCondition
ON Suppliers
FOR DELETE
AS
IF EXISTS (
           SELECT 1
             FROM Supplies Ses
             JOIN DELETED D
               ON D.SupplierID=Ses.SupplierID
          )
BEGIN
  RAISERROR ('This supplier has some supplies', 16, 1)
  ROLLBACK TRANSACTION
END;
 

Приблизительный вид таблиц:

Поставщики (SupplierID, имя, адрес, банковские реквизиты), Расходные материалы (SupplyID, SupplierID, ProductID, ImplementationPeriod, Вес, Цена)

Вот СОЗДАТЬ ТАБЛИЦУ:

 CREATE TABLE Suppliers
        (
         SupplierID INT IDENTITY,
         Name VARCHAR(150) NOT NULL UNIQUE,
         Address VARCHAR(900) NOT NULL,
         BankDetails VARCHAR(9) NOT NULL UNIQUE,

         CONSTRAINT pk_SupplierID PRIMARY KEY (SupplierID),
         CONSTRAINT chk_Name_Suppliers CHECK (NOT Name LIKE '%[^a-z ]%' AND NOT Name LIKE '[ ]%' AND NOT Name LIKE '%[ ]' AND NOT Name LIKE '%[ ][ ]%'),
         CONSTRAINT chk_Address_Suppliers CHECK (NOT Address LIKE '%[^a-zA-z0-9,./ ]%' AND NOT Address LIKE '[ ]%'),
         CONSTRAINT chk_BankDetails_Suppliers CHECK (BankDetails LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
        );
CREATE TABLE Supplies
        (
         SupplyID INT IDENTITY,
         SupplierID INT,
         ProductID INT,
         ImplementationPeriod DATE NOT NULL,
         Weight REAL NOT NULL,
         Price MONEY NOT NULL,

         CONSTRAINT pk_SupplyID PRIMARY KEY (SupplyID),
         CONSTRAINT fk_SupplierID FOREIGN KEY (SupplierID) REFERENCES Suppliers(SupplierID) ON DELETE CASCADE,
         CONSTRAINT fk_ProductID FOREIGN KEY (ProductID) REFERENCES Products(ProductID) ON DELETE CASCADE,
         CONSTRAINT chk_Weight_Supplies CHECK (Weight > 0)
        );
 

Когда я удаляю строку следующим образом:

 DELETE FROM Suppliers WHERE SupplierID=18
 

эта строка удалена, и я не получил ошибки

Комментарии:

1. Для предотвращения удаления следует использовать ограничение внешнего ключа, а не триггер.

2. Я знаю, что лучше использовать FK, но можно ли использовать триггер?

3. @salkcid, да, можно использовать триггеры для обеспечения ссылочной целостности, поскольку это был единственный способ сделать это до того, как 20 лет назад в SQL Server были введены ограничения RI. Опубликуйте CREATE TABLE и завершите сценарий, который воспроизводит проблему.

4. @DanGuzman Я добавил информацию

Ответ №1:

У вас есть внешний ключ с DELETE CASCADE опцией, поэтому триггер удаления является излишним. AFTER DELETE Триггер сработает после удаления строк от поставщиков и поставок, поэтому никакие строки никогда не будут соответствовать EXISTS предикату. Здесь нет необходимости в триггере, если только вы не можете удалить внешний ключ, чего я бы не рекомендовал. Пусть SQL Server сделает всю работу за вас.