I have written a Create trigger and it shows me some error on Incorrect Syntax near
My Code
CREATE TRIGGER [dbo].[News_data] ON [dbo].[News]
AFTER INSERT
AS
declare #NID uniqueidentifier;
select #NID = NEWID();
BEGIN
SET NOCOUNT ON;
INSERT INTO [ABC].[News](
#NID,
[Name], //<-- Incorrect Syntax near [Name]
[GeoLoc])
SELECT
[Name],
[GeoLoc]
FROM inserted
END
Your variable declaration is wrong with column list, if news table has primary column for which you are referring to #NID then use that column name instead :
INSERT INTO [dbo].[News] (PK, [Name], [GeoLoc])
SELECT #NID, [Name], [GeoLoc]
FROM inserted
Was about to post a sample code, but Yogesh already provided the answer
CREATE TRIGGER [dbo].[Customers_data] ON Customers
INSTEAD OF INSERT AS
DECLARE #NID INT = NEWID()
BEGIN
SET NOCOUNT ON;
INSERT INTO Customers(
CustomerID, -- <-- ColumnName instead of its value
CustomerName, -- <-- Incorrect Syntax near [Name]
ContactName)
SELECT
#NID
CustomerName,
ContactName
FROM inserted
END
Something else you might take a look at is the ID. If in one transaction multiple records are inserted, then the inserted will have multiple records with the same 'NewId'. Not sure if that is what you want in your case, but as I suspect that the #NID is the Primary Key, you might want to take a look at that.
Edit: To make sure the trigger still works with a batch-insert. Meaning that multiple records are inserted in one transaction, thus SELECT * FROM inserted will contain multiple records, while you do not wish them to use the same #NID value.
CREATE TRIGGER [dbo].[Customers_data] ON Customers
INSTEAD OF INSERT AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Customers(
CustomerID, -- <-- ColumnName instead of its value
CustomerName,
ContactName)
SELECT
NEWID(), -- <-- If the 'FROM inserted' contain multiple columns
CustomerName,
ContactName
FROM inserted
END
Related
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
I'm writing a DML trigger when change (update or Insert) happens in one table (Master table), I want to write the whole row into another table (Delta table).
The Master and Delta tables contains the same column with same datatype, except that Delta table contains an additional column called 'change_type', which should say either 'INSERT' OR 'MODIFY', depending on which trigger is updating the delta table.
The difficulty I'm having is I want to use the inserted table to update the Delta table row but its giving me errors.
CREATE TRIGGER [dbo].[TR_Update]
ON [dbo].[People_Master]
AFTER Update
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #RowCount int
Declare #ID int
Declare #Email nvarchar(50)
Declare #ct nvarchar(10)
select #ID = ID from inserted
Select #RowCount=COUNT(*) from People_Delta where People_Delta.ID = #ID and People_Delta.change_type = 'Modify';
if(#RowCount = 0)
Begin
Insert into People_Delta (ID,Email,uac,Department,FirstName,change_type)
values (iserted.ID,inserted.Email,inserted.uac,inserted.Department,inserted.Firstname'Modify');
END
END
GO
My table has 5 columns.
ID (primary key)
Email
Firstname
uac
Department
You are missing a , in your INSERT statement.
And because the number of columns you have specified does not match with the number of values you are inserting, you get an error.
inserted.Firstname , 'Modify'
Insert into People_Delta (ID,Email,uac,Department,FirstName,change_type)
values (iserted.ID,inserted.Email,inserted.uac,inserted.Department,inserted.Firstname,'Modify');
I basically want to insert something and use the OUTPUT function to get some values out of the inserted line. That's easy.
But I also want my query to get these values even if there has nothing been inserted because the primary already exists.
DECLARE #existingId bigint;
IF EXISTS(SELECT #existingId = Id FROM MyTable WHERE Name = #Name)
OUTPUT #existingId;
RETURN;
INSERT INTO MyTable (Name) OUTPUT INSERTED.Id VALUES (#Name);
This just always gives me Incorrect syntax near '='.
Any ideas how to achieve this behavior?
output takes a table, not a value. So the code you are striving to write should look more like this:
DECLARE #out table (existingid bigint);
INSERT INTO #out(existingid)
SELECT Id FROM MyTable WHERE Name = #Name;
IF EXISTS (SELECT * FROM #out)
RETURN;
INSERT INTO MyTable (Name)
OUTPUT INSERTED.Id INTO #out
VALUES (#Name);
This code, however, has race conditions. Because someone could insert Name between the check for the existence and the insert. To really fix this, you should use try/catch and have a unique index on name. Here is an example of the code:
DECLARE #out table (existingid bigint);
BEGIN TRY
INSERT INTO MyTable (Name)
OUTPUT INSERTED.Id INTO #out
VALUES (#Name);
RETURN
END TRY
BEGIN CATCH -- assume there is a duplicate although there could be other problems
INSERT INTO #out(existingid)
SELECT Id FROM MyTable WHERE Name = #Name;
END CATCH;
The following code creates the unique index:
create unique index idx_mytable_name on mytable(name);
I believe you are missing A opening and closing parenthesis, try:
DECLARE #existingId bigint;
IF EXISTS(SELECT #existingId =( Id FROM MyTable WHERE Name = #Name))
OUTPUT #existingId;
RETURN;
INSERT INTO MyTable (Name) OUTPUT INSERTED.Id VALUES (#Name);
I've cobbled together a trigger based on some answers I found here that I think is close, but is returning a supplied value error that I'm not sure how to fix. In short I have a ParticipationStatus table that I want to add a record to that will include the UserID of the inserted and a status of 'Pending' whenever a user RoleID of '19' is inserted in the UserRole table.
The Participation_Status table has a few other fields, but the only one that is required is an auto_id column. Here is what I have so far that is throwing a "Column name or number of supplied values does not match table definition." Any suggestions would be greatly appreciated.
CREATE TRIGGER [dbo].[trg_insert_status_participation] ON [dbo].[UserRoles]
FOR INSERT AS
BEGIN
If (SELECT RoleID FROM INSERTED)=19
DECLARE #UserID int
DECLARE #Status nvarchar(50)
INSERT INTO ParticipationStatus
VALUES (#UserID, #Status)
SET #UserID = (select UserID from inserted)
SET #Status = 'Pending'
END
INSERTED can have more than one row. You need to code your trigger accordingly. It's actually much simpler this way.
CREATE TRIGGER [dbo].[trg_insert_status_participation] ON [dbo].[UserRoles]
FOR INSERT AS
BEGIN
INSERT INTO ParticipationStatus(UserID, Status)
SELECT UserID, 'Pending' FROM INSERTED
WHERE RoleID = 19
END
Ok, so I want to create a trigger that fires when someone tries to insert into the table "products" and checks for a valid foreign key. For right now (This is NOT the end design in the least, but I'm using it for testing), I want the trigger to check that the inserted line references a valid ID in the Manufacturer table, and if no such row exists in the Manufacturer table, insert one with the proper ID and some general information for the remaining fields. My current code is as follows:
create trigger checkman
on dbo.products
instead of insert
as
declare
#manid char(5),
#manName varchar(50),
#transactionName varchar(20) = 'transaction1'
Begin
select #manid=Man_ID from Inserted
begin try
/*begin tran #transactionName*/
Insert into Manufacturers (Man_ID, Man_Name, Man_Description) VALUES #manid, 'Unknown Name', 'This is an unknown manufacturer');
insert into dbo.products select * from inserted;
end try
begin catch
/*rollback tran #transactionName;*/
insert into dbo.products select * from inserted;
end catch
End
The problem is that whenever I run my insert with a Manufacturer ID that already exists, I get this error:
(0 row(s) affected)
Msg 3930, Level 16, State 1, Procedure checkman, Line 20
The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.
The statement has been terminated.
I get the same error when I put the "Insert into Manufacturers" line in the catch block, only this time it appears when I try to insert with an ID that doesn't yet exist.
Don't handle this in a try/catch block, it isn't necessary. Also you need to allow for the fact that inserted can contain multiple rows. You can do this using a NOT EXISTS query:
CREATE TRIGGER CheckMan
ON dbo.products
INSTEAD OF INSERT
AS
INSERT Manufacturers (Man_ID, Man_Name, Man_Description)
SELECT DISTINCT Man_ID, 'Unknown Name', 'This is an unknown manufacturer'
FROM inserted i
WHERE NOT EXISTS
( SELECT 1
FROM Manufacturers m
WHERE m.Man_ID = i.Man_ID
);
INSERT dbo.Products
SELECT *
FROM inserted;
HOWEVER, I don't advocate this approach, I think it would be much better to just rely on the referencial integrity provided by the foreign key itself, and if the Man_ID does not exist let the insert fail, and if necessary ensure all Man_IDs exist before even attempting to insert.
I changed your trigger to following. In doing so, I made a few implicit assumptions. Assuming here that Products is a 3 column table (col1 & col2 being the other columns apart from Man_ID).
Hope this helps
alter
trigger checkman
on dbo.products
instead of insert
as
declare
#manid char(5),
#col1 varchar(50),
#transactionName varchar(20) = 'transaction1',
#col2 Varchar(500)
Begin
select #manid=Man_ID, #col1 = col1, #col2 = col2 from Inserted
IF (NOT EXISTS (SELECT Man_ID
FROM Manufacturers Where Man_ID = #manid
))
INSERT INTO ManuFacturers (Man_ID, Man_name, Man_Description) Values (#manid, 'Unknown Name', 'This is an unknown manufacturer')
INSERT INTO Products (Man_ID, col1, col2) values (#manid, #col1, #col2)
--begin try
-- /*begin tran #transactionName*/
-- Insert into Manufacturers (Man_ID, Man_Name, Man_Description) VALUES (#manid, 'Unknown Name', 'This is an unknown manufacturer')
-- insert into dbo.products select * from inserted;
--end try
--begin catch
-- /*rollback tran #transactionName;*/
-- insert into dbo.products select * from inserted;
--end catch
End