In the answers on this case
it was suggested that I should not use cursor because of performance reasons. What are the best practices to loop over the update data in an update trigger ?
UPDATE:
The following is the TSQL for the creation of that update trigger.
CREATE TRIGGER [dbo].[trAfterUpdateInfoDoc]
ON [dbo].[InfoDocs]
AFTER UPDATE
AS
BEGIN
DECLARE @infodoctemplateid INT;
DECLARE @infodocid INT;
DECLARE @requireccount FLOAT(2);
DECLARE @filledcount FLOAT(2);
DECLARE @pcnt FLOAT(2);
DECLARE c CURSOR FOR
SELECT id
FROM InfoDocs ifd
WHERE exists (SELECT 1 FROM Inserted AS i WHERE i.id = ifd.id)
OPEN c
FETCH NEXT FROM c INTO @infodocid
WHILE @@Fetch_Status = 0
BEGIN
SELECT @infodoctemplateid = InfoDocTemplateId
FROM InfoDocs
WHERE id = @infodocid;
SELECT @requireccount = COUNT(*)
FROM InfoDocTemplateFields
WHERE InfoDocTemplateId = @infodoctemplateid
AND IsRequired = 1;
IF (@requireccount = 0)
BEGIN
set @pcnt = 100;
END
ELSE
BEGIN
select @filledcount = count(*) from InfoDocFields
where InfoDocId = @infodocid
and InfoDocTemplateFieldId in (select id from InfoDocTemplateFields where InfoDocTemplateId = @infodoctemplateid and IsRequired = 1)
and (BooleanValue is not null or (StringValue is not null and StringValue <> '') or IntValue is not null or DateValue is not null)
set @pcnt = @filledcount / @requireccount * 100.0;
END
update InfoDocs set PercentageCompleted = @pcnt Where id = @infodocid;
Fetch next From c into @infodocid
End
Close c
Deallocate c
END
I've tried translating your cursor into a set based code, however there is no way for me to test if my solution is correct, and I didn't get much sleep last night so I might have missed some things here and there - and it probably can be a shorter and more efficient code than what I've written, but it should give you a good place to start:
You can get rid of the cursor by doing an update with a join.
E.g.
This will get you the best possible performance. And the code will be more compact and easier to understand.