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

时间:2018-02-28 02:08:10

标签: sql sql-server stored-procedures

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

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

1 个答案:

答案 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