sql table trigger - sql

I need to write a table trigger and I've never done this before. Here's what I'm trying to accomplish. Every time an order is placed with $0, I need the payment type to be set to 100. I run the below query manually, however it would be great if this was processed automatically.
UPDATE tblPay
SET lngPayTypeID = '100'
WHERE (lngFloatID IN (14171)) AND (dateWebDate > '5/25/18 6:00PM')
AND (curTender = '0')
Any help is greatly appreciated.

Generate the trigger SetPayment on table tblPlay:
CREATE TRIGGER [dbo].[SetPayment]
ON [dbo].[tblPlay]
AFTER INSERT
AS
DECLARE
#lngFloatID float,
#curTender decimal
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT
#lngFloatID = lngFloatID,
#curTender = curTender
FROM
inserted
IF (#curTender = 0)
BEGIN
UPDATE
tblPay
SET
lngPayTypeID = '100'
WHERE
lngFloatID = #lngFloatID
END
END
When a record with curTender = 0 is inserted, it will get its lngFloatID and set its lngPayTypeID to 100.

Related

Stored procedure to replace null's in FK on fact table

I have built a fact table in a staging area, where some of the FK (the BK from dimensions) are NULL.
During the ETL in SSIS, I have used a derived column to replace all NULL's with the value "-1".
The problem is that I have 15 columns and it takes a long time to populate the entire table.
Is there a stored procedure that I can use to avoid this? Or any other method that reduces this time?
I did it doing the following stored procedure:
CREATE PROCEDURE [dbo].[Inferred_FACT_TABLE]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN
UPDATE [dbo].[FACT_STG_cenas]
SET [FK_Alpha] = -1
WHERE [FK_Alpha] IS NULL
UPDATE [dbo].[FACT_STG_cenas]
SET [FK_Bravo] = -1
WHERE [FK_Bravo] IS NULL
UPDATE [dbo].[FACT_STG_cenas]
SET [FK_Lima] = -1
WHERE [FK_Lima] IS NULL
UPDATE [dbo].[FACT_STG_cenas]
SET [FK_Charlie] = -1
WHERE [FK_Charlie] IS NULL
UPDATE [dbo].[FACT_STG_cenas]
SET [FK_Mike] = -1
WHERE [FK_Mike] IS NULL
END
END

Trigger running every time despite conditional statement

I am trying to write an update trigger on a table which would cause it to run an additional update statement only if a certain column has been changed, so far the trigger runs the update no matter what, hoping maybe someone can see what I am doing wrong here.
Here is the trigger.
ALTER TRIGGER [dbo].[StatusChangedUpdateTrigger]
ON [dbo].[Trans_Order]
AFTER UPDATE
AS
DECLARE #OldOrderStatusId INT, #NewStatusOrderId INT, #ERRNUM INT;
BEGIN
SET #OldOrderStatusId = (SELECT OrderStatusId FROM deleted);
SET #NewStatusOrderId = (SELECT OrderStatusId FROM inserted);
IF (#OldOrderStatusId != #NewStatusOrderId)
SET NOCOUNT ON;
UPDATE Trans_Order
SET StatusChanged = 1
WHERE Id = (SELECT ID FROM inserted)
END
For some reason this is running no matter what, I can never set StatusChanged to 0 as it will automatically flip it back to 1 even if the OrderStatusId hasn't changed. So my update statement is running no matter what, so I am guessing I am doing something wrong in the if statement.
Hmmmm . . . Your logic seems strange. I would expect:
UPDATE t
SET StatusChanged = 1
FROM Trans_Order t JOIN
Inserted i
ON t.id = i.id JOIN
Deleted d
ON t.id = d.id
WHERE i.OrderStatusId <> d.OrderStatusId;
You might need to take NULL values into account -- although your code does not.
Note that your code is just a bug waiting to happen, because it assumes that inserted and deleted have only one row.
The specific problem with your code is that it is really:
IF (#OldOrderStatusId != #NewStatusOrderId)
BEGIN
SET NOCOUNT ON;
END;
UPDATE Trans_Order
SET StatusChanged = 1
WHERE Id = (SELECT ID FROM inserted);
Your indentation has confused the logic. However, you should still use the set-based version so the trigger does not fail.
The correct way to approach your trigger is as follows:
create or alter trigger [dbo].[StatusChangedUpdateTrigger] on [dbo].[Trans_Order]
after update
as
set nocount on
if ##RowCount=0 return
if Update(OrderStatusId)
begin
update t
set statusChanged=1
from inserted i join deleted d on d.id=i.id and d.OrderStatusId != i.OrderStatusId
join Trans_Order t on t.id=i.id
end
Always test ##rowcount and return if no rows updated.
Always put set options before DML
As you are only looking to update if a specific column is updated you can test specifically for that and if the update statement that's run doesn't touch that column the trigger will not run.
This will correctly account for multiple rows being updated and only update those where the new value is different to the old value.

Update trigger for update new table from another

I have 2 tables mpayment and account. When someone updates data in mpayment, then the trigger should automatically update the account table with the newly updated data. I wrote this trigger on my mpayment table, but when I try to update some data, I get an error:
The row value update or deleted either do make the row unique or they alter multiplerows [2 rows]
This is my trigger that I am trying to use
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[mpacupdate]
ON [dbo].[mpayment]
AFTER UPDATE
AS
BEGIN
DECLARE #pid AS NCHAR(10)
DECLARE #memid AS NCHAR(10)
DECLARE #pdate AS DATE
DECLARE #pamount AS MONEY
DECLARE #flag AS INT
SELECT #pid = list.pid FROM inserted list;
SELECT #memid = list.memid FROM inserted list;
SELECT #pdate = list.pdate FROM inserted list;
SELECT #pamount = list.pamount FROM inserted list;
SELECT #flag = list.flag FROM inserted list;
BEGIN
UPDATE [dbo].[account]
SET memid = #memid, pdate = #pdate,
pamount = #pamount, flag = #flag
WHERE pid = #pid
END
END
Your trigger is assuming that only 1 row will be updating at a time; it shouldn't. Treat the data as what it is, a dataset (not a set a scalar values).
This maynot fix the problem, as there's no sample data here to test against. I'm also not really sure that what you're after here is the right design choice, however, there's no information on what that is. Generally, you shouldn't be repeating data across tables; if you need data from another table then use a JOIN, don't INSERT or UPDATE both. If they become out of sync you'll start to get some really odd results I imagine.
Anyway, on track, this is probably what you're looking for, however, please consider the comments I've made above:
ALTER TRIGGER [dbo].[mpacupdate] ON [dbo].[mpayment]
AFTER UPDATE
AS BEGIN
UPDATE A
SET memid = i.memid,
pdate = i.pdate,
pamount = i.pamount,
flag = i.flag
FROM dbo.Account A
JOIN inserted i ON A.pid = i.pid;
END

Update Trigger Appends data twice to column

O.F.,
So I have been attempting to build a trigger that will update a table based on the when a a row is updated in a different table. The trigger so far looks like this.
ALTER TRIGGER [dbo].[tst_update_USCATVLS_6]
ON [dbo].[IV00101]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #ITEMNUMBER VARCHAR(75)
SET #ITEMNUMBER = (SELECT ITEMNMBR FROM dbo.IV00101 WHERE DEX_ROW_TS = (SELECT MAX(DEX_ROW_TS) FROM dbo.IV00101))
UPDATE dbo.EXT00101 SET STRGA255 = (RTRIM(LTRIM(STRGA255))) + '_0' WHERE PT_UD_KEY = #ITEMNUMBER AND PT_UD_Number = 2
What seems to happen when I run the test update like the one below.
UPDATE PDM.TEST.dbo.IV00101
SET USCATVLS_6 = 'OBSOLETE'
WHERE ITEMNMBR = 'HMLGDN-7563252-4'
Is that the trigger fires but updates the desired column twice. The end result being this 20025947756319_0_0 instead of this 20025947756319_0.
The weird part of all of this is if I drop the trigger and run the same test update and then run the update statement that was in the trigger all statements execute and the data is updated as desired.
So running this as one block of code works:
UPDATE PDM.TEST.dbo.IV00101
SET USCATVLS_6 = 'OBSOLETE'
WHERE ITEMNMBR = 'HMLGDN-7563252-4'
DECLARE #ITEMNUMBER VARCHAR(75)
SET #ITEMNUMBER = (SELECT ITEMNMBR FROM PDM.TEST.dbo.IV00101 WHERE DEX_ROW_TS = (SELECT MAX(DEX_ROW_TS) FROM PDM.TEST.dbo.IV00101))
UPDATE PDM.TEST.dbo.EXT00101 SET STRGA255 = (RTRIM(LTRIM(STRGA255))) + '_0' WHERE PT_UD_KEY = #ITEMNUMBER AND PT_UD_Number = 2
If any one can help me figure out why this is happening I would greatly appreciate it.
Kindest regards,
Z.
Having read Sean Lange's Comments I looked up inserted and deleted tables. I saw reference to these tables before but didn't realize they were temporary tables and thought they were physical tables of the database in the example/answers I saw. Anyway I created a trigger to show the data in each which helped me see how to join them to the update statement in the trigger. All the code is below.
Trigger to see what was in Inserted and Deleted as well as the join referencing the Inserted table:
ALTER TRIGGER [dbo].[inserted_deleted_Table]
ON [dbo].[IV00101]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select 'NEW DATA', * from inserted --new data
select 'OLD Data', * from deleted --old data
select 'iv00101', * From iv00101 as i JOIN inserted as u on i.itemNmbr = u.itemNmbr and i.DEX_ROW_TS = u.DEX_ROW_TS
-- Insert statements for trigger here
END
The end solution was to remove this peice of code:
SET #ITEMNUMBER = (SELECT ITEMNMBR FROM INV00101 WHERE DEX_ROW_TS = (SELECT MAX(DEX_ROW_TS) FROM INV00101 ) AND USCATVLS_6 ='OBSOLETE' )
And then Add a the FROM clause to the UPDATE Statement:
UPDATE PDM.TEST.dbo.EXT00101 SET STRGA255 = (RTRIM(LTRIM(STRGA255))) + '_0'
FROM (
SELECT u.ITEMNMBR ,
u.DEX_ROW_TS
From iv00101 as i JOIN inserted as u on i.itemNmbr = u.itemNmbr and i.DEX_ROW_TS = u.DEX_ROW_TS) as p
WHERE PT_UD_KEY = p.ITEMNMBR AND PT_UD_Number = 2
Once I figured out that insert and deleted table were temp tables not actual tables in a DB all the pieces sorta fell into place. Thanks for pointing me in the direction I needed to go #Sean Lange.
Best Regards,
Z.

SQL Server 2008 R2: trigger after update

This is my first post so please bear with me. Here are the tables I'm working with and I'm only showing the relevant columns:
Movement:
id
cnt_tare_weight
chassis_tare_weight
Stop:
movement_id
order_id
For each movement record, there are 2 or more stop records. The way this works, is that we create an order and create the stops. The stops are grouped into movements.
Here's some example data:
Movement:
id cnt_tare_weight chassis_tare_weight
-------------------------------------------------
1545257 4525.2 3652.2
1545258 null null
Stop:
order_id movement_id
------------------------
0933774 1545257
0933774 1545257
0933774 1545258
0933774 1545258
Here's what I am trying to accomplish:
When the cnt_tare_weight and/or chassis_tare_weight are updated in the movement record, I need to copy this data to all other movement records for that order. I want to use a trigger after update to do this.
Here is what I've come up with but and I'm not sure it will work. I would like to see if what I'm wanting do is correct or if I'm missing something.
Here's my SQL:
CREATE TRIGGER set_tare_weights
ON movement
AFTER UPDATE AS
BEGIN
SET NOCOUNT ON;
DECLARE #movement_id AS INT;
DECLARE #cnt_tare_weight AS DECIMAL(8,1);
DECLARE #chz_tare_weight AS DECIMAL(8,1);
DECLARE #order_id AS int;
SELECT #movement_id = inserted.id
FROM INSERTED
IF update(cnt_tare_weight)
BEGIN
SET #cnt_tare_weight = 'Updated cnt_tare_weight'
END
IF update(chz_tare_weight)
BEGIN
SET #chz_tare_weight = 'Updated chz_tare_weight'
END
SELECT #order_id = order_id
FROM stop
WHERE movement_id = #movement_id
UPDATE movement
SET cnt_tare_weight = #cnt_tare_weight,
chz_tare_weight = #chz_tare_weight
WHERE #movement_id IN (SELECT DISTINCT movement_id
FROM stop
WHERE order_id = #order_id)
AND id <> #movement_id
END
I have never created a SQL Server trigger before. I'm not sure if this will work or if I need to do something more. Do I need to create a trigger that calls a stored procedure? Or will the above work?
Thanks for any help!