SQL Server 2022边缘表INSTEAD OF DELETE触发器报错咨询
SQL Server 2022边缘表INSTEAD OF DELETE触发器报错问题
我在SQL Server 2022数据库中定义了如下AFTER DELETE触发器,可正常构建并运行:
CREATE OR ALTER TRIGGER After_Assignment_Delete ON dbo.[Assigned_To] AFTER DELETE AS BEGIN INSERT INTO dbo.[UpdateManifest]([DatabaseId], [UserId]) SELECT db.[Id], u.[Id] FROM deleted a INNER JOIN [User] u ON a.$from_id = u.$node_id OUTER APPLY [dbo].[GetAssignedDatabases](u.[Id]) db END
但将其修改为INSTEAD OF DELETE触发器时,出现错误提示:
Invalid column name '$from_id'
对应的INSTEAD OF触发器代码如下:
CREATE OR ALTER TRIGGER After_Assignment_Delete ON dbo.[Assigned_To] INSTEAD OF DELETE AS BEGIN INSERT INTO dbo.[UpdateManifest]([DatabaseId], [UserId]) SELECT db.[Id], u.[Id] FROM deleted a INNER JOIN [User] u ON a.$from_id = u.$node_id OUTER APPLY [dbo].[GetAssignedDatabases](u.[Id]) db END
请问边缘表是否不支持INSTEAD OF触发器?
边缘表支持INSTEAD OF触发器,你遇到的错误源于SQL Server对两种触发器的deleted虚拟表处理逻辑差异:
- AFTER DELETE触发器的
deleted表包含边缘表的所有列,包括系统自动维护的$from_id、$to_id、$edge_id等系统列。 - INSTEAD OF DELETE触发器的
deleted表仅包含边缘表中你自定义的列,不会包含这些系统生成列,因此会触发$from_id列不存在的错误。
要解决这个问题,你需要在INSTEAD OF触发器中手动处理删除操作,并通过OUTPUT子句捕获所需的系统列值,示例代码如下:
CREATE OR ALTER TRIGGER Instead_Assignment_Delete ON dbo.[Assigned_To] INSTEAD OF DELETE AS BEGIN -- 定义临时表存储删除的边表$from_id DECLARE @DeletedEdges TABLE (FromId NVARCHAR(128)); -- 请根据$from_id实际数据类型调整 -- 执行删除操作并捕获$from_id,通过自定义列匹配待删除行 DELETE FROM dbo.[Assigned_To] OUTPUT DELETED.$from_id INTO @DeletedEdges(FromId) WHERE [自定义唯一列] IN (SELECT [自定义唯一列] FROM deleted); -- 用捕获的$from_id完成后续插入逻辑 INSERT INTO dbo.[UpdateManifest]([DatabaseId], [UserId]) SELECT db.[Id], u.[Id] FROM @DeletedEdges de INNER JOIN [User] u ON de.FromId = u.$node_id OUTER APPLY [dbo].[GetAssignedDatabases](u.[Id]) db END
如果你的边缘表没有自定义列,无法通过自定义列匹配待删除行,建议添加用于标识的自定义业务列,或者根据实际业务逻辑调整触发器的匹配方式。
内容的提问来源于stack exchange,提问作者Chris Gonzales
相关产品推荐
相关产品推荐

