我試圖利用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