微软 SQL。级联删除和触发器
Posted
技术标签:
【中文标题】微软 SQL。级联删除和触发器【英文标题】:MS SQL. Cascade Delete and triggers 【发布时间】:2015-11-26 08:57:07 【问题描述】:小问题:“当我使用级联删除 DeliveryHeader 时,DeliveryLine 上没有触发触发器”
详情:
我有一张桌子
CREATE TABLE [dbo].[DeliveryHeader](
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_DeliveryHeader] PRIMARY KEY CLUSTERED
([Id] ASC)
);
CREATE TABLE [dbo].[DeliveryLine](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DeliveryHeaderId] [int] NOT NULL,
CONSTRAINT [PK_DeliveryLine] PRIMARY KEY CLUSTERED
( [Id] ASC )
);
外键级联删除:
ALTER TABLE [dbo].[DeliveryLine] WITH CHECK ADD CONSTRAINT [FK_DeliveryLine_DeliveryHeader] FOREIGN KEY([DeliveryHeaderId])
REFERENCES [dbo].[DeliveryHeader] ([Id])
ON DELETE CASCADE;
我在 DeliveryLine 上有一个触发器
CREATE TRIGGER [dbo].[trg_DeliveryLine_DeleteLog]
ON [dbo].[DeliveryLine]
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
-- some code
END
但是当我删除 DeliveryHeader 时,DeliveryLine 上的触发器没有触发
DELETE FROM [dbo].[DeliveryHeader];
有什么方法可以通过级联删除触发触发器吗?我只知道迂回的方式:
-
从外键中删除级联。
更新:
编写另一个触发器:
CREATE TRIGGER [dbo].[trg_DeliveryHeader_DeleteLog]
ON [dbo].[DeliveryHeader]
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM [dbo].[DeliveryLine] WHERE [DeliveryHeaderId] IN (SELECT Id from deleted)
DELETE FROM [dbo].[DeliveryHeader] WHERE [Id] IN (SELECT Id from deleted)
END
【问题讨论】:
我真的相信级联删除是邪恶的。另一种方法是创建一个过程来删除您想要的内容,并在其中明确说明您要删除的内容。 是的,我知道。我使用它非常罕见。一个很仔细。 【参考方案1】:IF OBJECT_ID('dbo.[DeliveryLine]', 'U') IS NOT NULL
DROP TABLE dbo.[DeliveryLine]
GO
IF OBJECT_ID('dbo.[DeliveryHeader]', 'U') IS NOT NULL
DROP TABLE dbo.[DeliveryHeader]
GO
CREATE TABLE dbo.DeliveryHeader (
Id INT /*IDENTITY(1,1)*/ PRIMARY KEY
)
GO
CREATE TABLE dbo.DeliveryLine (
Id INT IDENTITY(1,1) PRIMARY KEY,
DeliveryHeaderId INT NOT NULL
)
ALTER TABLE dbo.DeliveryLine WITH CHECK
ADD CONSTRAINT FK_DeliveryLine_DeliveryHeader FOREIGN KEY(DeliveryHeaderId)
REFERENCES dbo.DeliveryHeader(Id)
ON DELETE CASCADE
GO
CREATE TRIGGER [dbo].[trg_DeliveryLine_DeleteLog]
ON [dbo].[DeliveryLine]
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
PRINT 'all works!!!'
END
GO
INSERT INTO dbo.DeliveryHeader (Id) VALUES (0)
INSERT INTO dbo.DeliveryLine (DeliveryHeaderId) VALUES (0)
GO
DELETE FROM dbo.DeliveryHeader WHERE Id = 0 -- trigger fire only when data exists in both tables
INSERT INTO dbo.DeliveryHeader (Id) VALUES (1) -- trigger not fire
DELETE FROM dbo.DeliveryHeader WHERE Id = 1
【讨论】:
然后呢?不能加两个字吗? 正确。对不起,我没有真正的数据。这就是为什么没有工作 @Giorgi Nakeuri,我更喜欢简洁地回答:) @Devart,我更喜欢阅读 OP 的代码有什么问题。您可以只说“嘿,OP,它应该可以工作,检查您的数据”,而不是从问题中逐字复制粘贴代码并将其作为答案。抱歉,我不赞成。以上是关于微软 SQL。级联删除和触发器的主要内容,如果未能解决你的问题,请参考以下文章