SQL-服务器触发器为已删除的行字段值返回空值
SQL-Server Trigger Returning Null Values For DELETED Row Field Values
我 运行 遇到一个问题,我需要先将记录的副本保存到 "History" table 中,然后再保存更新记录的原始字段值更新。
我正在使用触发器来执行此操作。触发器 INSERTED 值应包含更新后的行字段值,DELETED 应显示更新前的字段值。
但是,每当示例触发器代码运行时,SELECT 的 return 对于 ArticleID、Title、StepContent 和 SortOrder 参数总是 return 为 null。但是,如果我要更改从 DELETED 拉取到从 INSERTED 拉取的代码行,它就可以正常工作。
ALTER TRIGGER [dbo].[TRG_SaveHistory]
ON [dbo].[ArticleStep]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SortOrder INT,
@ArticleID INT,
@ArticleHistoryID INT,
@Title varchar(max),
@StepContent varchar(max);
--SELECT @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM INSERTED;
SELECT TOP (1) @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM DELETED WHERE @SortOrder != null;
SELECT TOP (1) @ArticleHistoryID = ID FROM dbo.ArticleHistory WHERE OriginalArticleID = @ArticleID ORDER BY ID DESC;
IF @SortOrder IS NOT Null AND @ArticleHistoryID IS NOT NULL
INSERT INTO [dbo].[ArticleStepHistory]
([ArticleHistoryID]
,[SortOrder]
,[Title]
,[StepContent])
VALUES
(@ArticleHistoryID
,@SortOrder
,@Title
,@StepContent);
END
当我改变这个时有效:
SELECT @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM DELETED;
为此:
SELECT @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM INSERTED;
这是我的更新查询运行:
UPDATE [dbo].[ArticleStep] SET [ArticleID] = 2 ,[SortOrder] = 3,[StepContent] = 'Changed Text' WHERE ID = 1
所以这里是对你的触发器可能是什么样子的疯狂猜测:
alter trigger dbo.TRG_SaveHistory
on dbo.ArticleStep after update
as
begin
set nocount on;
if not exists (select * from deleted)
return;
with cte as (
select max(ID) as HistoryID, OriginalArticleID
from dbo.ArticleHistory
group by OriginalArticleID)
insert dbo.ArticleStepHistory (ArticleHistoryID, SortOrder, Title, StepContent)
select cte.HistoryID, deleted.SortOrder, deleted.Title, deleted.StepContent
from deleted inner join cte
on deleted.ArticleID = cte.OriginalArticleID;
end;
完全是猜测。您可能需要针对较小的语法错误对其进行调整,因为我没有您的数据库并使用记事本编写了它。如果您正在编写 tsql 代码,您应该能够(并且应该能够)纠正小错误。
重要的是要了解 ArticleStep 的主键、您的历史记录的主键和外键(即使 FK 未强制执行)table,以及所有这些行应该如何与其关联原始值,也许还有其他 "higher level" 行。您需要从历史 table 中检索 ID 以便向其中添加行,这有点奇怪。这意味着您有(或应该有)一个插入触发器。如果这样做,它可能也会受到相同的 single-row 假设的影响。
但确实没有必要 "look up" 来自历史 table 的 id 以插入更多行。在其他日志记录情况下,我还没有看到这种需求。您应该仔细考虑为什么您认为需要这样做。
标题是 varchar(max)?我也会重新考虑这一点。也许这会推动您找到更好的解决方案。
我 运行 遇到一个问题,我需要先将记录的副本保存到 "History" table 中,然后再保存更新记录的原始字段值更新。
我正在使用触发器来执行此操作。触发器 INSERTED 值应包含更新后的行字段值,DELETED 应显示更新前的字段值。
但是,每当示例触发器代码运行时,SELECT 的 return 对于 ArticleID、Title、StepContent 和 SortOrder 参数总是 return 为 null。但是,如果我要更改从 DELETED 拉取到从 INSERTED 拉取的代码行,它就可以正常工作。
ALTER TRIGGER [dbo].[TRG_SaveHistory]
ON [dbo].[ArticleStep]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SortOrder INT,
@ArticleID INT,
@ArticleHistoryID INT,
@Title varchar(max),
@StepContent varchar(max);
--SELECT @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM INSERTED;
SELECT TOP (1) @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM DELETED WHERE @SortOrder != null;
SELECT TOP (1) @ArticleHistoryID = ID FROM dbo.ArticleHistory WHERE OriginalArticleID = @ArticleID ORDER BY ID DESC;
IF @SortOrder IS NOT Null AND @ArticleHistoryID IS NOT NULL
INSERT INTO [dbo].[ArticleStepHistory]
([ArticleHistoryID]
,[SortOrder]
,[Title]
,[StepContent])
VALUES
(@ArticleHistoryID
,@SortOrder
,@Title
,@StepContent);
END
当我改变这个时有效:
SELECT @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM DELETED;
为此:
SELECT @SortOrder = SortOrder, @Title = Title, @StepContent = StepContent, @ArticleID = ArticleID FROM INSERTED;
这是我的更新查询运行:
UPDATE [dbo].[ArticleStep] SET [ArticleID] = 2 ,[SortOrder] = 3,[StepContent] = 'Changed Text' WHERE ID = 1
所以这里是对你的触发器可能是什么样子的疯狂猜测:
alter trigger dbo.TRG_SaveHistory
on dbo.ArticleStep after update
as
begin
set nocount on;
if not exists (select * from deleted)
return;
with cte as (
select max(ID) as HistoryID, OriginalArticleID
from dbo.ArticleHistory
group by OriginalArticleID)
insert dbo.ArticleStepHistory (ArticleHistoryID, SortOrder, Title, StepContent)
select cte.HistoryID, deleted.SortOrder, deleted.Title, deleted.StepContent
from deleted inner join cte
on deleted.ArticleID = cte.OriginalArticleID;
end;
完全是猜测。您可能需要针对较小的语法错误对其进行调整,因为我没有您的数据库并使用记事本编写了它。如果您正在编写 tsql 代码,您应该能够(并且应该能够)纠正小错误。
重要的是要了解 ArticleStep 的主键、您的历史记录的主键和外键(即使 FK 未强制执行)table,以及所有这些行应该如何与其关联原始值,也许还有其他 "higher level" 行。您需要从历史 table 中检索 ID 以便向其中添加行,这有点奇怪。这意味着您有(或应该有)一个插入触发器。如果这样做,它可能也会受到相同的 single-row 假设的影响。
但确实没有必要 "look up" 来自历史 table 的 id 以插入更多行。在其他日志记录情况下,我还没有看到这种需求。您应该仔细考虑为什么您认为需要这样做。
标题是 varchar(max)?我也会重新考虑这一点。也许这会推动您找到更好的解决方案。