对于两个表A和B,我希望实现参照完整性,使得在表A中,外键的值必须存在于表B中,而在表B中,主键只能被删除如果表A中没有该值,则进行修改。我的要求是我希望将表A和B作为变量,并将该过程应用于表的任意实例。也就是说,
sp_referential_integrity_across_databases(A, B)
我已经想出如何将引用完整性作为一对特定表的触发器。我想知道编写这样的存储过程是否可行以节省未来的工作量?
我的环境是Microsoft SQL Server 2017.解决方案越便携越好。
以下是我制作的程序:
表格上的触发器" A"插入和更新:
USE DWPractice
IF OBJECT_ID ('dbo.trgCheckCustomer_Cat_Id_Customer_D', 'TR') IS NOT NULL
DROP Trigger trgCheckCustomer_Cat_Id_Customer_D;
GO
CREATE TRIGGER trgCheckCustomer_Cat_Id_Customer_D
ON Customer_D
AFTER INSERT, UPDATE
AS
IF NOT EXISTS
(
SELECT Customer_Cat_Id
FROM inserted
WHERE Customer_Cat_Id IN (SELECT Customer_Cat_Id FROM [OtherDW].[dbo].[Customer_Cat_D])
)
BEGIN
RAISERROR('Lookup Value Not Found -- Inerst Failed', 16, 1);
ROLLBACK TRANSACTION;
END;
表格上的触发器" B"删除和更新:
USE OtherDW
IF OBJECT_ID ('dbo.trgCheckCustomer_Cat_Id_Customer_Cat_D', 'TR') IS NOT NULL
DROP Trigger trgCheckCustomer_Cat_Id_Customer_Cat_D;
GO
CREATE TRIGGER trgCheckCustomer_Cat_Id_Customer_Cat_D
ON Customer_Cat_D
AFTER DELETE, UPDATE
AS
Begin
IF EXISTS
(
SELECT Customer_Cat_Id
FROM deleted
WHERE Customer_Cat_Id IN (SELECT Customer_Cat_Id FROM [DWPractice].[dbo].[Customer_D])
)
BEGIN
RAISERROR('Lookup Value Found -- Delete Failed', 16, 1);
ROLLBACK TRANSACTION;
END;
-- It seems that the following for the case of update is not needed
-- The above clauses would get executed even for the case of update.
-- IF EXISTS
-- (
-- SELECT Customer_Cat_Id
-- FROM inserted
-- WHERE Customer_Cat_Id IN (SELECT Customer_Cat_Id FROM [DWPractice].[dbo].[Customer_D])
-- )
-- BEGIN
-- RAISERROR('Lookup Value Found -- Update Failed', 16, 1);
-- ROLLBACK TRANSACTION;
-- END;
End;
如果存储过程不是最佳实践,那么最佳做法是什么?在我看来,有很多样板代码,只有数据库名称和表名是变量。
答案 0 :(得分:1)
(第一个)触发器中的逻辑不正确。如果inserted
中有多行,则只有一行必须匹配。相反,你想要:
CREATE TRIGGER trgCheckCustomer_Cat_Id_Customer_D ON Customer_D AFTER INSERT, UPDATE
AS BEGIN
IF EXISTS (SELECT 1
FROM inserted i LEFT JOIN
[OtherDW].[dbo].[Customer_Cat_D] d
ON i.Customer_Cat_Id = d.Customer_Cat_Id
WHERE d.Customer_Cat_Id IS NULL
)
BEGIN
RAISERROR('Lookup Value Not Found -- Insert Failed', 16, 1);
ROLLBACK TRANSACTION;
END;
END; -- trigger