Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 156617
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T10:21:32+00:00 2026-05-11T10:21:32+00:00

I am having to use triggers in MSSQL for the first time, well triggers

  • 0

I am having to use triggers in MSSQL for the first time, well triggers in general. Having read around and tested this myself I realise now that a trigger fires per command and not per row inserted, deleted or updated.

The entire thing is some statistics for an advertising system. Our main stat table is rather large and doesn’t contain the data in a way that makes sense in most cases. It contains one row per advert clicked, viewed and etc. As a user one is more inclined to want to view this as day X has Y amount of clicks and Z amount of views and so forth. We have done this purely based on a SQL query so far, getting this sort of report from the main table, but as the table has grown so does the time for that query to execute. Because of this we have opted for using triggers to keep another table updated and hence making this a bit easier on the SQL server.

My issue is now to get this working with multiple records. What I have done is to create 2 stored procedures, one for handling the operation of an insert, and one for a delete. My insert trigger (written to work with a single record) then graps the data off the Inserted table, and sends it off to the stored procedure. The delete trigger works in the same way, and (obviously?) the update trigger does the same as a delete + an insert.

My issue is now how to best do this with multiple records. I have tried using a cursor, but as far as I have been able to read and see myself, this performs really badly. I have considered writing some ‘checks’ as well – as in checking to see IF there are multiple records in the commands and then go with the cursor, and otherwise simply just avoid this. Anyhow, here’s my solution with a cursor, and im wondering if there’s a way of doing this better?

CREATE TRIGGER [dbo].[TR_STAT_INSERT]    ON  [iqdev].[dbo].[Stat]    AFTER INSERT AS  BEGIN     SET NOCOUNT ON;      DECLARE @Date DATE      DECLARE @CampaignId BIGINT     DECLARE @CampaignName varchar(500)     DECLARE @AdvertiserId BIGINT     DECLARE @PublisherId BIGINT     DECLARE @Unique BIT     DECLARE @Approved BIT     DECLARE @PublisherEarning money     DECLARE @AdvertiserCost money     DECLARE @Type smallint      DECLARE InsertCursor CURSOR FOR SELECT Id FROM Inserted     DECLARE @curId bigint      OPEN InsertCursor      FETCH NEXT FROM InsertCursor INTO @curId      WHILE @@FETCH_STATUS = 0     BEGIN          SELECT @Date = [Date], @PublisherId = [PublisherCustomerId], @Approved = [Approved], @Unique = [Unique], @Type = [Type], @AdvertiserCost = AdvertiserCost, @PublisherEarning = PublisherEarning         FROM Inserted         WHERE Id = @curId          SELECT @CampaignId = T1.CampaignId, @CampaignName = T2.Name, @AdvertiserId = T2.CustomerId         FROM Advert AS T1         INNER JOIN Campaign AS T2 on T1.CampaignId = T2.Id         WHERE T1.Id = (SELECT AdvertId FROM Inserted WHERE Id = @curId)          EXEC ProcStatInsertTrigger @Date, @CampaignId, @CampaignName, @AdvertiserId, @PublisherId, @Unique, @Approved, @PublisherEarning, @AdvertiserCost, @Type          FETCH NEXT FROM InsertCursor INTO @curId     END      CLOSE InsertCursor     DEALLOCATE InsertCursor END 

The stored procedure is rather big and intense and I do not think there’s a way of having to avoid looping through the records of the Inserted table in one way or another (ok, maybe there is, but I’d like to be able to read the code too :p), so I’m not gonna bore you with that one (unless you like to think otherwise). So pretty much, is there a better way of doing this, and if so, how?

EDIT: Well after request, here’s the sproc

CREATE PROCEDURE ProcStatInsertTrigger      @Date DATE,     @CampaignId BIGINT,     @CampaignName varchar(500),     @AdvertiserId BIGINT,     @PublisherId BIGINT,     @Unique BIT,     @Approved BIT,     @PublisherEarning money,     @AdvertiserCost money,     @Type smallint AS BEGIN     -- SET NOCOUNT ON added to prevent extra result sets from     -- interfering with SELECT statements.     SET NOCOUNT ON; IF @Approved = 1         BEGIN             DECLARE @test bit              SELECT @test = 1 FROM CachedStats WHERE [Date] = @Date AND CampaignId = @CampaignId AND CustomerId = @PublisherId              IF @test IS NULL                 BEGIN                     INSERT INTO CachedStats ([Date], CustomerId, CampaignId, CampaignName) VALUES (@Date, @PublisherId, @CampaignId, @CampaignName)                 END              SELECT @test = NULL                      DECLARE @Clicks int                     DECLARE @TotalAdvertiserCost money                     DECLARE @TotalPublisherEarning money                     DECLARE @PublisherCPC money                     DECLARE @AdvertiserCPC money                      SELECT @Clicks = Clicks, @TotalAdvertiserCost = AdvertiserCost + @AdvertiserCost, @TotalPublisherEarning = PublisherEarning + @PublisherEarning FROM CachedStats                     WHERE [Date] = @Date AND CustomerId = @PublisherId AND CampaignId = @CampaignId                      IF @Type = 0 -- If click add one to the calculation                         BEGIN                             SELECT @Clicks = @Clicks + 1                         END                      IF @Clicks > 0                         BEGIN                             SELECT @PublisherCPC = @TotalPublisherEarning / @Clicks, @AdvertiserCPC = @TotalAdvertiserCost / @Clicks                         END                     ELSE                         BEGIN                             SELECT @PublisherCPC = 0, @AdvertiserCPC = 0                         END             IF @Type = 0                 BEGIN                      UPDATE CachedStats SET                         Clicks = @Clicks,                         UniqueClicks = UniqueClicks + @Unique,                         PublisherEarning = @TotalPublisherEarning,                         AdvertiserCost = @TotalAdvertiserCost,                         PublisherCPC = @PublisherCPC,                         AdvertiserCPC = @AdvertiserCPC                     WHERE [Date] = @Date AND CustomerId = @PublisherId AND CampaignId = @CampaignId                 END             ELSE IF @Type = 1 OR  @Type = 4 -- lead or coreg                 BEGIN                     UPDATE CachedStats SET                         Leads = Leads + 1,                         PublisherEarning = @TotalPublisherEarning,                         AdvertiserCost = @TotalAdvertiserCost,                         AdvertiserCPC = @AdvertiserCPC,                         PublisherCPC = @AdvertiserCPC                     WHERE [Date] = @Date AND CustomerId = @PublisherId AND CampaignId = @CampaignId                 END             ELSE IF @Type = 3 -- Isale                 BEGIN                     UPDATE CachedStats SET                         Leads = Leads + 1,                         PublisherEarning = @TotalPublisherEarning,                         AdvertiserCost = @TotalAdvertiserCost,                         AdvertiserCPC = @AdvertiserCPC,                         PublisherCPC = @AdvertiserCPC,                         AdvertiserOrderValue = @AdvertiserCost,                         PublisherOrderValue = @PublisherEarning                      WHERE [Date] = @Date AND CustomerId = @PublisherId AND CampaignId = @CampaignId                                  END            ELSE IF @Type = 2 -- View                 BEGIN                     UPDATE CachedStats SET                         [Views] = [Views] + 1,                         UniqueViews = UniqueViews + @Unique,                         PublisherEarning = @TotalPublisherEarning,                         AdvertiserCost = @TotalAdvertiserCost,                         PublisherCPC = @PublisherCPC,                         AdvertiserCPC = @AdvertiserCPC                     WHERE [Date] = @Date AND CustomerId = @PublisherId AND CampaignId = @CampaignId                          END         END END 

After help, here’s my final result, posted in case others have a similiar issue

CREATE TRIGGER [dbo].[TR_STAT_INSERT]    ON  [iqdev].[dbo].[Stat]    AFTER INSERT AS  BEGIN      SET NOCOUNT ON      -- insert all missing 'CachedStats' rows     INSERT INTO         CachedStats ([Date], AdvertId, CustomerId, CampaignId, CampaignName)      SELECT DISTINCT         CONVERT(Date, i.[Date]), i.AdvertId, i.[PublisherCustomerId], c.Id, c.Name     FROM         Inserted i         INNER JOIN Advert AS   a ON a.Id = i.AdvertId         INNER JOIN Campaign AS c ON c.Id = a.CampaignId     WHERE         i.[Approved] = 1         AND NOT EXISTS (                 SELECT 1                  FROM CachedStats as t                 WHERE                          [Date] = CONVERT(Date, i.[Date])                         AND CampaignId = c.Id                          AND CustomerId = i.[PublisherCustomerId]                         AND t.AdvertId = i.AdvertId         )    -- update all affected records at once     UPDATE          CachedStats     SET         Clicks =              Clicks + (                 SELECT COUNT(*) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] = 0             ),         UniqueClicks =              UniqueClicks + (                 SELECT COUNT(*) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.[Unique] = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] = 0             ),         [Views] =              [Views] + (                 SELECT COUNT(*) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] = 2             ),         UniqueViews =              UniqueViews + (                 SELECT COUNT(*) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.[Unique] = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] = 2             ),         Leads =              Leads + (                 SELECT COUNT(*) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.[Unique] = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] IN (1,3,4)             ),         PublisherEarning =             CachedStats.PublisherEarning + ISNULL((                 SELECT SUM(PublisherEarning) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                         ), 0),         AdvertiserCost =             CachedStats.AdvertiserCost + ISNULL((                 SELECT SUM(AdvertiserCost) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId             ), 0),         PublisherOrderValue =             PublisherOrderValue + ISNULL((                 SELECT SUM(PublisherEarning) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] = 3                           ), 0),         AdvertiserOrderValue =             AdvertiserOrderValue + ISNULL((                 SELECT SUM(AdvertiserCost) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                            AND   s.[Type] = 3             ), 0),         PublisherCPC =              CASE WHEN (Clicks + (                 SELECT COUNT(*) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] = 0             )) > 0 THEN                 (CachedStats.PublisherEarning + ISNULL((                 SELECT SUM(PublisherEarning) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                        ), 0)) -- COST ^                 / (                     Clicks + (                         SELECT COUNT(*) FROM Inserted s                         WHERE s.Approved = 1                         AND   s.PublisherCustomerId = i.PublisherCustomerId                         AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                         AND   s.AdvertId = i.AdvertId                         AND   s.[Type] = 0                     )                                ) --- Clicks ^             ELSE                 0             END,             AdvertiserCPC =              CASE WHEN (Clicks + (                 SELECT COUNT(*) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                 AND   s.[Type] = 0             )) > 0 THEN                 (CachedStats.AdvertiserCost + ISNULL((                 SELECT SUM(AdvertiserCost) FROM Inserted s                 WHERE s.Approved = 1                 AND   s.PublisherCustomerId = i.PublisherCustomerId                 AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                 AND   s.AdvertId = i.AdvertId                        ), 0)) -- COST ^                 / (                     Clicks + (                         SELECT COUNT(*) FROM Inserted s                         WHERE s.Approved = 1                         AND   s.PublisherCustomerId = i.PublisherCustomerId                         AND   CONVERT(Date, s.[Date]) = CONVERT(Date, i.[Date])                         AND   s.AdvertId = i.AdvertId                         AND   s.[Type] = 0                     )                                ) --- Clicks ^             ELSE                 0             END         FROM         Inserted i     WHERE         i.Approved = 1 AND         CachedStats.Advertid = i.AdvertId AND         CachedStats.[Date] = Convert(Date, i.[Date]) AND         CachedStats.CustomerId = i.PublisherCustomerId   SET NOCOUNT OFF END 

It looks slightly different now because I had to index it per advertisement too – but thanks alot for the help – sped everything up from 30hour+ to 30 sec to generate the CachedStats from my own development Stat table 🙂

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-11T10:21:33+00:00Added an answer on May 11, 2026 at 10:21 am

    The trick with these kinds of situations is to turn the sequential operation (for each record do xyz) into a set-based operation (an UPDATE statement).

    I have analyzed your stored procedure and merged your separate UPDATE statements into a single one. This single statement can then be transformed into a version that can be applied to all inserted records at once, eliminating the need for a stored procedure and thereby the need for a cursor.

    EDIT: Below is the code that we finally got working. Execution time for the whole operation went down from ‘virtually forever’ (for the original solution) to something under one second, according to the OP’s feedback. Overall code size also decreased quite noticeably.

    CREATE TRIGGER [dbo].[TR_STAT_INSERT]    ON  [iqdev].[dbo].[Stat]    AFTER INSERT AS  BEGIN   SET NOCOUNT ON    -- insert all missing 'CachedStats' rows   INSERT INTO     CachedStats ([Date], AdvertId, CustomerId, CampaignId, CampaignName)    SELECT DISTINCT     CONVERT(Date, i.[Date]), i.AdvertId, i.PublisherCustomerId, c.Id, c.Name   FROM     Inserted i     INNER JOIN Advert   a ON a.Id = i.AdvertId     INNER JOIN Campaign c ON c.Id = a.CampaignId   WHERE     i.Approved = 1     AND NOT EXISTS (        SELECT 1        FROM   CachedStats       WHERE  Advertid   = i.AdvertId AND              CustomerId = i.PublisherCustomerId AND              [Date]     = CONVERT(DATE, i.[Date])     )    -- update all affected records at once   UPDATE      CachedStats   SET     Clicks               = Clicks               + i.AddedClicks,     UniqueClicks         = UniqueClicks         + i.AddedUniqueClicks,     [Views]              = [Views]              + i.AddedViews,     UniqueViews          = UniqueViews          + i.AddedUniqueViews,     Leads                = Leads                + i.AddedLeads,     PublisherEarning     = PublisherEarning     + ISNULL(i.AddedPublisherEarning, 0),     AdvertiserCost       = AdvertiserCost       + ISNULL(i.AddedAdvertiserCost, 0),     PublisherOrderValue  = PublisherOrderValue  + ISNULL(i.AddedPublisherOrderValue, 0),     AdvertiserOrderValue = AdvertiserOrderValue + ISNULL(i.AddedAdvertiserOrderValue, 0)   FROM     (     SELECT       AdvertId,       CONVERT(DATE, [Date]) [Date],       PublisherCustomerId,       COUNT(*) NumRows,       SUM(CASE WHEN Type IN (0)                      THEN 1 ELSE 0 END) AddedClicks,       SUM(CASE WHEN Type IN (0)     AND [Unique] = 1 THEN 1 ELSE 0 END) AddedUniqueClicks,       SUM(CASE WHEN Type IN (2)                      THEN 1 ELSE 0 END) AddedViews,       SUM(CASE WHEN Type IN (2)     AND [Unique] = 1 THEN 1 ELSE 0 END) AddedUniqueViews,       SUM(CASE WHEN Type IN (1,3,4) AND [Unique] = 1 THEN 1 ELSE 0 END) AddedLeads,       SUM(PublisherEarning)                                      AddedPublisherEarning,       SUM(AdvertiserCost)                                        AddedAdvertiserCost,       SUM(CASE WHEN Type IN (3) THEN PublisherOrderValue  ELSE 0 END) AddedPublisherOrderValue,       SUM(CASE WHEN Type IN (3) THEN AdvertiserOrderValue ELSE 0 END) AddedAdvertiserOrderValue     FROM       Inserted     WHERE       Approved = 1     GROUP BY       AdvertId,       CONVERT(DATE, [Date]),       PublisherCustomerId     ) i      INNER JOIN CachedStats cs ON        cs.Advertid   = i.AdvertId AND       cs.CustomerId = i.PublisherCustomerId AND       cs.[Date]     = i.[Date]    SET NOCOUNT OFF END 

    The operations involving the CachedStats table will greatly benefit from one multiple-column index over (Advertid, CustomerId, [Date]) (as confirmed by the OP).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 78k
  • Answers 78k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • added an answer I think you really ought to be using the ValueProvider… May 11, 2026 at 3:41 pm
  • added an answer My product uses layered windows to draw the little tabs… May 11, 2026 at 3:41 pm
  • added an answer Here is the link to XML query expression to select… May 11, 2026 at 3:41 pm

Related Questions

I'm writing a program that needs to take input from an XBox 360 controller.
I have a fairly large PHP codebase (10k files) that I work with using
i have an application that records a date/time when the space bar is pressed
Is it possible to do CAD/CAM software without having to use C++? My company

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.