#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 сделает всю работу за вас.