Internal Trigger to Obtain Newly Inserted Records - sql

I am trying to execute a query but am having trouble. To start I have Table A and Table B. Table A has the following columns (RowID, ItemNumber, CaseCount, Elc, TotalElc, TimeStamp). Table B has the following columns( RowID, ItemNumber, Elc, TotalElc)
I am using a dashboard to insert values into Table A. I am inserting integers into ItemNumber, and CaseCount.
When these values are inserted, I am using an internal trigger on Table A after any inserts that have been made. The internal trigger obtains the values that were just inserted and uses the ItemNumber to lookup Table B to obtain the ELC and Totallc and insert it into Table A where the ItemNumber matches Table B.
How to obtain the values with the trigger to retrieve the newly inserted values (values being ItemNumber, CaseCount)?
Then after the values are retrieved, how to use the item numbers(will be 20 ItemNumbers inserted at once) to look up values in table B and insert them into Table A where the ItemNumber matches?
I don’t have much code since I am practically stuck on number one . Any help is most appreciated.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER ObtainValues
ON Table A
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for trigger here
END
GO

As you have created Trigger on Table A, whenever a row is insert, SQL Server will create a table called INSERTED which holds newly added rows only. The scope of this INSERTED table is within your Trigger body only.
Check the below code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER ObtainValues
ON Table A
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE TableA
SET col1 = B.col1,
col1 = B.col1
FROM TableB B
WHERE B.ItemNumber = (SELECT ItemNumber FROM INSERTED)
END
GO
Similarly, when delete event occurs, DELETED table is created.

Taking Nithin's fine example as a starting point. I modified this so it will handle multiple row inserts.
CREATE TRIGGER ObtainValues
ON TableA
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE TableA
SET col1 = B.col1,
col1 = B.col1
FROM TableB B
INNER JOIN TableA A on a.[YourPrimaryKey] = b.[YourPrimaryKey]
SET NOCOUNT OFF;
GO

Related

Create a string from inserted.id via trigger

I'm creating a trigger on insert that will create a new record in another table using the id from the newly inserted row.
I need to format the id before I insert it into the other table. This is my code so far.... having problems creating the formated #PseudoID.
CREATE TRIGGER OnInsertCreateUnallocatedPseudo
ON tblTeams
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
DECLARE #PseudoID NVARCHAR(50), #tmID NVARCHAR(10)
SELECT #tmID = CONVERT(nvarchar(10),inserted.tmID) FROM inserted
--NEED SOME CODE TO CREATE A PADDED OUT PseudoID e.g.
-- if #tmID = '7' then #PseudoID = 'PSU0007'
-- if #tnID = '25' then #PseudoID = 'PSU0025'
INSERT INTO [dbo].[tblUsersPseudo].....
END
You can't assign it to a variable within the trigger since there could be multiple rows, but you could do something like this to insert into the other table.
LEFT('PSU0000',LEN('PSU0000')-LEN(CONVERT(nvarchar(10),inserted.tmID))) + CONVERT(nvarchar(10),inserted.tmID)
You can't assume that Inserted has only a single row, you have to treat it as a table with 0-N rows and carry out set-based operations on it (rather than procedural).
FORMAT will format your existing id into the new format you require.
INSERT INTO [dbo].[tblUsersPseudo] (id, col1, col2, ...)
SELECT FORMAT(id,'PSU0000')
, col1, col2
FROM Inserted;

Delete trigger and getting field from another table

I have this delete trigger on an SQL database. The record deletes currently and gets written to an audit table. I have been asked to include in this history table a field from another table that is related to the record being deleted based on SurveyID. I thought I could do something like
select #Status = Status from table where Survey = deleted.Survey
But this is incorrect syntax.
ALTER trigger [dbo].[table_Selfdelete]
on [dbo].[table]
after delete
as
Begin
Set nocount on;
Declare #SurveyId int
Declare #StudentUIC varchar(10)
Declare #Status varchar(10)
select #SurveyId = deleted.SurveyID,
#StudentUIC = deleted.StudentUIC
from deleted
select #Status = Status from tbly when SurveyID = deleted.SurveyID
insert into fupSurveyAudit
values(#SurveyId,#StudentUIC,#Status)
End
Arrgh. I think you want this insert in your trigger (and nothing else):
insert into fupSurveyAudit(SurveyId, StudentUIC, status)
select d.SurveyId, d.StudentUIC, y.status
from deleted d left join
tbly y
on d.SurveyId = y.SurveyId;
Notes:
deleted could contain more than one row, so assuming that it has one row can lead to a run-time error or incorrect results.
A left join is needed in case there is no matching row for the status.
You should always include the columns in an insert
Your archive table should have additional columns, such as an identity column and the date of the insert, which are set automatically (and hence not explicitly part of the insert).
Triggers are fired once for each statement (Delete,insert,update) not for each row inside the statement.
You cannot use variables here because when multiple lines are deleted from the table only one line will be inserted in the Audit table because the variable can only hold one value.
You just need a simple insert from the deleted table into the Audit table something like this....
ALTER trigger [dbo].[table_Selfdelete]
on [dbo].[table]
after delete
as
Begin
Set nocount on;
insert into fupSurveyAudit(SurveyId, StudentUIC,[Status])
select d.SurveyID
,d.StudentUIC
,y.[Status]
from deleted d
INNER JOIN tbly y ON y.SurveyID = deleted.SurveyID
End
Try this
ALTER trigger [dbo].[table_Selfdelete]
on [dbo].[table]
after delete
as
Begin
Set nocount on;
insert into fupSurveyAudit -- Better listed the column list here
select
d.SurveyID, d.StudentUIC, y.Status
from
deleted d JOIN tbly y ON d.SurveyID = y.SurveyID
End

UPDATE after INSERT for potentially multiple rows - not working

I have the following trigger which doesn't work and I'm not sure why.
The trigger should fire after an insert into the REFERRALS table and I've allowed for the possibility of multiple rows being inserted.
The value of ORIGINAL_PATIENT_ID in the REFERRALS table should be set to the value of PATIENT_ID in Inserted, but it just doesn't work, i.e. the value of ORIGINAL_PATIENT_ID remains NULL.
IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[updateOSC]'))
DROP TRIGGER [dbo].[updateOSC]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[updateOSC]
ON [dbo].[REFERRALS]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
IF (SELECT ORIGINAL_PATIENT_ID FROM Inserted) IS NULL
UPDATE [dbo].[REFERRALS]
SET ORIGINAL_PATIENT_ID = i.PATIENT_ID
FROM Inserted i
WHERE dbo.REFERRALS.PATIENT_ID = i.PATIENT_ID
END
GO
If you can have multiple rows being updated then IF (SELECT ORIGINAL_PATIENT_ID FROM Inserted) IS NULL doesn't make much sense to me as this will return multiple values which you cannot compare to NULL.
I think you will get your desired result by using
CREATE TRIGGER [dbo].[updateOSC]
ON [dbo].[REFERRALS]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
UPDATE [dbo].[REFERRALS]
SET
ORIGINAL_PATIENT_ID = i.PATIENT_ID
FROM
Inserted i
WHERE
dbo.REFERRALS.PATIENT_ID = i.PATIENT_ID AND i.ORIGINAL_PATIENT_ID IS NULL
END
GO

Insert multiple rows into a table with a trigger on insert into another table

I am attempting to create a T-SQL trigger that will essentially insert x number of rows into a third table based upon the data being inserted into the original table and data contained in a second table; however, I'm getting all sorts of errors in the select portions of the insert statement.
If I comment out this portion [qmgmt].[dbo].[skillColumns].[columnID] in (select columnID from [qmgmt].[dbo].[skillColumns]), IntelliSense gets rid of all the red lines.
Table designs:
Users table - contains user info
skillColumns table - list of all columns possible, filtered on the productGroupID of the user
Skills table - contains the data per user, one row for every columnID in skillColumns
CREATE TRIGGER tr_Users_INSERT
ON [qmgmt].[dbo].[Users]
AFTER INSERT
AS
BEGIN
INSERT into [qmgmt].[dbo].[Skills]([userID], [displayName], [columnID])
Select [iTable].[userID],
[iTable].[displayName],
[cID] in (select [columnID] as [cID] from [qmgmt].[dbo].[skillColumns])
From inserted as [iTable] inner join
[qmgmt].[dbo].[skillColumns] on
[iTable].[productGroupID] = [qmgmt].[dbo].[skillColumns].[groupID]
END
GO
Is what I'm looking to accomplish even possible with a trigger? Can multiple rows be inserted into a table with the in keyword?
UPDATE:
After using the answer provided by J0e3gan, I was able to create a trigger in the opposite direction:
CREATE TRIGGER tr_skillColumns_INSERT_Users
ON [qmgmt].[dbo].[skillColumns]
AFTER INSERT
AS
BEGIN
INTO [qmgmt].[dbo].[Skills]([userID], [displayName], [columnID])
Select [qmgmt].[dbo].[Users].[userID],
[qmgmt].[dbo].[Users].[displayName],
[iTable].[columnID]
From inserted as [iTable] inner Join
[qmgmt].[dbo].[Users] on
[iTable].[groupID] = [qmgmt].[dbo].[Users].[productGroupID]
Where
[qmgmt].[dbo].[Users].[userID] in (select [userID] from [qmgmt].[dbo].[Users])
END
GO
Yes, this can be done with an AFTER trigger.
The column list is not the correct place for the IN criterion that you are trying to use, which is why it is underlined in red.
Try adding the IN criterion to the JOIN criteria instead:
CREATE TRIGGER tr_Users_INSERT
ON [qmgmt].[dbo].[Users]
AFTER INSERT
AS
BEGIN
INSERT into [qmgmt].[dbo].[Skills]([userID], [displayName], [columnID])
Select [iTable].[userID],
[iTable].[displayName],
[qmgmt].[dbo].[skillColumns].[columnID]
From inserted as [iTable] inner join
[qmgmt].[dbo].[skillColumns] on
[iTable].[productGroupID] = [qmgmt].[dbo].[skillColumns].[groupID] and
[qmgmt].[dbo].[skillColumns].[columnID] in (select columnID from [qmgmt].[dbo].[skillColumns])
END
GO
Alternatively add it to a WHERE clause:
CREATE TRIGGER tr_Users_INSERT
ON [qmgmt].[dbo].[Users]
AFTER INSERT
AS
BEGIN
INSERT into [qmgmt].[dbo].[Skills]([userID], [displayName], [columnID])
Select [iTable].[userID],
[iTable].[displayName],
[qmgmt].[dbo].[skillColumns].[columnID]
From inserted as [iTable] inner join
[qmgmt].[dbo].[skillColumns] on
[iTable].[productGroupID] = [qmgmt].[dbo].[skillColumns].[groupID]
Where
[qmgmt].[dbo].[skillColumns].[columnID] in (select columnID from [qmgmt].[dbo].[skillColumns])
END
GO

How to create a trigger that uses INSERT , DELETE , UPDATE events

I want to create a trigger for logging.So i need event names of INSERT,UPDATE or DELETE.i.e : one of these statements is used in query execution my trigger will trig and starts logging.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER LogBuses
ON Bus_table
AFTER INSERT,DELETE
AS
BEGIN
DECLARE #PlateNo nvarchar(50)
IF INSERT//something like that-INSERTING- DELETING
SELECT #PlateNo=PlateNo from inserted
insert into Logger (EffectedTable,ActionName,EffectDate,EffectedID)
VALUES ('Bus_table','Insert',SYSDATETIME (),#PlateNo);
ELSE IF DELETE
SELECT #PlateNo=PlateNo from deleted
insert into Logger (EffectedTable,ActionName,EffectDate,EffectedID) VALUES ('Bus_table','Insert',SYSDATETIME (),#PlateNo);
END
GO
You use the inserted and deleted tables. It's inserted if just the inserted table is populated, deleted if just the deleted table is populated, and updated if both tables are populated. Use if exists (select 1 from inserted) to test.
if exists (select 1 from inserted) and exists (select 1 from deleted)
--update
else if exists (select 1 from inserted)
--insert
else if exists (select 1 from deleted)
--delete
Create a stored procedure that logs, and triggers for each event, that call the procedure, passing the needed data.