trigger

  • I have three tables one called PONumber which has PONumber and Subtotal another table called PurchaseOrderHeader and one called PurchaseOrderDetail the PurchaseOrderDetail it has Qty, Price, shipping, and total adds up automatically Im wanting a Trigger to update the PONumber Subtotal. The PurchasedOrderDetail has multiple lines for the same PONumber that is why I am using the sum(total) as Subtotal which with out the trigger information it works right

    --alter Trigger UPDate_PONumber

    --On PurchaseOrderDetail

    --for insert, Update, delete

    --as

    Declare @SubTotal decimal(14,2)

    Select sum (Total) as SubTotal, pod.PurchaseOrderID, PON.PONumber , PON.SubTotal

    from PurchaseOrderDetail as POD

    inner Join PurchaseOrderHeader as POH

    on POD.PurchaseOrderID = POH.PurchaseOrderID

    Inner join PONumber as PON

    on PON.PONumber = POH.PONumber

    where POD.PurchaseOrderID = POD.PurchaseOrderID

    Group by POD.PurchaseOrderID, pod.PurchaseOrderID, PON.PONumber, PON.SubTotal

    if (@SubTotal!=0)

    Begin

    update PONumber

    set SubTotal = @SubTotal

    where PONumber = PONumber

    End

  • If you provide DDL and sample data for your PO Header and Detail tables, I or someone else can make short work of this and give you a tested solution.


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • Here is the script for the database.

  • edward_hall76 (7/24/2012)


    Here is the script for the database.

    I think you may have forgotten to include the attachment?


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St

  • edward_hall76 (7/24/2012)


    Here is the script for the database.

    Holy cow. We don't need the entire database just the stuff relevant to your issue. In the future it would probably be in your best interest to post the code using IFCode shortcuts (over there on the left when you are posting) instead of a Word doc.

    I took the liberty of retrieving the relevant tables from your description.

    CREATE TABLE [dbo].[PONumber](

    [PONumber] [int] NOT NULL,

    [SubTotal] [decimal](14, 2) NULL,

    CONSTRAINT [PK_PONumber] PRIMARY KEY CLUSTERED

    (

    [PONumber] ASC

    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

    ) ON [PRIMARY]

    GO

    CREATE TABLE [dbo].[PurchaseOrderHeader](

    [PurchaseOrderID] [int] IDENTITY(1,1) NOT NULL,

    [PONumber] [int] NULL,

    [VendorID] [int] NULL,

    [ApporvedBy] [varchar](50) NULL,

    [ApporvedDate] [date] NULL,

    [DateModified] [datetime] NULL,

    [DeptID] [int] NULL,

    [AccountNumber] [varchar](50) NULL,

    CONSTRAINT [PK_PurchaseOrderHeader] PRIMARY KEY CLUSTERED

    (

    [PurchaseOrderID] ASC

    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

    ) ON [PRIMARY]

    GO

    CREATE TABLE [dbo].[PurchaseOrderDetail](

    [PurchaseOrderDetailID] [int] IDENTITY(1,1) NOT NULL,

    [PurchaseOrderID] [int] NULL,

    [DeptID] [varchar](50) NULL,

    [AccountNumber] [varchar](50) NULL,

    [PODate] [date] NULL,

    [Product] [varchar](50) NULL,

    [QTY] [int] NULL,

    [Price] [decimal](14, 2) NULL,

    [Shipping] [decimal](14, 2) NULL,

    [Total] AS ([QTY]*[Price]+[Shipping])

    ) ON [PRIMARY]

    GO

    OK so now we have tables but we still don't have any data to work with. See the first link in my signature about best practices when posting questions.

    In looking at your trigger I am totally confused what you are trying to do. You define a @SubTotal variable but never set a value. You never reference the inserted table in your code.

    if (@SubTotal!=0)

    Begin

    update PONumber

    set SubTotal = @SubTotal

    where PONumber = PONumber

    I think I understand what you are trying to accomplish. Let me know if I am incorrect but I think you want to update PONumber and set the SubTotal = sum of Total from PurchaseOrderDetail?

    This is certainly obtainable but is one the main reasons it is frowned on to store calculated data like this. I would suggest you create a view instead of a permanent table with calculated totals.

    Something like this:

    create view PONumber

    as

    select poh.PONumber, SUM(pod.Total) as SubTotal

    from PurchaseOrderHeader poh

    join PurchaseOrderDetail pod on poh.PurchaseOrderID = pod.PurchaseOrderID

    group by poh.PONumber

    This way you don't have to worry about your trigger and the possible performance issues along with possible data issues from not having your calculated data updated correctly.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • He is the information in the database.

    On a view will it update the PONumber table everytime something is updated or added to the PurhcaseOrderDetail

  • edward_hall76 (7/25/2012)


    He is the information in the database.

    On a view will it update the PONumber table everytime something is updated or added to the PurhcaseOrderDetail

    I don't understand your response here. A view doesn't update anything. It would be used to get current information instead of trying to store calculated data. Storing calculated data like you are trying to do is fraught with issues. Your example is text book case of why you should use views.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • I think the code below should at least be close to what you need (hopefully very close :-)):

    ALTER TRIGGER UPDate_PONumber

    ON dbo.PurchaseOrderDetail

    AFTER INSERT, UPDATE, DELETE

    AS

    UPDATE PON

    SET SubTotal = PO_Total.SubTotal

    FROM dbo.PONumber AS PON

    INNER JOIN (

    SELECT

    SUM(Total) AS SubTotal, POH.PONumber

    FROM dbo.PurchaseOrderDetail AS POD

    INNER JOIN inserted AS i

    ON i.PurchaseOrderDetailID = pod.PurchaseOrderDetailID

    INNER JOIN dbo.PurchaseOrderHeader AS POH

    ON POH.PurchaseOrderID = POD.PurchaseOrderID

    GROUP BY

    POH.PONumber

    ) AS PO_Total

    ON PON2.PONumber = PO_Total.PONumber

    GO

    SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".

  • ScottPletcher (7/25/2012)


    I think the code below should at least be close to what you need (hopefully very close :-)):

    ALTER TRIGGER UPDate_PONumber

    ON dbo.PurchaseOrderDetail

    AFTER INSERT, UPDATE, DELETE

    AS

    UPDATE PON

    SET SubTotal = PO_Total.SubTotal

    FROM dbo.PONumber AS PON

    INNER JOIN (

    SELECT

    SUM(Total) AS SubTotal, POH.PONumber

    FROM dbo.PurchaseOrderDetail AS POD

    INNER JOIN inserted AS i

    ON i.PurchaseOrderDetailID = pod.PurchaseOrderDetailID

    INNER JOIN dbo.PurchaseOrderHeader AS POH

    ON POH.PurchaseOrderID = POD.PurchaseOrderID

    GROUP BY

    POH.PONumber

    ) AS PO_Total

    ON PON2.PONumber = PO_Total.PONumber

    GO

    This does not handle deletes though. 😉 You need to subtract when deleting.

    OP - What do you want to happen to that table if you delete the last detail? Do you want to leave orphans or delete it?

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • Sean Lange (7/25/2012)


    ScottPletcher (7/25/2012)


    I think the code below should at least be close to what you need (hopefully very close :-)):

    ALTER TRIGGER UPDate_PONumber

    ON dbo.PurchaseOrderDetail

    AFTER INSERT, UPDATE, DELETE

    AS

    UPDATE PON

    SET SubTotal = PO_Total.SubTotal

    FROM dbo.PONumber AS PON

    INNER JOIN (

    SELECT

    SUM(Total) AS SubTotal, POH.PONumber

    FROM dbo.PurchaseOrderDetail AS POD

    INNER JOIN inserted AS i

    ON i.PurchaseOrderDetailID = pod.PurchaseOrderDetailID

    INNER JOIN dbo.PurchaseOrderHeader AS POH

    ON POH.PurchaseOrderID = POD.PurchaseOrderID

    GROUP BY

    POH.PONumber

    ) AS PO_Total

    ON PON2.PONumber = PO_Total.PONumber

    GO

    This does not handle deletes though. 😉 You need to subtract when deleting.

    OP - What do you want to happen to that table if you delete the last detail? Do you want to leave orphans or delete it?

    Good point about DELETEs -- remove DELETE from the trigger actions:

    AFTER INSERT, UPDATE

    and use a separate trigger for that.

    SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".

  • ScottPletcher (7/25/2012)


    Sean Lange (7/25/2012)


    ScottPletcher (7/25/2012)


    I think the code below should at least be close to what you need (hopefully very close :-)):

    ALTER TRIGGER UPDate_PONumber

    ON dbo.PurchaseOrderDetail

    AFTER INSERT, UPDATE, DELETE

    AS

    UPDATE PON

    SET SubTotal = PO_Total.SubTotal

    FROM dbo.PONumber AS PON

    INNER JOIN (

    SELECT

    SUM(Total) AS SubTotal, POH.PONumber

    FROM dbo.PurchaseOrderDetail AS POD

    INNER JOIN inserted AS i

    ON i.PurchaseOrderDetailID = pod.PurchaseOrderDetailID

    INNER JOIN dbo.PurchaseOrderHeader AS POH

    ON POH.PurchaseOrderID = POD.PurchaseOrderID

    GROUP BY

    POH.PONumber

    ) AS PO_Total

    ON PON2.PONumber = PO_Total.PONumber

    GO

    This does not handle deletes though. 😉 You need to subtract when deleting.

    OP - What do you want to happen to that table if you delete the last detail? Do you want to leave orphans or delete it?

    Good point about DELETEs -- remove DELETE from the trigger actions:

    AFTER INSERT, UPDATE

    and use a separate trigger for that.

    Why? You can do an

    IF (SELECT COUNT(*) FROM INSERTED > 0) for inserts and updates and then ELSE for deletes.

    Jared
    CE - Microsoft

  • All this work and effort to store a piece of data that should be retrieved real time using a view instead. 😛

    I would comment on the table structure a little bit. You have PONumber in your PONumber table. This column is not unique in the PurchaseOrderHeader, and shouldn't be unique. However it is effectively the PK of the PONumber table. It should instead have PurchaseOrderID and then add an actual foreign key to PurchaseOrderHeader. The other challenge is your PONumber is an int. Unless this is holding ONLY PONumbers from your system you will have issues with that. There are plenty of companies out there that use character data in their PONum.

    I am not quite sure why you have DeptID, AccountNumber and PODate in the detail table. Those all look like they belong to the entire PO and not the line items. Of course I may be wrong on these since you have AccountNumber in both the header and the detail tables.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • Thats working ok except if there is already a amount in the subtotal in the PONumber table then it doesnt add them together.

    I also get a error if trying to insert data into the table using another software as a frount end.

  • The reason for account number being the line item is because each office has there own budget and they are broken into computer supplies, office furnture, copy supplies etc and each one has its on accoun number like xxx-000-yyy so we would have to show which account it is comeing out of for the same po or they would have to fill out multuple pos.

  • edward_hall76 (7/25/2012)


    Thats working ok except if there is already a amount in the subtotal in the PONumber table then it doesnt add them together.

    I also get a error if trying to insert data into the table using another software as a frount end.

    That is because the trigger as posted does not do what you want/need it to. The update statement should be

    UPDATE PON

    SET SubTotal = PON.SubTotal + PO_Total.SubTotal

    ...

    As for the error I am guessing your insert statement has an OUTPUT clause? Here is a link that explains the condition and at least one way to work around it. http://beyondrelational.com/modules/2/blogs/115/posts/11166/output-clause-and-triggers.aspx

    OK so I have to ask. I have suggested multiple times using a view for this but you are still fighting a battle to make this into a trigger. What is wrong with doing this the easy way?

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

Viewing 15 posts - 1 through 15 (of 23 total)

You must be logged in to reply to this topic. Login to reply