不同数据库中两个表之间的引用完整性的存储过程?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不同数据库中两个表之间的引用完整性的存储过程?相关的知识,希望对你有一定的参考价值。

对于两个表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;

如果存储过程不是最佳实践,那么最佳实践是什么?在我看来,有很多样板代码,只有数据库名称和表名是变量。

答案

(第一个)触发器中的逻辑不正确。如果你在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

以上是关于不同数据库中两个表之间的引用完整性的存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

存储过程与触发器的区别

数据库知识

数据库及表的创建

存储过程

触发器

如何避免这两个 SQL 语句之间出现死锁?