我试图利用SQL Server 2008R MERGE功能来管理连接表中的父子关系记录。我可以创建一个虚拟INSTEAD OF UPDATE,INSERT触发器,以便我可以使用MERGE和INSTEAD OF DELETE?
连接表表示多对多关系,所以它有两个用于相同主键的外键。因此,不能使用ON DELETE CASCADE
。在这里,我使用了触发器INSTEAD OF DELETE
并删除了连接记录,因此删除了约束条件,因此我可以完成最初预期的删除操作。
不幸的是,当我尝试在这种情况下使用MERGE时,出现以下错误。
The target 'Content' of the MERGE statement has an INSTEAD OF trigger on some,
but not all, of the actions specified in the MERGE statement. In a MERGE statement,
if any action has an enabled INSTEAD OF trigger on the target, then all actions
must have enabled INSTEAD OF triggers.
下面是用于重现此问题的T-SQL。为了方便起见,我添加了注释掉和选择语句。
CREATE DATABASE [TestDatabase]
GO
USE [TestDatabase]
GO
CREATE TABLE dbo.[Content] (
ContentID int NOT NULL IDENTITY (1, 1),
Title varchar(255)
)
ALTER TABLE dbo.[Content]
ADD CONSTRAINT PK_Content
PRIMARY KEY CLUSTERED (ContentID)
CREATE TABLE dbo.[Attachment] (
ParentContentID int NOT NULL,
ChildContentID int NOT NULL
)
ALTER TABLE [dbo].[Attachment]
ADD CONSTRAINT [PK_Attachment]
PRIMARY KEY CLUSTERED (
[ParentContentID] ASC,
[ChildContentID] ASC
)
ALTER TABLE dbo.Attachment
ADD CONSTRAINT FK_Attachment_ParentContent
FOREIGN KEY (ParentContentID)
REFERENCES dbo.[Content] (ContentID)
ON UPDATE NO ACTION
ON DELETE NO ACTION
ALTER TABLE dbo.Attachment
ADD CONSTRAINT FK_Attachment_ChildContent
FOREIGN KEY (ChildContentID)
REFERENCES dbo.[Content] (ContentID)
ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
CREATE TRIGGER trContentInsteadOfDelete
ON dbo.[Content]
INSTEAD OF DELETE
AS
SET NOCOUNT ON;
DELETE FROM dbo.[Attachment]
WHERE [ParentContentID] IN (SELECT [ContentID] FROM deleted)
OR [ChildContentID] IN (SELECT [ContentID] FROM deleted)
DELETE FROM dbo.[Content]
WHERE [ContentID] IN (SELECT [ContentID] FROM deleted)
GO
INSERT INTO [Content] ([Title]) VALUES ('a'), ('a'), ('a'), ('b')
GO
INSERT INTO [Attachment] ([ParentContentID], [ChildContentID])
VALUES (1, 2), (1, 4), (3, 4)
GO
MERGE [Content] AS target
USING (VALUES (1, 'a'), (2, 'b'), (NULL, 'b')) AS source ([ContentID], [Title])
ON target.[ContentID] = source.[ContentID]
WHEN MATCHED AND target.[Title] != source.[Title] THEN
UPDATE SET target.[Title] = source.[Title]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([Title]) VALUES (source.[Title])
WHEN NOT MATCHED BY source THEN
DELETE;
/*
USE master
DROP DATABASE [TestDatabase]
SELECT * FROM [Content]
SELECT * FROM [Attachment]
*/;
是否有任何替代品添加触发器
INSTEAD OF INSERT
和
INSTEAD OF UPDATE
,而不必从内容表中删除记录之前明确地删除附件表中的任何约束的记录?
我可以暂时禁用触发器,但是我必须显式删除附件表中的约束记录。
我担心添加额外的触发器只是为了适应MERGE语句而失败了使用MERGE语句的目的。
更新:有没有办法创建一个虚拟INSTEAD的插入,更新触发器,使我能够继续使用合并?
我“不能确定你期望在这里有什么答案:错误是明确和要求[记录](http://msdn.microsoft.com/en-us/library/bb510625(V = SQL .105).aspx)所以最好的你可以希望是一个解决方法,比如创建虚拟触发器,它什么都不做。 – Pondlife
@Pondlife,我宁愿保留使用MERGE的能力,并找到更好的方法来清理孤儿连接记录在附件表中,我希望有人有更好的方法来达到我在上面的代码中说明的相同结果,谢谢你的评论。 – Kuyenda