Trigger to updated default properties result in nesting level of 32 [duplicate]
![Trigger to updated default properties result in nesting level of 32 [duplicate]](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2F80wy3gkl%2Fproduction%2F54e30bbcb677f725db7afda2ea2f51db97c37e46-1201x631.png%3Fh%3D1000&w=3840&q=75)
I have SQL Server which is linked to MS Access through a DSN link:
Where SQL Server works as the developer back-end and MS Access works as the user front-end.
In the table "Components", I have two columns which are supposed to be system generated:
- UpdatedAt: GETDATE()
- UpdatedBy: SUSER_SNAME()
The are default filled out by the following constraints:
ALTER TABLE [dbo].[Components] ADD CONSTRAINT [DF_Components_UpdatedAt] DEFAULT (getdate()) FOR [UpdatedAt]
ALTER TABLE [dbo].[Components] ADD CONSTRAINT [DF_Components_UpdatedBy] DEFAULT (SUSER_SNAME()) FOR [UpdatedBy]
Both of these works as intended.
But now I have some trouble configurating the trigger, which will update "UpdatedAt", "UpdatedBy" after a row/record are updated.
So far I have the Trigger showed below. However in MS access I have several cases of Me.Refresh
in a form (primarily used to update the row/record, when a column included in a computed column are updated, such that the computed column are evaluated right away. Apparently the trigger combined with Me.Refresh
results in an 'endless' loop of them triggering each other and them selves, until SQL Server reaches nesting level of 32:
CREATE TRIGGER [dbo].[TR_Components_UpdateDefaultProperties]
ON [dbo].[Components]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.[Components]
SET UpdatedAt = GETDATE(),
UpdatedBy = SUSER_SNAME()
FROM inserted i
WHERE dbo.[Components].ComponentNumber = i.ComponentNumber;
END;
I found a lot of related questions and great answers here on Stackoverflow which has helped me to this point, but haven't yet found one solving my specific problem.
What could be a work around to avoid the loop of nesting?
The ComputedColumn looks like this:
[ComputedColumn] AS (CONVERT([varchar](1),[Prefix])+CONVERT([varchar](3),[SequenceNumber])) PERSISTED
And here is the VB in MS Access
Private Sub UpdateComputedColumn()
If Not IsNull(Me.Prefix) And Not IsNull(Me.SequenceNumber) Then
Me.Refresh
End If
End Sub
Private Sub Prefix_AfterUpdate()
Call UpdateComputedColumn
End Sub
Private Sub SequenceNumber_AfterUpdate()
Call UpdateComputedColumn
End Sub
Answer
Your trigger updates the table that the trigger is on, and then updates it again, and again... and again i.e. your trigger has an infinite recursion loop because each time it updates it fires the trigger again. You have to find a way to identify that the system update has happened and bail without repeating.
Give these are system generated columns I would suggest using the UPDATE
function to detect this by adding if update(UpdatedAt) return;
at the top of the trigger i.e. if the UpdatedAt
column was updated, it means it was the trigger, so you don't want to run again.
CREATE TRIGGER [dbo].[TR_Components_UpdateDefaultProperties]
ON [dbo].[Components]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
-- Prevent recursion
IF UPDATE(UpdatedAt) RETURN;
UPDATE dbo.[Components]
SET UpdatedAt = GETDATE(),
UpdatedBy = SUSER_SNAME()
FROM inserted i
WHERE dbo.[Components].ComponentNumber = i.ComponentNumber;
END;
Enjoyed this article?
Check out more content on our blog or follow us on social media.
Browse more articles