Question

Need to fix this trigger to run on both SQL7 and SQL 2000.

Asked by: Dexstar

I need to have code for this trigger that works properly on both SQL7 and SQL 2000.  If I try to run the original version (made for SQL7) on SQL2000, it gives me an error.  With a small change, I can make it so that SQL 2000 accepts it, but then SQL7 doesn't like it.  Help me come up with a version that works on both so I can have one script that I can use on both platforms.

FYI:  I can't accept any answer that uses cursors or that doesn't work properly on batch updates.

Here is the trigger code:

-------------------------------------
-- SQL Server 7.0
-------------------------------------
CREATE TRIGGER tblAccountEntries_Maintain_Balance
ON dbo.tblAccountEntries
FOR INSERT, UPDATE, DELETE
AS
      -- Do not return row count
      SET NOCOUNT ON
      -- Update the balance if the amount, AssetID, or AccountID has changed
      -- OR if the record is being deleted (indicated by COLUMNS_UPDATED() = 0)
      IF ( UPDATE(Amount) OR UPDATE(AssetID) OR UPDATE(AccountID) OR (COLUMNS_UPDATED() = 0) )
            BEGIN
                  -- Update the Balances
                  UPDATE
                        dbo.tblAccountBalances
                  SET
                        CurrentBalance = AB.CurrentBalance + Change
                  FROM
                        dbo.tblAccountBalances AB INNER JOIN
                         (
                              SELECT COALESCE(I.AccountID, D.AccountID) AS AccountID,
                                    COALESCE(I.AssetID, D.AssetID) AS AssetID,
                                    SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) AS Change
                                    FROM Inserted I FULL OUTER JOIN Deleted D ON
                                          I.AccountID = D.AccountID
                                          AND
                                          I.AssetID = D.AssetID
                                          AND
                                          I.EntryID = D.EntryID
                                    GROUP BY
                                          COALESCE(I.AccountID, D.AccountID),
                                          COALESCE(I.AssetID, D.AssetID)
                         ) AS ChangeData ON
                              AB.AssetID = AssetID
                              AND
                              AB.AccountID = AccountID

                  -- Rollback on error
                  IF ( @@ERROR <> 0 )
                        BEGIN
                              ROLLBACK TRANSACTION
                        END
            END


-----------------------------
-- SQL Server 2000
------------------------------
CREATE TRIGGER tblAccountEntries_Maintain_Balance
ON dbo.tblAccountEntries
FOR INSERT, UPDATE, DELETE
AS
      -- Do not return row count
      SET NOCOUNT ON
      -- Update the balance if the amount, AssetID, or AccountID has changed
      -- OR if the record is being deleted (indicated by COLUMNS_UPDATED() = 0)
      IF ( UPDATE(Amount) OR UPDATE(AssetID) OR UPDATE(AccountID) OR (COLUMNS_UPDATED() = 0) )
            BEGIN
                  -- Update the Balances
                  UPDATE
                        dbo.tblAccountBalances
                  SET
                        CurrentBalance = AB.CurrentBalance + Change
                  FROM
                        dbo.tblAccountBalances AB INNER JOIN
                         (
                              SELECT COALESCE(I.AccountID, D.AccountID) AS AccountID,
                                    COALESCE(I.AssetID, D.AssetID) AS AssetID,
                                    SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) AS Change
                                    FROM Inserted I FULL OUTER JOIN Deleted D ON
                                          I.AccountID = D.AccountID
                                          AND
                                          I.AssetID = D.AssetID
                                          AND
                                          I.EntryID = D.EntryID
                                    GROUP BY
                                          COALESCE(I.AccountID, D.AccountID),
                                          COALESCE(I.AssetID, D.AssetID)
                         ) AS ChangeData ON
                              AB.AssetID = ChangeData.AssetID
                              AND
                              AB.AccountID = ChangeData.AccountID

                  -- Rollback on error
                  IF ( @@ERROR <> 0 )
                        BEGIN
                              ROLLBACK TRANSACTION
                        END
            END

---
(Yes, I really do always format my SQL code that way...)

The only change is to this part, where in the SQL2000 version, I specify the sub-query's alias on the columns:
                         ) AS ChangeData ON
                              AB.AssetID = ChangeData.AssetID
                              AND
                              AB.AccountID = ChangeData.AccountID

If I run the SQL7 version on SQL2K, I get this error:
      Server: Msg 209, Level 16, State 1, Procedure tblAccountEntries_Maintain_Balance, Line 2 Ambiguous column name 'AssetID'.

If I run the SQL2K version on SQL7, I get this error:
      Error 107: the column prefix 'ChangeData' does not match with a table name or alias name used in the query

Oh, and I'm always open to any other suggestions you guys could make about optimizing the query or anything like that.  This trigger runs quite frequently, so anything that improves the performance is worth extra points.

Dex*

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2004-03-30 at 11:20:36ID20937692
Tags

column

,

name

,

sql

,

trigger

Topic

MS SQL Server

Participating Experts
2
Points
500
Comments
12

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Audit Triggers and Rollbacks?
    I see this question has been hashed out many different ways but I am still unable to get what I need. Here is my situation. I need to log inserts, updates, and deletes occuring on 4 seperate tables. I have decided to make a copy of each table and use the corresponding c...
  2. Ambiguous column name
    I have a coloum called OBCUSD within a table and when ever i run a sum on this coloum i get a "Ambiguous column name" error appear. A: what is this B: how can i over come it? I tried to do a SELECT OBCUSD AS 'OTHER_NAME' But this did not work for the query that i w...
  3. SET NOCOUNT ON clearing @@ROWCOUNT in trigger
    On Books online it says: "The @@ROWCOUNT function is updated even when SET NOCOUNT is ON" Thus, I created the following trigger: CREATE TRIGGER triggerMaster ON dbo.CG_BalanceMovements AFTER INSERT AS set nocount on if (@@rowcount = 1) begin -- do intere...
  4. Problem with prefix for inner join and output to file
    Hello, I'm writing a store procedure that uses inner joins but for some reason I am getting the following error: Server: Msg 107, Level 16, State 2, Procedure mw_aragedreceivables_sp, Line 206 The column prefix 'a' does not match with a table name or alias name used in the q...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: LowfatspreadPosted on 2004-03-30 at 12:34:16ID: 10717443

whats the point of the entryid condition on the Join ?  

 

by: DexstarPosted on 2004-03-30 at 12:40:18ID: 10717502

@Lowfatspread:

It uniquely identifies each entry record, so that if a record is updated, the inserted and deleted values match up in the join.  Does it look like it isn't necessary to you?  I'd have to try removing it and do some testing.  Either way, I'm not sure it would fix the immediate problem.

Dex*

 

by: LowfatspreadPosted on 2004-03-30 at 12:43:55ID: 10717545

try this

you shouldn't have to modify the trigger for SQL 7 or 2000

i don't see the point of doing the individual column update tests
particularly as the trigger functions across the insert,update,delete
functions and the results are consistent...

so use a temp table, and only do the updates if a "Total" change has occurred for the account...  


CREATE TRIGGER tblAccountEntries_Maintain_Balance
ON dbo.tblAccountEntries
FOR INSERT, UPDATE, DELETE
AS
     -- Do not return row count
     SET NOCOUNT ON

Select AccountID,AssetId,Change Into #Temp
  From (
SELECT COALESCE(I.AccountID, D.AccountID) AS AccountID,
       COALESCE(I.AssetID, D.AssetID) AS AssetID,
       SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) AS Change
  FROM Inserted I
  FULL OUTER JOIN Deleted D
    ON I.AccountID = D.AccountID
   AND I.AssetID = D.AssetID
 GROUP BY  COALESCE(I.AccountID, D.AccountID),
           COALESCE(I.AssetID, D.AssetID)
     ) as X
 Where Change <> 0


              -- Update the Balances
               IF @@ERROR = 0
               BEGIN
                  UPDATE  dbo.tblAccountBalances
                     SET CurrentBalance = AB.CurrentBalance + T.Change
                    FROM   dbo.tblAccountBalances AB
                   INNER JOIN #Temp as T
                      ON AB.AssetID = T.AssetID
                     AND AB.AccountID = T.AccountID
               -- Rollback on error
                  IF ( @@ERROR <> 0 )
                    BEGIN
                         ROLLBACK TRANSACTION
                    END
               END
               else
                    BEGIN
                         ROLLBACK TRANSACTION
                    END



 

by: DexstarPosted on 2004-03-30 at 12:57:40ID: 10717708

@Lowfatspread:

I'll try it right now.  Do you think that you way is going to be more efficient?  If so, why?  Isn't using a temporary table expensive?

Dex*

 

by: danblakePosted on 2004-03-30 at 13:07:18ID: 10717831

Dex*,

Your error matches a previous sql-server version fault:
http://support.microsoft.com/default.aspx?scid=kb;en-us;825019&Product=sql2k
(Just in case you want to make this 6.5 compatible...)

But your exact problem is here (For sql-server 7):
http://support.microsoft.com/default.aspx?scid=kb;en-us;225492&Product=sql

(Looks like its' not completly fixed yet, the change you need to make is quite simple....)


Basically change the update statement to:
UPDATE
                    dbo.tblAccountBalances
               SET
                    CurrentBalance = AB.CurrentBalance + Change
               FROM
                     (
                         SELECT COALESCE(I.AccountID, D.AccountID) AS AccountID,
                              COALESCE(I.AssetID, D.AssetID) AS AssetID,
                              SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) AS Change
                              FROM Inserted I FULL OUTER JOIN Deleted D ON
                                   I.AccountID = D.AccountID
                                   AND
                                   I.AssetID = D.AssetID
                                   AND
                                   I.EntryID = D.EntryID
                              GROUP BY
                                   COALESCE(I.AccountID, D.AccountID),
                                   COALESCE(I.AssetID, D.AssetID)
                     ) AS ChangeData
              INNER JOIN                     dbo.tblAccountBalances AB
             ON
                         AB.AssetID = ChangeData.AssetID
                         AND
                         AB.AccountID = ChangeData.AccountID


Not a massive major change, and should keep you up and running.
Saves using the temporary table !...

(Also I like the use of your update() /Columns_Updated checks..., Formating is also good.)

Rgds,

Dan.

 

by: DexstarPosted on 2004-03-30 at 13:22:41ID: 10718008

@Dan:  I like the fact that you got the source of the problem.  That helps me out a lot.  It helps me to know that I'm going crazy ... It's actually a known SQL bug.  :)

@Lowfatspread:  I'd still like to hear if you think using a temporary table is a good idea.  I said I'd give points to optimizing the query.  There seems to be some disagreement on whether or not my UPDATE() usage is appropriate.

Dex*

 

by: danblakePosted on 2004-03-30 at 13:33:03ID: 10718134

Dex*,

I've fixed this one before...

Thanks,

Dan.

 

by: LowfatspreadPosted on 2004-03-30 at 13:39:19ID: 10718189

... I like your formatting as well

I've never experienced problems with using a temp table, but we're not heavy users of triggers

it may depend on your mix of singleton to multiple row updates... but you need to cater for both...

if you've got multi-row updates then its probably as well to confirm you actually need to update
the column test only tell you that some rows have had a column change...

the best approach may be to do without the temp table altogether , like your original example
but you need to consider the query plans involved and the likely update scenarios...

the advantage of the initial creation of the temp table is that only 2 "small" virtual tables are being
processed... doing it on the update statement (may)involve the physical table as well...

e.g.
 
Just

              -- Update the Balances
               IF @@ERROR = 0
               BEGIN
                  UPDATE  dbo.tblAccountBalances
                     SET CurrentBalance = AB.CurrentBalance + T.Change
                    FROM   dbo.tblAccountBalances AB
                   INNER JOIN

(Select AccountID,AssetId,Change
  From (
SELECT COALESCE(I.AccountID, D.AccountID) AS AccountID,
       COALESCE(I.AssetID, D.AssetID) AS AssetID,
       SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) AS Change
  FROM Inserted I
  FULL OUTER JOIN Deleted D
    ON I.AccountID = D.AccountID
   AND I.AssetID = D.AssetID
 GROUP BY  COALESCE(I.AccountID, D.AccountID),
           COALESCE(I.AssetID, D.AssetID)
     ) as X
 Where Change <> 0
) as T
                      ON AB.AssetID = T.AssetID
                     AND AB.AccountID = T.AccountID



Ps . I still don't understand the inclusion of the Entryid test in your update statement....

 

by: DexstarPosted on 2004-03-30 at 15:40:21ID: 10719307

I'm working a solution that combines the suggestions.  I like lowfat's idea of filtering out the records where Change = 0, to avoid unnecessary updates because I know SQL Server will physically do the update, even if the value doesn't change.  And, I will obviously need to change the order of the tables in the query to account for the SQL bug.

> Ps . I still don't understand the inclusion of the Entryid test in your update statement....

Consider a statement like this:
    UPDATE tblAccountEntries
    SET Amount = Amount + 1.50

Without the EntryID in the join, the AccountBalances get all messed up.       Here is the result of the sub-queries.  The 2nd one doesn't join on the EntryID, but the first one does.

AccountID                            AssetID     Change                
------------------------------------ ----------- ---------------------
00000000-0000-0000-0000-000000000001 100         61.5000
CFEF54C9-8D9E-40FA-A754-1FDE43640985 100         10.5000
8A6A3B19-F91F-4103-B051-2450673DD827 100         10.5000
490A7121-B1D1-4BC2-99B5-AD0020D997F3 100         4.5000
A2909DF4-FAAF-4ADE-A1DF-E8A7DD9D837E 100         3.0000
79186F24-09E8-4B49-93B4-F4D930748917 100         33.0000

AccountID                            AssetID     Change                
------------------------------------ ----------- ---------------------
00000000-0000-0000-0000-000000000001 100         2521.5000
CFEF54C9-8D9E-40FA-A754-1FDE43640985 100         73.5000
8A6A3B19-F91F-4103-B051-2450673DD827 100         73.5000
490A7121-B1D1-4BC2-99B5-AD0020D997F3 100         13.5000
A2909DF4-FAAF-4ADE-A1DF-E8A7DD9D837E 100         6.0000
79186F24-09E8-4B49-93B4-F4D930748917 100         726.0000


Dex*

 

by: DexstarPosted on 2004-03-30 at 15:59:11ID: 10719425

@Lowfatspread:

Just a quick question about your modification...  Are those two identical, or is there a reason to use one over the other?

---
(Select AccountID,AssetId,Change
  From (
SELECT COALESCE(I.AccountID, D.AccountID) AS AccountID,
       COALESCE(I.AssetID, D.AssetID) AS AssetID,
       SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) AS Change
  FROM Inserted I
  FULL OUTER JOIN Deleted D
    ON I.AccountID = D.AccountID
   AND I.AssetID = D.AssetID
 GROUP BY  COALESCE(I.AccountID, D.AccountID),
           COALESCE(I.AssetID, D.AssetID)
     ) as X
 Where Change <> 0
) as T
---
(SELECT COALESCE(I.AccountID, D.AccountID) AS AccountID,
       COALESCE(I.AssetID, D.AssetID) AS AssetID,
       SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) AS Change
  FROM Inserted I
  FULL OUTER JOIN Deleted D
    ON I.AccountID = D.AccountID
   AND I.AssetID = D.AssetID
  GROUP BY  COALESCE(I.AccountID, D.AccountID),
           COALESCE(I.AssetID, D.AssetID)
   HAVING
        SUM(COALESCE(I.Amount, 0) - COALESCE(D.Amount,0)) <> 0
) as T
---

Dex*

 

by: LowfatspreadPosted on 2004-03-31 at 09:38:05ID: 10725585

hopefully they are the same ...

you need to check the query plan to confirm that the Server has actually performed the same
operations....

i usually like to try an restrict the numbers of functions and aggregations I ask the optimiser to perform
as to my mind that usually makes for easier code maintenance, and simplifies query optimisation requirements..

 

 

by: DexstarPosted on 2004-04-02 at 12:16:08ID: 10744076

Thanks for your help guys!  :)  It is much appreciated!

-Dex*

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...