How to sum multiple rows on trigger update? - sql

I wrote a trigger on update on table [CART] to count and insert value to other table [HEADERS] to column [SUM]. It works but only for 1 row where [CART].[NUMBER] = [HEADERS].[NUMBER]. Column [NUMBER] in [CART] is not unique and i want to count all values from [CART] where [NUMBER] is identical. It means [AMOUNT]*[PRICE] for each row with same number, add this and insert into column [HEADERS].[SUM]
Here is what i got:
CREATE TRIGGER [dbo].[sum] ON [dbo].[CART] AFTER UPDATE AS
BEGIN
DECLARE #RESULT DECIMAL
DECLARE #AMOUNT FLOAT
DECLARE #PRICE FLOAT
DECLARE #NUMBER FLOAT
SET NOCOUNT ON;
IF UPDATE([NUMBER]) or UPDATE([AMOUNT]) or UPDATE([STATUS])
BEGIN
SELECT #AMOUNT=[AMOUNT],#PRICE=[PRICE],#NUMBER=[NUMBER] FROM inserted
IF #NUMBER is not NULL
BEGIN
SELECT #RESULT=#AMOUNT * #PRICE
UPDATE HEADERS SET SUM=#RESULT WHERE NUMBER=#NUMBER
END
END
GO
I'm not really good at SQL and i cant find correct syntax for this task. Can you help me?

Your trigger code does not handle cases when multiple rows are updated.
CREATE TRIGGER [dbo].[sum] ON [dbo].[CART] AFTER UPDATE AS
BEGIN
SET NOCOUNT ON;
IF UPDATE([NUMBER]) or UPDATE([AMOUNT]) or UPDATE([STATUS])
BEGIN
UPDATE H
SET [SUM] = I.AMOUNT * I.PRICE
FROM inserted I
INNER JOIN HEADER H ON I.NUMBER = H.NUMBER
END
GO

Related

SQL I want to have a piece deducted from the stock, and in the event that a piece is retrieved it is added to the store

I am using this SQL code but it works on the discount only. I want to make it in the event that a positive value is entered in the sales table, it is deducted from the inventory table, and in the case of entering a negative value, it increases in the inventory table
CREATE TRIGGER [dbo].[TryCutStock_By_Insert]
ON [dbo].[SaleDetail]
FOR INSERT
AS
DECLARE #StockQty AS varchar(10)
DECLARE #SaleQty AS varchar(10)
DECLARE #ProID AS varchar(50)
DECLARE #Result AS varchar(50)
SELECT #ProID = i.Code FROM inserted i;
SELECT #StockQty = ItemCard.Qty
FROM ItemCard
WHERE ItemCard.Code = #ProID;
SELECT #SaleQty = i.Qty FROM inserted i;
SELECT
#Result = CONVERT (int, #StockQty) - CONVERT(int, #SaleQty);
BEGIN
UPDATE ItemCard
SET Qty = #Result
WHERE Code = #ProID;
END
PRINT ''
Few things.
Don't use VARCHAR datatype for storing integers. Use right datatype.
As suggested by #Mitch-wheat, design the trigger to be batch aware
Don't have PRINT statement in the trigger
begin
update ic
set Qty= CONVERT (int,ic.Qty) - CONVERT(int,i.Qty)
FROM ItemCard AS ic
INNER JOIN inserted as i
ON i.Code = ic.Code
end

Alternative to Iteration for INSERT SELECT UPDATE in a sequence

I have a table with around 17k unique rows for which I need to run these set of statements in sequence
INSERT INTO TABLE1 using MASTERTABLE data (MASTERTABLE have 6 column)
SELECT value of column ID (Primary Key) of newly inserted row from TABLE1
Update that ID value in TABLE2 using a Stored Procedure
I have tried:
while loop: took around 3 hours to complete the execution
cursor: cancelled the query after executing it overnight
In my understanding I can not use JOIN as I need to execute the statements in a sequence
The questions is not detailed enough. The general idea I would like to use something like this
-- create a output table to hold new id, and key columns to join later
DECLARE #OutputTbl TABLE (ID INT, key_Columns in MASTERTABLE)
INSERT INTO TABLE1
OUTPUT INSERTED.ID, MASTERTABLE.key_columns INTO #OutputTbl
SELECT *
FROM MASTERTABLE
UPDATE T2
SET ID = o.ID
FROM TABLE2 t2
INNER JOIN OutputTbl o
ON t2.key_column = o.key_column
Maybe you can consider a TRIGGER on TABLE1 from which to call the stored procedure on TABLE2, and then you can call your INSERT as you wish/need.. one by one or in blocks..
DROP TRIGGER TR_UPD_TABLE2
GO
CREATE TRIGGER TR_UPD_TABLE2 ON TABLE1 AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE #columnID INT = NULL
IF (SELECT COUNT(*) FROM INSERTED)=1 BEGIN
-- SINGLE INSERT
SET #columnID = (SELECT columnID FROM INSERTED)
EXEC TableTwoUpdateProcedure #columnID
END ELSE BEGIN
-- MASSIVE INSERT (IF NEEDED)
SET #columnID = 0
WHILE #columnID IS NOT NULL BEGIN
SET #columnID = (SELECT MIN(columnID) FROM INSERTED WHERE columnID > #columnID)
IF #columnID IS NOT NULL BEGIN
EXEC TableTwoUpdateProcedure #columnID
END
END
END
END

SQL Server 2012: correct trigger does not fire after insert

I have 2 triggers for 2 tables. Both create numbers, one creates an articlenumber, the other an ordernumber.
Articlenumber:
ALTER TRIGGER [dbo].[trg_CreateArtikelnummer]
ON [dbo].[tblArtikel]
AFTER INSERT
AS
IF ((SELECT TRIGGER_NESTLEVEL()) < 2)
BEGIN
DECLARE #ArtikelID INT;
DECLARE #LfID INT; --supplierID
DECLARE #ProdID INT
-- ---Wein, Traubensaft, Sekt
SET #ArtikelID = (SELECT
CASE WHEN Artikelart = 'Wein' THEN 1
WHEN Artikelart = 'Traubensaft' THEN 2
WHEN Artikelart = 'Sekt' THEN 3
END AS ArtikelID
FROM inserted)
SET #LfID = (SELECT Lfid FROM inserted)
SET #ProdID = (SELECT ProdID FROM inserted)
SET #Prodid = (SELECT COUNT(ProdID)
FROM [dbo].[tblArtikel]
WHERE Lfid = #LfID)
UPDATE dbo.tblArtikel
SET Artikelnummer = CONVERT(INT, CONVERT(NCHAR(1), #ArtikelID) +
CONVERT(NCHAR(3), FORMAT(#LfID, '000')) + CONVERT(NCHAR(4), FORMAT(#ProdID,'0000')))
FROM inserted
INNER JOIN dbo.tblArtikel ON inserted.prodid = dbo.tblArtikel.prodid
This one fires IMMEDIATELY when inserting date in the table by hand (for test purpose) and displays the generated articlenumber instantely.
Ordernumber: should be build from the running number per year for each supplier, so 1703001 stands for year 2017, supplierID 03, ordernumber 001
ALTER TRIGGER [dbo].[trg_CreateBestellnummer]
ON [dbo].[tblOrders]
AFTER INSERT
AS
IF ((SELECT TRIGGER_NESTLEVEL()) < 2)
BEGIN
--set nocount on;
declare #Jahr int
declare #LfID int --supplierID
declare #OrderID int
declare #Order int
--declare #Bestelldatum date
set #Jahr=(select right(year(getdate()),2))
set #LfID=(SELECT Lfid from inserted)
--SELECT #OrderID=INSERTED.OrderID from inserted
set #Order=(SELECT count(OrderID) from [dbo].[tblOrders] where Lfid=#LfID and year(Bestelldatum)=Year(Getdate()))
Update dbo.tblOrders set Bestellnummer=convert(int,convert(nchar(2),#Jahr)+convert(nchar(2),FORMAT(#LfID, '00'))+convert(nchar(3),format(#Order,'000')))
from INSERTED inner join dbo.tblOrders on INSERTED.OrderID= dbo.tblOrders.OrderID
This one does NOT fire at once, when finishing inserting date into the table and does NOT display the generated ordernumber.
I get a red exclamation mark on the left side of the records saying something like "data are write protected. Execute query again".
When I click the execute button on the menue the the trigger fires and updates the correct ordernumber.
What can be the reason?
Thanks
Michael

Can I put an INSERT inside an INSTEAD OF INSERT trigger in SQL Server?

I'm having a some troubles with a complicated query, that required me to insert something in a table, but if I found that two columns are the same I should stop the transaction with a trigger. I make some code to do that, but I'm not sure 100% of it even when it works fine now.
alter trigger TR1
on Passer instead of insert
as
begin
declare #A int
declare #B int
declare #C int
set #A = (select code_ligne from inserted)
set #B = (select ordre_passage from inserted)
set #C = (select code_ville from inserted)
select * from passer
where code_ligne = #A
and ordre_passage = #B
if(##rowcount = 0 )
begin
insert into Passer values(#A,#C,#B)
print 'okay'
print ##rowcount
end
end
When you have scalar variables like this in a trigger you are going to run into problems. If you have two rows inserted at once you will only get 1 row inserted into Passer. You don't need these variables at all. Just switch this around to be a single set based insert statement. Something along these lines.
alter trigger TR1 on Passer instead of insert as
begin
insert into Passer
(
code_ligne
, ordre_passage
, code_ville
)
select i.code_ligne
, i.ordre_passage
, i.code_ville
from inserted i
join Passer p on p.code_ligne = i.code_ligne
and p.ordre_passage = i.ordre_passage
if(##rowcount = 0 ) begin
print 'okay'
print ##rowcount
end
end

Trigger to update sum of columns?

I know this is not a way to do it but it's a interview question
to update total = marks1 + marks2 + marks3 using a trigger.
I wrote something like this but it's not updating after an insert statement.
CREATE table marks
(
marks1 int,
marks2 int,
marks3 int,
total int
)
SELECT * from marks m
insert into marks values(10,10,20,0)
drop TRIGGER total_marks
create TRIGGER total_marks ON marks
AFTER INSERT
AS
begin
SET NOCOUNT ON
DECLARE #marks1 as int
select #marks1 = inserted.marks1 FROM inserted
DECLARE #marks2 as int
select #marks1 = inserted.marks2 FROM inserted
DECLARE #marks3 as int
select #marks1 = inserted.marks3 FROM inserted
DECLARE #result as int
set #result = #marks1 + #marks2 + #marks3
update marks
set total = #result
SET NOCOUNT OFF
end
Your trigger doesn't handle multiple row inserts, updates all rows to the same value (rather than just the row(s) inserted), and is far more complex than necessary anyway. Where is your key?
CREATE TRIGGER dbo.total_marks
ON dbo.marks
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE m
SET total = i.marks1 + i.marks2 + i.marks3
FROM dbo.marks AS m
INNER JOIN inserted AS i
ON m.key = i.key;
END
GO
If your table really doesn't have a key (it doesn't make a whole lot of sense to me), then you can say this, but it may update rows that were already updated:
ON m.marks1 = i.marks1 AND m.marks2 = i.marks2 AND m.marks3 = i.marks3
WHERE m.total = 0;