Trigger to insert multiple record - sql-server

I'm trying to create a trigger to insert all the value that I delete from a table in a "Backup" table,
Ex:
Table 1: NomePilota, ModelloVettura, NomeScuderia
BackupTable1 (Table 2): NomePilota, ModelloVettura, NomeScuderia
What I want from the trigger to do: Insert into 'Table 2' deleted values from table 1.
I tried like this:
CREATE TRIGGER Backup ON dbo.Table1 AFTER (i can only use after) DELETE AS
BEGIN
DECLARE #Pilota VARCHAR(20) = (SELECT NomePilota FROM deleted)
DECLARE #Vettura VARCHAR(50) = (SELECT ModelloVettura FROM deleted)
DECLARE #Scuderia VARCHAR(20) = (SELECT NomeScuderia FROM deleted)
INSERT INTO Table2 (NomePilota, ModelloVettura, NomeScuderia) VALUES (#Pilota, #Vettura, #Scuderia)
But it send a error:
Cannot insert multiple records in #Pilota, #Vet, #Scud
How can I fix that? Does the deleted table already have a default ID column to use like in a for? Can I use something like vectors? (like #Nome[] = SELECT * FROM Tabella, Insert into Tabella2 (Nome) VALUES #Nome[#Numero (numero is like the record number of nome]).

Why not make life simple?
INSERT INTO Table2 (NomePilota, ModelloVettura, NomeScuderia)
SELECT NomePilota, ModelloVettura, NomeScuderia FROM deleted
The insert statment can work on the results of a select -- here we leverage this to simplify the task at hand.

Related

How can i get updated identies from mssql table?

I'm trying to track the updated rows in my database by saving them in another table. I have a code like this:
"UPDATE Table1 SET [HastaSN] = #HastaSN WHERE Id = #Id; INSERT INTO Changes ([TableName],[Ids]) VALUES ('Table1 ', (SELECT IDENT_CURRENT('[Table1 ]')))"
I always get a table when I try to update a few rows in my database :
TableName Ids
Table1 56697
Table1 56697
Table1 56697
It's just showing me the last ID of the table. Not every ID number. How do I fix this problem?
The OUTPUT clause should work for you. Here's an example of using it.
DROP TABLE IF EXISTS #t;
CREATE TABLE #t
(
ID INT NOT NULL IDENTITY(1,1),
SomeText VARCHAR(100)
);
DROP TABLE IF EXISTS #IDTable;
CREATE TABLE #IDTable (ID INT);
INSERT INTO #t (SomeText)
VALUES ('Hello'),
('World');
UPDATE #t
SET SomeText = 'World!'
OUTPUT Inserted.ID
INTO #IDTable
WHERE ID = 2;
SELECT ID FROM #IDTable;
In your example it might look something like this:
UPDATE Table1
SET [HastaSN] = #HastaSN
OUTPUT 'Table1', Inserted.Id
INTO Changes
WHERE Id = #Id

How to access inserted and deleted logical tables with a stored procedure

Is there a way to access inserted and deleted tables using a stored procedure or a function WITHOUT using or passing values from a trigger.
Ex:
INSERT INTO dbo.Table (ID)
VALUES (1)
SELECT * FROM inserted -> This raises an error
Is there a way to do something like this in order to capture the inserted value?
I was able to do this to a query which uses the MERGE command as below.
MERGE Products AS TARGET
USING UpdatedProducts AS SOURCE ON (TARGET.ProductID = SOURCE.ProductID)
WHEN MATCHED AND TARGET.ProductName <> SOURCE.ProductName
OR TARGET.Rate <> SOURCE.Rate
THEN
UPDATE SET TARGET.ProductName = SOURCE.ProductName,
TARGET.Rate = SOURCE.Rate
WHEN NOT MATCHED BY TARGET
THEN
INSERT (ProductID, ProductName, Rate)
VALUES (SOURCE.ProductID, SOURCE.ProductName, SOURCE.Rate)
WHEN NOT MATCHED BY SOURCE
THEN
DELETE
OUTPUT
$action,
DELETED.ProductID AS TargetProductID,
DELETED.ProductName AS TargetProductName,
DELETED.Rate AS TargetRate,
INSERTED.ProductID AS SourceProductID,
INSERTED.ProductName AS SourceProductName,
INSERTED.Rate AS SourceRate;
Is there a way to access inserted and deleted tables for simple SQL queries?
You can use the inserted and deleted tables only in triggers or in the output clause of DML statements.
In an insert statement, the output clause can reference the inserted table:
DECLARE #Ids AS TABLE (id int);
INSERT INTO dbo.Table (ID)
OUTPUT Inserted.ID INTO #Ids(id)
VALUES (1), (2), (3);
In an update statement, you can reference both the inserted table and the deleted table:
DECLARE #Ids AS TABLE (oldId int, newId int);
UPDATE dbo.Table
SET ID = 1
OUTPUT Deleted.ID, Inserted.ID INTO #Ids(oldId, newId);
And in a delete statement, you can reference the deleted table:
DECLARE #Ids AS TABLE (id int);
DELETE dbo.Table
OUTPUT Inserted.ID INTO #Ids(id)
FROM dbo.Table
WHERE ID IN (1, 2, 3);
A Merge statement is unique since you have access to both the source table and the inserted/deleted tables in it's output clause, as demonstrated on this post.

Creating a temporary table within a TRIGGER with GROUP BY

I need to create and use a temporary table with GROUP BY clause within a trigger, but I'm having difficulties doing so.
My attempt:
Here I'm trying to use two temporary tables which are dropped after the trigger reach an end.
First I create a #Temptable and the trigger.
CREATE TABLE #TempTable (admID smallint, diagID smallint);
CREATE TRIGGER tr_newTest
ON Adm_Diag
FOR INSERT
AS
BEGIN
...
END
Since the table inserted only contains rows for a current INSERT and UPDATE statements I'm passing several INSERT and UPDATE statements to #TempTable.
DECLARE #admID smallint
SELECT #admID = Adm_ID
FROM inserted
DECLARE #diagID smallint
SELECT #diagID=Diag_ID
FROM inserted
INSERT INTO #TempTable VALUES (#admID, #diagID)
Now with this data I want to create a temporary table that groups the rows of #TempTable:
SELECT *
INTO #TempGroupTable
FROM
(
SELECT admID, COUNT(*) as Diag
FROM #TempTable
GROUP BY admID
) t1
WHERE Diag > 2
The whole script
CREATE TABLE #TempTable (admID smallint, diagID smallint);
CREATE TRIGGER tr_newTest
ON Adm_Diag
FOR INSERT
AS
BEGIN
DECLARE #admID smallint
SELECT #admID = Adm_ID
FROM inserted
DECLARE #diagID smallint
SELECT #diagID=Diag_ID
FROM inserted
INSERT INTO #TempTable VALUES (#admID, #diagID)
-- Below I'm tring to create #TempGroupTable
SELECT *
INTO #TempGroupTable
FROM
(
SELECT admID, COUNT(*) as Diag
FROM #TempTable
GROUP BY admID
) t1
WHERE Diag > 2
END
After executing the trigger I get an error:
Msg 208, Level 16, State 0, Line 41 Invalid object name
'#TempGroupTable'.
How can I create #TempGroupTable?
Not quote sure what you are trying to do but would a global temporary tables which starts with ## work for you? So make the #TempGroupTable into ##TempGroupTable?
Why not dispense with all the overhead of temp tables and variables? Try:
CREATE TRIGGER tr_newTest
ON Adm_Diag
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO Adm_Diag (adminID, Diag)
SELECT admID, COUNT(*) as Diag
FROM inserted
GROUP BY admID
END

Trying to create a trigger for a table

I have a table [dbo].[main] composed of 4 columns:
MovieGenre
MusicGenre
PodcastGenre
CombinedColumn
I want to create a trigger where if anything is inserted in MovieGenre, PodcastGenre, MusicGenre that it also gets inserted into CombinedColumn.
CREATE TRIGGER trgAfterInsert ON [dbo].[Main]
FOR INSERT
AS
???
GO
--dbo.main` needs a key column (let's say its a identity column 'id1')
CREATE TRIGGER trgAfterInsert
ON [dbo].[Main]
FOR INSERT AS
declare #allcols varchar(500)
declare #key1 int
set #key1 = ident_current('dbo.main')
select #allcols = MovieGenre+' '+ PodcastGenre+' '+ MusicGenre from inserted
update dbo.main set CombindedColumn= #allcols where id1 = #key1
Okay, this will add values to Combined Column one after another. "Stacking" them as you want:
CREATE TRIGGER trgAfterInsert on dbo.main
AFTER INSERT
AS
INSERT INTO yourTable(CombinedColumn)
SELECT MovieGenre
FROM inserted
UNION ALL
SELECT PodcastGenre
FROM inserted
UNION ALL
SELECT MusicGenre
FROM inserted
GO

Merge statement on a single record table

I need to write a single statement to insert or update a record in a single record table
the merge statement allows me to write this:
create table t1 (n int)
-- insert into t1 (n) Values (1); -- uncomment to test the matched branch
MERGE t1 AS P
USING (SELECT 3 AS n) AS S
ON 1 = 1
WHEN MATCHED THEN
UPDATE SET n = S.n
WHEN NOT MATCHED THEN
INSERT (n)
VALUES (S.n);
select * from t1
this work, but I think that the 1=1 condition purpose is not very easy to understand.
Is there a different syntax to insert a record when the table is empty or update the record when it does already exist?
The other option would be to do it the old fashioned way.
if exists (select null from t1)
update t1 set n = 3
else
insert into t1 (n) values (3)
Replace
ON 1 = 1
with
ON S.n = P.n
Example of recent procedure I wrote to either update an existing row or insert a new row.
Table has the same structure as MembershipEmailFormat the table variable.
Found it easiest to create a table variable to be the source in the Using clause. I realize that the main purpose of Merge statements really are merging muliple rows between two tables. My use case is that I need to insert a new email address for a user or modify and existing email address.
CREATE PROCEDURE [dbo].[usp_user_merge_emailformat]
#UserID UNIQUEIDENTIFIER,
#Email varchar(256),
#UseHTML bit
AS
BEGIN
--SELECT #UserID='04EFF187-AEAC-408E-9FA8-284B31890FBD',
-- #Email='person#xxxx.com',
-- #UseHTML=0
DECLARE #temp TABLE
(
UserID UNIQUEIDENTIFIER,
Email varchar(256),
HtmlFormat bit
)
INSERT INTO #temp(UserID,Email, HtmlFormat)
Values(#UserID,#Email,#UseHTML)
SELECT * FROM #temp
MERGE dbo.MembershipEmailFormat as t
USING #temp AS s
ON (t.UserID = s.UserID and t.Email = s.Email)
WHEN MATCHED THEN UPDATE SET t.HtmlFormat = s.HtmlFormat
WHEN NOT MATCHED THEN INSERT VALUES(s.UserID,s.Email,s.HtmlFormat);
END

Resources