Trigger in SQL causing error "Product_Reorder is not a recognized SET option" - sql

CREATE OR ALTER TRIGGER CheckQuantity
ON dbo.Products
AFTER UPDATE
AS
BEGIN
UPDATE dbo.Products
SET Product_ReOrder = 1
FROM Inserted i
WHERE i.Product_ID = dbo.Products.Product_ID
AND i.Product_QOH < 5;
I am not getting a syntax error
syntax error near ;
This is referring to the ; at the end of the code.

Not 100% sure what you're trying to do - you're not giving us much to go on, either!
I'm assuming you mean you want to set a column called Product_ReOrder in your table to 1 if another column Product_QOH is less than 5 - correct?
In that case - use a trigger something like this:
CREATE OR ALTER TRIGGER CheckQuantity
ON dbo.Products
AFTER UPDATE
AS
BEGIN
UPDATE dbo.Products
SET Product_ReOrder = 1
FROM Inserted i
WHERE i.PrimaryKeyColumn = dbo.Products.PrimaryKeyColumn
AND i.Product_QOH < 5;
END
The trigger will fire after an UPDATE, and Inserted will contain all rows (can and will be multiple rows!) that have been updated - so I'm assuming you want to check the quantity on those rows.
I'm joining the base table (dbo.Products) to the Inserted pseudo table on the primary key column of your table (which we don't know what it is - so you need to adapt this as needed), and I'm setting the Product_ReOrder column to 1, if the Products_QOH value is less than 5.
Your line of code
Select #QOH = (select Product_QOH from inserted)
has a fatal flaw of assuming that only one row was updated - this might be the case sometimes - but you cannot rely on that! Your trigger must be capable of handling multiple rows being updated - because the trigger is called only once, even if 10 rows are updated with a command - and then Inserted will contain all those 10 updated rows. Doing such a select is dangerous - you'll get one arbitrary row, and you'll ignore all the rest of them ....
Is that what you're looking for?

I'm unclear what you were thinking when you wrote this code, or what template you were basing off, but there are many syntax errors.
It seems you probably want something like this:
The update() function only tells us if that column was present in the update statement, not if anything was actually changed.
We need to check if we are being called recursively, in order to bail out.
We also check if no rows have been changed at all, and bail out early
Note how inserted and deleted are compared to see if any rows actually changed. This also deals correctly with multiple rows.
We then need to rejoin Products in order to update it.
create or alter trigger CheckQuantity
on Products
after update
as
set nocount on;
if not(update(Products_QOH))
or TRIGGER_NESTLEVEL(##PROCID, 'AFTER', 'DML') > 1
or not exists (select 1 from inserted)
return; -- early bail-out
update p
set Product_ReOrder = 1
from Products p
join (
select i.YourPrimaryKey, i.Products_QOH
from inserted i
where i.Product_QOH < 5
except
select d.YourPrimaryKey, d.Products_QOH
from deleted d
) i on i.YourPrimaryKey = p.YourPrimaryKey;
However, I don't understand why you are using a trigger at all.
I strongly suggest you use a computed column for this instead:
ALTER TABLE Products
DROP COLUMN Product_ReOrder;
ALTER TABLE Products
ADD Product_ReOrder AS (CASE WHEN Product_QOH < 5 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END);

Related

How do I correctly update values with a trigger?

I have a Products table with columns QtySold_Day and QtySold_Yesterday, which contain information about the quantity of sold products today and yesterday respectively.
I want to create a trigger that moves every single value from the QtySold_Day column to the QtySold_Yesterday whenever there's an attempt to update the QtySold_Day column.
This is what I already have:
create or alter trigger UpdateQuantity
on Products
instead of update
as
declare #x int
set nocount on
while (#x < ##ROWCOUNT)
begin
update Products
set QtySold_Day = QtySold_Yesterday
where (ProductID = #x)
end
I'd like to know how can I finish the trigger for it to work as intended.
SQL is a set based language, so you should always attempt set based operations. Inside a trigger you have access to a pseudo table called Inserted which has the new details of the update. You can therefore update all the relevant records in one go.
As commented you are probably going to need a way to avoid copying the values over if the record is updated multiple times - so I have added a check to ensure it only happens once. That might not be quite the behaviour you want so if you clarify we can tweak it.
Do you really want an INSTEAD OF trigger? Because that will capture ALL updates to this table, and for the most part do nothing.
UPDATE Products SET
QtySold_Day = QtySold_Yesterday
WHERE ProductID IN (SELECT ID FROM Inserted)
-- Only update once
AND QtySold_Yesterday IS NULL;

how to execute trigger when only one column changes

I have the following trigger, and I need that its only executed when one column value changes, is that possible?
ALTER TRIGGER [dbo].[TR_HISTORICO]
ON [dbo].[Tbl_Contactos]
AFTER UPDATE
AS
BEGIN
IF UPDATE (primerNombre) -- sólo si actualiza PRIMER NOMBRE
BEGIN
INSERT INTO [dbo].[Tbl_Historico] ([fecha],[idUsuario],[valorNuevo], [idContacto],[tipoHistorico] )
SELECT getdate(), 1, [dbo].[Encrypt]([dbo].[Decrypt](primerNombre)), [idContacto], 1
FROM INSERTED
END
END
The problem is the code is executed always even if another column changes
The problem is probably the way you are doing updates in your code. It may be updating every field and not only the one that changed.
In this case you need to check to see if there is a difference between the values in the inserted and deleted pseudo tables. Or fix your code so that it only updates what needs to be updated.
Comparing the value of primerNombre from the inserted and deleted tables
ALTER TRIGGER [dbo].[TR_HISTORICO] ON [dbo].[Tbl_Contactos]
AFTER UPDATE AS
BEGIN
INSERT INTO [dbo].[Tbl_Historico] ([fecha],[idUsuario],[valorNuevo], [idContacto],[tipoHistorico] )
SELECT getdate(), 1, [dbo].[Encrypt]([dbo].[Decrypt](i.primerNombre)), i.[idContacto], 1
FROM INSERTED i
inner join deleted d
on i.idContacto = d.idContacto
where i.primerNombre <> d.primerNombre
END
If primerNombre is nullable, the where will need to handle null comparisons as well.

Create a trigger that updates a column in a table when a different column in the same table is updated - SQL

How to create a trigger that updates a column in a table when a different column in the same table is updated.
So far I have done the following which works when any new data is created. Its able to copy data from "Purchase Requisition" to "PO_Number" however when data has been modified in "Purchase Requisition" , no changes is made to "PO_Number" and the value becomes NULL. Any kind help will be seriously appreciated.
ALTER TRIGGER [dbo].[PO_Number_Trigger]
ON [dbo].[TheCat2]
AFTER INSERT
AS BEGIN
UPDATE dbo.TheCat2 SET PO_Number=(select Purchase_Requisition from inserted) where DocNo= (Select DocNo from inserted);
END
You need to add 'UPDATE' as well as insert to the trigger, otherwise it will only execute on new data, not updated data. Also added 'top 1' to the select statements from the inserted table to allow this to be 'safe' on batch updates, however it will only update 1 record.
ALTER TRIGGER [dbo].[PO_Number_Trigger]
ON [dbo].[TheCat2]
AFTER INSERT, UPDATE
AS BEGIN
UPDATE dbo.TheCat2 SET PO_Number=(select top 1 Purchase_Requisition from inserted) where DocNo= (Select top 1 DocNo from inserted);
END
This might do what you want:
Your trigger is altering all rows in TheCat2. Presumably, you only want to alter the new ones:
ALTER TRIGGER [dbo].[PO_Number_Trigger]
ON [dbo].[TheCat2] AFTER INSERT
AS
BEGIN
UPDATE tc
SET PO_Number = Purchase_Requisition
FROM dbo.TheCat2 tc JOIN
inserted i
on tc.DocNo = i.DocNo ;
END;
However, perhaps a computed column is sufficient for your purposes:
alter table add PO_Number as Purchase_Requisition;

SQL Insert, Update Trigger - Can you update the inserted table?

I have an SQL Trigger FOR INSERT, UPDATE I created which basically does the following:
Gets a LineID (PrimaryID for the table) and RegionID From the Inserted table and stores this in INT variables.
It then does a check on joining tables to find what the RegionID should be and if the RegionID is not equal what it should be from the Inserted table, then it should update that record.
CREATE TRIGGER [dbo].[TestTrigger]
ON [dbo].[PurchaseOrderLine]
FOR INSERT, UPDATE
AS
-- Find RegionID and PurchaseOrderLineID
DECLARE #RegionID AS INT
DECLARE #PurchaseOrderLineID AS INT
SELECT #RegionID = RegionID, #PurchaseOrderLineID = PurchaseOrderLineID FROM Inserted
-- Find PurchaserRegionID (if any) for the Inserted Line
DECLARE #PurchaserRegionID AS INT
SELECT #PurchaserRegionID = PurchaserRegionID
FROM
(...
) UpdateRegionTable
WHERE UpdateRegionTable.PurchaseOrderLineID = #PurchaseOrderLineID
-- Check to see if the PurchaserRegionID has a value
IF #PurchaserRegionID IS NOT NULL
BEGIN
-- If PurchaserRegionID has a value, compare it with the current RegionID of the Inserted PurchaseOrderLine, and if not equal then update it
IF #PurchaserRegionID <> #RegionID
BEGIN
UPDATE PurchaseOrderLine
SET RegionID = #PurchaserRegionID
WHERE PurchaseOrderLineID = #PurchaseOrderLineID
END
END
The problem I have is that it is not updating the record and I'm guessing, it is because the record hasn't been inserted yet into the PurchaseOrderLine table and I'm doing an update on that. But can you update the row which will be inserted from the Inserted table?
The major problem with your trigger is that it's written in assumption that you always get only one row in INSERTED virtual table.
SQL Server triggers are statement-triggers not row-triggers. You have to take that fact into consideration.
Now if I understand correctly the logic behind this trigger then you need just one update statement in it
CREATE TRIGGER TestTrigger ON PurchaseOrderLine
FOR INSERT, UPDATE
AS
UPDATE l
SET RegionID = u.PurchaserRegionID
FROM PurchaseOrderLine l JOIN INSERTED i
ON l.PurchaseOrderLineID = i.PurchaseOrderLineID JOIN
(
SELECT PurchaseOrderLineID, PurchaserRegionID
FROM UpdateRegionTable -- !!! change this for your proper subquery
) u ON l.PurchaseOrderLineID = u.PurchaseOrderLineID
For this example I've created a fake table UpdateRegionTable. You have to change it to the proper query that returns PurchaseOrderLineID, PurchaserRegionID (in your code you replaced it with ...). Make sure that it returns all necessary rows, not one.
Here is SQLFiddle demo
I think the problem could be that you are making the update to PurchaceOrderLine inside the trigger that is monitoring updates to the same table as well. Try to alter the trigger to just monitor the inserts, than if this works, you can make some changes or break your trigger on two: one for inserts, another for updates.
This has been resolved. I resolved the problem by adding the trigger to another table as the IF #PurchaserRegionID IS NOT NULL was always false.

SQl trigger after insert issue

I am working on triggers using SQL server 2005. I have a trigger for a table which is after update. After declaring the variables, the code is like this.
if #isconfirmed_before = 0 and #isconfirmed_after = 1
begin
if #invite_userid <> ''
begin
select #points = points from dbo.InvitePoint where code = 'USR' and packageid = #packageid
INSERT INTO InviteCount
([userID]
,[joinMerchantID]
,[packageID]
,[points]
,[joinDate])
VALUES
(#invite_userid
,#merchantid
,#packageid
,#points
,getdate())
end
SET #alpha_numeric=''
SELECT #alpha_numeric=#alpha_numeric+CHAR(n) FROM
(
SELECT TOP 8 number AS n FROM master..spt_values
WHERE TYPE='p' and (number between 48 and 57 or number between 65 and 90)
ORDER BY NEWID()
) AS t
update merchant
set reg_code = #alpha_numeric
where merchantid = #merchantid
END
The last part of
update merchant
set reg_code = #alpha_numeric
where merchantid = #merchantid
This reg_code shoule be inserted only once when the row is inserted but it is changing every time there is an update to the table. How do i make it happen. Please help me, Thank you in advance!!
update merchant
set reg_code = #alpha_numeric
where merchantid = #merchantid
That code is executing every time there is an update, because you have no conditional flow preventing it from executing sometimes. If you want to only execute that given a certain condition, you'll need to wrap it in an IF block.
You say: "This reg_code shoule be inserted only once when the row is inserted but it is changing every time there is an update to the table." Why is that in an AFTER UPDATE trigger then? It looks like it should be in an AFTER INSERT trigger. Unless I am misunderstanding you.
OK you are very much in trouble with triggers. First you need to show the actual create trigger code. I suspect you don't have it set correctly to only fire on insert.
Next you need to assume that the trigger must be able to handle multiple record inserts. Anytime you are setting a value to a scalar variable in a trigger, you are probably doing something wrong. This can't be your whole trigger either because you haven't shown how you get the varible values.