SQL insert trigger for insert with update - sql

I have two tables:
[1] Donations - with amount and pet_id field
[2] Pets - with id and total donations field
I'm trying to create a trigger which will update total donations field whenever
a new row is being inserted to Donations table. I tried this one:
create trigger update_donations
on sponserships
for insert
as
update dbo.Pets
set tot_donations = (
select new_val = inserted.amount + pets.tot_donations
from inserted
where inserted.[Pet-ID] = pets.[Animal-ID]
)
But of course it changes all records, whereas i want to change only records that are changed in the donations table.

It is usually not a good practice to store this type of derived information - you could have a view that computes it on the fly rather than a trigger that keeps it up to date. Also please note that if you go that way, you also need a delete and an update trigger...
That said, you can use the following query in your insert trigger to update the relevant record in the pets table:
update p
set p.total_donations = p.total_donations + i.amount
from dbo.Pets p
inner join inserted i on i.[Pet-ID] = p.[Animal-ID]

Related

Create a record in table A and assign its id to table B

I have a set of companies and for each of them, I need to generate a UUID in another table.
companies table
detail_id (currently NULL for all companies)
details table
id
uuid
date
...
I'd like to update all companies with newly created detail like this:
UPDATE companies
SET details_id =
(
INSERT INTO details
(uuid, date)
VALUES (uuid_generate_v1(), now()::date)
RETURNING id
)
But that gives me a syntax error since I can't use INSERT INTO inside UPDATE.
What is a proper way to create a row in the details table and immediately set the newly created id in the companies table?
(I am using Postgres)
You can use a data-modifying CTE:
with new_rows as (
INSERT INTO details ("uuid", "date")
VALUES (uuid_generate_v1(), current_date)
RETURNING id
)
update companies
set details_id = new_rows.id
from new_rows

Add data to trigger from the last insert

I am faced with the following situation:
I created a trigger which reacts on insert to the third table. When I insert any data (for example 1 1 2), last number should be subtracted from the Amount of stock column from cell, which has necessary ID Product (as it's shown on picture). But how can I understand which row was the last added? I thought firstly to do it by select, but it seems impossible. And now I think that it's possible to do it with the help of cursor, but it doesn't seem as the best variant. Is there a better variant how can I do it?
Here's my code of trigger, but it only subtracts 1 from the 1st product each time, unfortunately:
CREATE TRIGGER AmountInsert ON Amount
AFTER INSERT
AS
BEGIN
UPDATE Product
SET Amount_On_Stock =
(SELECT Amount_On_Stock FROM Product
WHERE ID_Product = 1) - 1
WHERE ID_Product = 1
END
The first thing you need to understand is that in a trigger in SQL Server you are provided with an inserted pseudo-table and a deleted pseudo-table. You use these tables to determine what changes have occurred.
I think the following trigger accomplishes what you are looking for - the comments explain the logic.
CREATE TRIGGER dbo.AmountInsert ON dbo.Amount
AFTER INSERT
AS
BEGIN
set nocount on;
update P set
-- Adjust the stock level by the amount of the latest insert
Amount_On_Stock = coalesce(Amount_On_Stock) - I.Amount
from dbo.Product P
inner join (
-- We need to group by ID_Product in case the same product appears in the insert multiple times
select ID_Product, sum(Amount) Amount
from Inserted
group by ID_Product
-- No need to update is net change is zero
having sum(Amount) <> 0
) I
on I.ID_Product = P.ID_Product;
END

SQL After trigger update value that triggers update

I have 2 tables, shipment and invoice. I have an after trigger that updates the shipment table with the invoice number from the invoice table.The invoice table has their related shipment numbers, can be more than one for each invoice.
Create Trigger ShipmentInvoice
on Therefore.dbo.Invoice
For Insert
AS
Update cat set
invoice = Fac.invoice
FROM therefore.dbo.thecat10 cat
INNER JOIN therefore.dbo.vFacturaAlbaran alb
on alb.shipment COLLATE Modern_Spanish_CI_AS = alb.shipment
This Works but it updates the whole table every time. I need a way to update the shipment table only with the values that were recently added in the invoice table when the trigger is activated.
Edit
The trigger is over the invoice table. I am updating the shipment table with the invoice numbers from the invoice table.
This Works but it updates the whole table every time. I need a way to update the shipment table only with the values that were recently added in the invoice table when the trigger is activated.
That because you are joining both tables, you need to use INSERTED table to get only the inserted rows as :
Create Trigger ShipmentInvoice
on Therefore.dbo.Invoice
For Insert
AS
Update cat set
invoice = I.invoice
FROM therefore.dbo.thecat10 cat
INNER JOIN INSERTED I alb ON Cat.ID = I.ID
...
it seems odd that you are updating the table to you are already inserting into; why are you not resolving the correct value before hand? This is pseudo-sql, but will get you on the right path
CREATE TRIGGER ShipmentInvoice
ON Therefore.dbo.Invoice
FOR INSERT
AS
UPDATE cat
SET invoice = Fac.invoice --There is no table/alias Fac, where is this coming from? inserted?
FROM therefore.dbo.thecat10 cat
JOIN inserted i ON cat.{Primary/Foreign ID COLUMN} = i.{Primary/Foreign ID COLUMN}
INNER JOIN therefore.dbo.vFacturaAlbaran alb ON alb.shipment COLLATE Modern_Spanish_CI_AS = alb.shipment;
Note the items in the braces ({}) and also my comment about your object Fac.

How can I update and replicate one column from one table to another column from another table?

I need to replicate one column (TYPE) from one table (CUTOMER) to another column (UNDEF000) from table (ORDERS), by this way everytime when someone update column(TYPE) to be automaticaly replicated on (UNDEF000), Table CUSTOMER and ORDERS are linked by column (PRE_ORDERCODE).
First I try to fill UNDEF000 from TYPE:
UPDATE ORDERS
JOIN CUSTOMER
SET ORDERS.UNDEF000=CUSTOMER.TYPE
WHERE ORDERS.PRE_ORDERCODE= CUSTOMER.PRE_ORDERCODE;
not function :(
UPDATE ORDERS
SET ORDERS.UNDEF000= CUSTOMER.TYPE
FROM CUSTOMER CUSTOMER
INNER JOIN ORDERS ORDERS
ON CUSTOMER.PRE_ORDERCODE= ORDERS.PRE_ORDERCODE
Can you please help me with this two problems?
I think your update should be like:
UPDATE ORDERS O SET O.UNDEF000= (
SELECT CUSTOMER.TYPE FROM CUSTOMER
WHERE CUSTOMER.PRE_ORDERCODE = O.PRE_ORDERCODE);
Trigger code:
create or replace trigger after_update_customer after update on
customer for each row
declare
begin
update orders set UNDEF000 = :new.type
where pre_ordercode = :new.pre_ordercode;
end;

SQL: insert records is not in order

I am having a problem while a record is inserted into a table.
each parking_cost is inserted after its related record. It should be with its record. why is this happening?
Any ideas ?
Regards.
If you are doing two separate queries to populate the row in the table, the first query needs to be an INSERT, the second query needs to be an UPDATE, eg:
INSERT INTO Customers (Pre_Payed_Card, Parking_ID) VALUES ('1234', 1)
Then
UPDATE Customers SET Parking_Cost = <cost> WHERE Parking_ID = 1
An INSERT will always create a new row; two INSERT queries for the same logical entity will result in two separate rows like you have in the screenshot.
Update: re-reading that query, you're probably after something like
UPDATE Customers SET Parking_Cost = p.Parking_Cost
FROM Customers c INNER JOIN Parking p ON c.Parking_ID = p.Parking_ID
WHERE c.Parking_ID = 1