Creating SQL trigger that only affects specific row - sql

I have two tables created inventory and customer_sales. Individuals working in the warehouse can't have access to the customer_sales table.
So I added an additional field to inventory table called num_sales.
I want to create a trigger functions that whenever a new customer sale is added. It will correspond to the specific inventory_item that was sold's row and not the entire table.
This is what I have so far.
ALTER TABLE inventory
ADD num_sales INT
UPDATE movies SET num_sales = 0;
ALTER TABLE movies ALTER COLUMN num_rentals INT NOT NULL;
GO
CREATE TRIGGER tr_movies_num_rentals_add
ON customer_sales FOR INSERT
AS
BEGIN
UPDATE inventory
SET num_sales = num_sales + (SELECT sale_status_code FROM INSERTED)
WHERE 1 = (SELECT sale_status_code FROM INSERTED);
END;
Note:
sale_status_code values: 1=sold, 2=reserved, 3=lost.
UPDATE: I am using Microsoft SQL server management studio. I am newbie and this is a question I have for school.

First assume inserted willhave multiple rows. SQL server triggers do not operate row by row. YOu need to join to inserted not use a subquery. Next if you want this to happen on insert, update and delete, then you need to use more than an INSert trigger. And the delete trigger should use a different formula than inserted and updated becasue you will be subtracting the value from the deleted table from the inventory total.

Related

Trigger for update base on parent table condition

Hi I use SQL SERVER 2012 and I have two table named tbcustomer and tbcustomerdetail. Both tables have column customerID.
I manage only tbcustomerdetail. If I update tbcustomerdetail where customerID='001' then I need the trigger to update tbcustomer where customerID='001'
I try this but not found spelling.
CREATE TRIGGER Deletecustomer
ON tbcustomerdetail
FOR UPDATE
AS
BEGIN
update tbcustomer tbcustomer.status=0 where tbcustomer.customerID=updated.customerID;
END
//updated.customerID is the ID on column tbcustomerdetail where customerID is '001'.
I also tried AFTER UPDATE but it doesn't work.
Updated does not exist, in a trigger you have two views Deleted which contains previous data and Inserted contains the new one
As I mentioned they are views, and contains data for all the rows affected by the statement, so, you need to use them in a join
CREATE TRIGGER Deletecustomer
ON tbcustomerdetail
FOR UPDATE
AS
BEGIN
UPDATE C
SET Status = 0
FROM tbCustomer C
JOIN Inserted I ON C.CustomerID = I.CustomerID
END

Trigger: How does the inserted table work? How to access its rows?

I have the following table
Data --Table name
ID -- Identity column
PCode -- Postal Code
I created the following trigger:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * from inserted
END
And inserted the following values
INSERT INTO Data VALUES (125)
INSERT INTO Data VALUES (126)
INSERT INTO Data VALUES (127)
It shows this:
But I was expecting something like this:
After the 1st insertion, the trigger is executed -> one row is shown in the inserted table.
After the 2nd insertion, the trigger is executed -> two rows are shown in the inserted table.
After the 3rd insertion, the trigger is executed -> three rows are shown in the inserted table.
According to msdn.microsoft all the rows inserted are in this table.
How can I access the inserted table so that I can see all the expected rows and not separately?
You can not. From the Use the inserted and deleted Tables article on microsoft.com, you can read:
The inserted table stores copies of the affected rows during INSERT and UPDATE statements.
That means that the inserted table will only contain rows for the current INSERT or UPDATE statement.
If you do want to see all rows for several such INSERT or UPDATE statements, you will have to store these rows in a table you created yourself.
There are 2 table available in a trigger, the inserted and the deleted. Each update on table XXX is actually a delete row X from XXX then an insert of row X in table XXX. So the inserted inside the trigger is a copy of what got inserted. You can do a lot with a trigger, but triggers are dangerous.
For example, on a performance gig, I found a huge SP being run by a trigger, we dropped it and the database came back online. Or another example, if you do a trigger wrong to audit logins, you can down the server.
As TT mentioned, if you want to see all the inserted records then you need to change your Trigger to something like this:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * into "tablename"
from
(Select * from inserted) Ins
END

Update a table when an specific column of another table is updated using trigger in SQL Server

I am using this trigger:
create trigger UpdateCustomerOnWholeSellerIdChange
on Invoice after update
as
begin
set nocount on;
if update(WholeSellerId)
begin
update Customer
set Customer.WholeSellerId = d.WholeSellerId
from deleted d
where d.CustomerId = Customer.CustomerId
end
end
What I am trying to accomplish is: each CustomerId has his own WholeSellerId meaning each Customer has their own salesman. In the Invoice table, each Invoice has its own CustomerId and WholeSellerId.
So when I update the WholeSellerId in the Invoice table, I would like to update the WholeSellerId of the Customer table as well to the WholeSellerId of the Invoice table.
With my code above, even when I update my WholeSellerId in the Invoice table, it doesn't update the Customer's WholeSellerId.
Your help is appreciated.
You are using deleted table as source, which contain data BEFORE your update run. Replace it with inserted table which have the new data.
MSDN - Use the inserted and deleted Tables

Sql Trigger After Insert Update another table with conditions

I am creating After Insert trigger , its working fine, but I have certain conditions before executing the statements inside the trigger
Based on Different CustomerId Run the trigger, I want check which CustomerId got inserted in my LoyaltyDetailsTable, say if last insert
was Customerid=2 then pass that Customerid in where condition then run
the trigger , or if Customerid = 1 then run the trigger for that Id,
so on.
I want to check whether in PriceClaimTable the inserted CustomerId exist or not, If exists then update the details else just insert the
values in LoyaltyDetailsTable only.
Trigger query
CREATE TRIGGER DetailsAfterInsert ON [dbo].[LoyaltyDetailsTable]
FOR INSERT
as
UPDATE PriceClaimTable
SET CurrentPoints =
(
(SELECT SUM(LoayaltyPointsTable.Points) AS RecentPoints FROM LoayaltyPointsTable
join LoyaltyDetailsTable ON LoayaltyPointsTable.LoyaltyPointsId
= LoyaltyDetailsTable.LoyaltyPointsId
WHERE CustomerId=1 and LoyaltyDetailsId= (SELECT MAX(LoyaltyDetailsId)
AS LoyaltyDetailsTable FROM LoyaltyDetailsTable))
+
(SELECT CurrentPoints FROM PriceClaimTable WHERE ClaimCustomerId=1 and
PriceClaimId=(SELECT max(PriceClaimId) FROM PriceClaimTable
))
)
WHERE ClaimCustomerId=1 and PriceClaimId=(SELECT max(PriceClaimId) FROM PriceClaimTable)
This is my first attempt to write a trigger, and here is table structure.
Any help would be great.
What you're looking for here is the inserted table. Every time you issue an UPDATE statement, SQL Server generates two virtual tables called inserted and deleted that store information on the data modifications you're making. These tables are accessible from your trigger. For more information, see here: https://msdn.microsoft.com/en-us/library/ms191300.aspx
You can use inserted to get the IDs you're looking for. So, instead of:
WHERE ClaimCustomerId=1
you can use:
WHERE ClaimCustomerId=inserted.ClaimCustomerId

After insert trigger for updating a column

I am writing an after insert trigger trying to find a solution to this problem here:
https://stackoverflow.com/questions/19355644/dead-ends-all-around-trying-to-update-geography-column
What I am unsure of is how to write the trigger to take into consideration multiple records as explained here as a potential you need to code for.
So far I had this but it applies only to a single record so if the table had 100 records inserted in a batch 99 would not be updated. This is my understanding so far and may not be correct.
create trigger tri_inserts on [dbo].[Address]
after insert
as
set nocount on
update Address
SET AddyGeoCode = GEOGRAPHY::Point(inserted.AddyLat, inserted.Addylong, 4326)
GO
Would I say join to the inserted table to discover / update all the new records?
In case it is needed my Address table schema is AddyLat & AddyLong decimal(7,4) and AddyGeoCode Geography.
TIA
Yes, you need to join on inserted table.
UPDATE a
SET a.AddyGeoCode = GEOGRAPHY::Point(a.AddyLat, a.Addylong, 4326) --you can use AddyLat&Long from either a or i
FROM Address a
INNER JOIN inserted i ON a.id = i.id --whatever are your PK columns