SQL Server trigger does not recognize inserted row - sql-server

I have simple SQL Server trigger and for some reason it does not recognize INSERTED row.
Here is code:
-- code
DROP TABLE a;
GO
CREATE TABLE a
(
id INT IDENTITY(1,1) PRIMARY KEY,
v INT
)
GO
DROP TABLE a_audit;
CREATE TABLE a_audit
(
id INT,
v INT,
[updated_at] [DATETIME] NOT NULL DEFAULT GETDATE()
)
GO
CREATE TRIGGER [dbo].[trg_a]
ON [dbo].[a]
AFTER INSERT, UPDATE, DELETE
NOT FOR REPLICATION
AS
BEGIN
SET NOCOUNT ON;
PRINT 'start';
DECLARE #xmltmp xml = (SELECT * FROM inserted FOR XML AUTO);
PRINT CONVERT(NVARCHAR(MAX), #xmltmp);
-- INSERT INTO a_audit (id, v) VALUES (inserted.id, inserted.v);
END;
GO
INSERT INTO a (v)
VALUES (1);
WAITFOR DELAY '00:00:01.11';
INSERT INTO a (v)
VALUES (2);
GO
SELECT * FROM a;
PRINT 'done'
It produces this output
start
<inserted id="1" v="1"/>
(1 row affected)
start
<inserted id="2" v="2"/>
(1 row affected)
(2 rows affected)
done
So I see that INSERTED row does exist.
However, if I remove comment on insert statements the output is this:
Msg 4104, Level 16, State 1, Procedure trg_a, Line 14 [Batch Start Line 16]
The multi-part identifier "inserted.id" could not be bound.
Msg 4104, Level 16, State 1, Procedure trg_a, Line 14 [Batch Start Line 16]
The multi-part identifier "inserted.v" could not be bound.
What is wrong?

inserted is a table, not a function. To INSERT from another table you need to use a INSERT INTO... SELECT ... FROM statement:
INSERT INTO a_audit (id,v)
SELECT id,
v
FROM inserted;
You can't reference a table's columns unless you use a FROM. For example just running the below would give the error below:
SELECT a_audit.id, a.audit.v;
The multi-part identifier "a_audit.id" could not be bound.
You would have to a SELECT...FROM:
SELECT id, v
FROM a_audit;

Related

SQL Server Stored Procedure Syntax Error

I am trying to write a stored procedure that returns a deposit record for a specific person, the number of deposits for that person and the row number of that deposit for that person. The parameter #personID is always supplied the correct personID; however #SpecificRow is either 0 (meaning: return most recent deposit) or a row number (meaning:return record at this specific row).
Script:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [schema].[procedure]
#personID varchar(5),
#SpecificRow int,
#RowNumber INT OUTPUT,
#RowCount INT OUTPUT
AS
BEGIN
IF OBJECT_ID('#TempSortedDeposits') IS NOT NULL
DROP Table #TempSortedDeposits
-- get all deposits with record number into temp file for specific personID
SELECT
ROW_NUMBER() OVER (ORDER BY Date ASC) AS RecordNo, *
INTO
#TempSortedDeposits
FROM
persons.Deposits
WHERE
personID = #personID
-- get record count in file
SELECT #RowCount = COUNT(personID)
FROM persons.Deposits
WHERE personID = #personID
IF #SpecificRow = 0 --get most recent record
SET #RowNumber = #RowCount;
ELSE
--get record by rownumber
SET #RowNumber = #SpecificRow;
SELECT *
FROM #TempSortedDeposits
WHERE RecordNo = ­#RowNumber
END
When I try running the alter statement, I get the following error:
Msg 102, Level 15, State 1, Procedure procedure, Line 33 [Batch Start Line 9]
Incorrect syntax near '­'.
Any insight?
Thanks.
I deleted this line SELECT * FROM #TempSortedDeposits WHERE RecordNo = #RowNumber and manually re-type it then it worked.
This is because the error occurs due to copy and paste. That result to pasted code contains unprintable characters like d non-braking spaces.
Just a side note... your #TempSortedDeposits table dropping like you think it is.
Here's a quick example:
create table #TempSortedDeposits (i int)
insert into #TempSortedDeposits
values
(1)
IF OBJECT_ID('#TempSortedDeposits') IS NOT NULL DROP TABLE #TempSortedDeposits
select * from #TempSortedDeposits
If you run this the first time, it will return 1 when it shouldn't, because it should have been dropped. On the second run (same connection) you will get this error, showing you that the table still exists and wasn't dropped:
Msg 2714, Level 16, State 6, Line 2 There is already an object named
'#TempSortedDeposits' in the database.
To fix this, change the syntax to:
IF OBJECT_ID('tempdb..#TempSortedDeposits') IS NOT NULL DROP TABLE #TempSortedDeposits
Here is a test
create table #TempSortedDeposits (i int)
insert into #TempSortedDeposits
values
(1)
IF OBJECT_ID('tempdb..#TempSortedDeposits') IS NOT NULL DROP TABLE #TempSortedDeposits
select * from #TempSortedDeposits
If you first manually drop the table (since we created it with the last run) and then run this, you will get the error message:
Msg 208, Level 16, State 0, Line 7 Invalid object name
'#TempSortedDeposits'.
Which means the select failed, thus showing that the table was in fact dropped.
I have removed the extra character present in below line and re execute this proc. Line is
SELECT * FROM #TempSortedDeposits WHERE RecordNo = #RowNumber

SQL Server Insert Null error in spite of providing not null values

I am trying to do an insert but it is giving an error stating that credits cannot be null but I am not providing null. Attached Screenshot
Code: Insert into [dbo].[Course] values (12,'Java',1,1,1);
Error: Msg 515, Level 16, State 2, Procedure trgAfterInsert, Line 31
Cannot insert the value NULL into column 'Credits', table 'DemoCollege.dbo.Course'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Trigger:
Create trigger trgAfterInsert2 ON [dbo].[Course]
After Insert
AS
Declare #cid int;
Declare #cname nvarchar(50);
Select #cid = i.CourseID from inserted i;
Select #cname = i.Title from inserted i;
Insert into dbo.CourseTemp values (#cid, #cname);
Print 'After insert trigger fired';
GO
There's an insert trigger on the table & that's where the error is being generated from.
There must be some logic in that is converting the provided credit value to a null value somehow.
Just provide the columns where you want to insert the values.
Insert into [dbo].[Course](ColName1, ColName2, ColName3, ColName4, etc..) values (12,'Java',1,1,1);
Most probably you're missing a col in the middle

Insert Values with foreign keys SQL

I am trying to insert data that has foreign keys. I am able to update the first two tables with the GUID but I am not able to do so in the last 3 tables I am trying to update
BEGIN TRANSACTION;
DECLARE #myid uniqueidentifier
SET #myid = NEWID()
INSERT INTO [SERVER].[DB].[Pod] (id)
VALUES (#myid)
INSERT INTO [SERVER].[DB].[RackPattern] ([id])
VALUES (#myid)
INSERT INTO [SERVER].[DB].[PhysicalServer] ([serialNumber], [rackPosition],[Rack_id], id)
VALUES ('2327', '25', 'DBedc1001r01', #myid)
INSERT INTO [SERVER].[DB].[Rack] ([Site_id], [Pod_id], [RackPattern_id], id)
VALUES ('Datacenter','PostionID', 'RACK_PATTERN_ID_1', #myid)
INSERT INTO [SERVER].[DB].[Site] (Pod_id, id)
VALUES ('PostionID', #myid)
COMMIT;
Results:
(1 row(s) affected)
(1 row(s) affected)
Msg 547, Level 16, State 0, Line 11
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__PhysicalS__Rack___00DF2177". The conflict occurred in database "VCO01-A_PATTERN_DB", table "DB.Rack", column 'id'.
Msg 547, Level 16, State 0, Line 14
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Rack__Site_id__6BE40491". The conflict occurred in database "VCO01-A_PATTERN_DB", table "DB.Site", column 'id'.
Msg 547, Level 16, State 0, Line 17
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Site__Pod_id__4F47C5E3". The conflict occurred in database "VCO01-A_PATTERN_DB", table "DB.Pod", column 'id'.
Well, you insert something into PhysicalServer in your third statement, which references Rack with a specific ID - but the insert into the Rack table only happens in the fourth statement - so that Rack.Id isn't going to be there (yet) when you run your third SQL statement! Same for the fifth statement - you insert a Site with an id - but you already reference that table in your fourth statement....
It's just a matter of inserting in the RIGHT order here - try this:
BEGIN TRANSACTION;
DECLARE #myid uniqueidentifier
SET #myid = NEWID()
INSERT INTO [SERVER].[DB].[Pod] (id)
VALUES (#myid)
INSERT INTO [SERVER].[DB].[RackPattern] ([id])
VALUES (#myid)
-- insert into SITE
INSERT INTO [SERVER].[DB].[Site] (Pod_id, id)
VALUES ('PostionID', #myid)
-- insert into RACK, referencing the SITE
INSERT INTO [SERVER].[DB].[Rack] ([Site_id], [Pod_id], [RackPattern_id], id)
VALUES ('Datacenter', 'PostionID', 'RACK_PATTERN_ID_1', #myid)
-- NOW you can insert into "PhysicalServer" which references the rack ...
INSERT INTO [SERVER].[DB].[PhysicalServer] ([serialNumber], [rackPosition],[Rack_id], id)
VALUES ('2327', '25', 'DBedc1001r01', #myid)
COMMIT;
But there's still something fishy.....
In the third statement you insert something into Site with an id that's this GUID you created. Yet in the fourth statement, you reference the SiteId as 'Datacenter' ...... something isn't right yet.....

Error in Insert into database in Stored Procedure

I have a problem with this code :
ALTER PROCEDURE [arch].[spInsertToDocumentFileCategoryRelation]
#DocumentNumber nvarchar(50)
,#DocumentDate date
,#IsDocumentDelete bit
,#Address nvarchar(max)
,#DocumentLevelTypeId int
,#DocumentId2 bigint
,#DocumentRelationTypeId tinyint
,#CategoryId bigint
,#FileId bigint
,#FileAssignCategoryId bigint OUTPUT
,#DocumentRelationId bigint OUTPUT
,#FileOfDocumentId bigint OUTPUT
,#DocumentId bigint OUTPUT
AS
BEGIN
INSERT INTO [arch].[Document]
(
[DocumentNumber]
,[DocumentDate]
,[DateOfDocumentCreate]
,[IsDocumentDelete]
,[Address]
,[DocumentLevelTypeId]
)
VALUES
(
#DocumentNumber
,#DocumentDate
,'2015-5-12'
,#IsDocumentDelete
,#Address
,#DocumentLevelTypeId
)
Set #DocumentId = SCOPE_IDENTITY();
INSERT INTO [arch].[FileOfDocument]
(
[DocumentId]
,[FileId]
)
VALUES
(
#DocumentId
,#FileId
)
Set #FileOFDocumentId = SCOPE_IDENTITY();
INSERT INTO [arch].[DocumentRelation]
(
[DocumentRelationTypeId]
,[DocumentId1]
,[DocumentId2]
)
VALUES
(
#DocumentRelationTypeId
,#DocumentId
,#DocumentId2
)
Set #DocumentRelationId = SCOPE_IDENTITY();
INSERT INTO [arch].[FileAssignCategory]
(
[CategoryId]
,[FileId]
)
VALUES
(
#CategoryId
,#FileId
)
Set #FileAssignCategoryId = SCOPE_IDENTITY();
END
this code Execute correctly but when I want to test this Stored Procedure with some input values, sql server report some errors :
Msg 515, Level 16, State 2, Procedure
spInsertToDocumentFileCategoryRelation, Line 27
Cannot insert the value NULL into column 'DocumentTypeId', table
'ffisherDB.arch.Document'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Msg 515, Level 16, State 2, Procedure
spInsertToDocumentFileCategoryRelation, Line 48
Cannot insert the value NULL into column 'DocumentId', table
'ffisherDB.arch.FileOfDocument'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Msg 515, Level 16, State 2, Procedure
spInsertToDocumentFileCategoryRelation, Line 61
Cannot insert the value NULL into column 'DocumentId1', table
'ffisherDB.arch.DocumentRelation'; column does not allow nulls. INSERT
fails.
The statement has been terminated.
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
I have four Key that set with SCOPE_IDENTITY(). the first one set exactly right but the others fails and above Errors report.
please help me.
Well, from error text it looks like your arch.Document table has non-nullable column DocumentTypeId.
And you're not filling that column here:
INSERT INTO [arch].[Document]
(
[DocumentNumber]
,[DocumentDate]
,[DateOfDocumentCreate]
,[IsDocumentDelete]
,[Address]
,[DocumentLevelTypeId]
)
So this column has its default value (I guess it is null), thus this insert fails, thus #DocumentId is null and remaining inserts fails too...
As per first error message DocumentTypeId field in Document table is not allowing null. You should insert a value into it in the insert query.
Change your insert to
INSERT INTO [arch].[Document]
(
[DocumentNumber]
,[DocumentDate]
,[DateOfDocumentCreate]
,[IsDocumentDelete]
,[Address]
,[DocumentLevelTypeId]
,[DocumentTypeId] --Add document type id here
)
VALUES
(
#DocumentNumber
,#DocumentDate
,'2015-5-12' --You better insert a DATE type or in ISO formatted 'yyyymmdd' string.
,#IsDocumentDelete
,#Address
,#DocumentLevelTypeId
,#DocumentTypeId --Insert a non - null value
)
Second & third error messages are due to first error.

Firing an Insert trigger only when there is no data in the target table similar to the data from the inserted

I am trying to execute a SQL Insert trigger which is fired and inserts some data into another table when data is inserted into a table which is a straight forward trigger but I am trying to check a condition before firing the trigger which is to find if the data similar to the inserted data is already in the target table. I tried with the following query
CREATE trigger [dbo].[trgI_InsertINTOLastTrade]
ON [dbo].[tblCC]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
IF(SELECT COUNT(id) AS IDC
FROM LastTrades
WHERE product = inserted.Product
AND grade = inserted.grade
AND Term = inserted.Term
AND ISNULL(Pipeline, '') = inserted.Pipeline
AND ISNULL([Index], '') = inserted.[Index]) != 0
BEGIN
RETURN
END
INSERT INTO LastTrades(Product, Grade, Term, Pipeline,[Index], LastTradeValue)
SELECT
Product, Grade, Term, Pipeline, [Index], LastTradeValue
FROM
inserted
END
When I execute the above query I get these errors:
Msg 4104, Level 16, State 1, Procedure trgI_InsertINTOLastTrade, Line 15
The multi-part identifier "inserted.Product" could not be bound.
Msg 4104, Level 16, State 1, Procedure trgI_InsertINTOLastTrade, Line 15
The multi-part identifier "inserted.grade" could not be bound.
Msg 4104, Level 16, State 1, Procedure trgI_InsertINTOLastTrade, Line 15
The multi-part identifier "inserted.Term" could not be bound.
Msg 4104, Level 16, State 1, Procedure trgI_InsertINTOLastTrade, Line 15
The multi-part identifier "inserted.Pipeline" could not be bound.
Msg 4104, Level 16, State 1, Procedure trgI_InsertINTOLastTrade, Line 15
The multi-part identifier "inserted.Index" could not be bound.
Is there any good way I can solve this?
Before you call inserted.Product, you need to declare it in "from" statement.
CREATE trigger [dbo].[trgI_InsertINTOLastTrade]
on [dbo].[tblCC]
after insert
as
begin
SET NOCOUNT ON
IF(
select count(id) AS IDC
from LastTrades
inner join inserted i
on product=i.Product
and grade=i.grade
and Term=i.Term
and ISNULL(Pipeline,'')=i.Pipeline
and ISNULL([Index],'')=i.[Index]) !=0
Begin
Return
End
insert into LastTrades(Product,Grade,Term,Pipeline,[Index],LastTradeValue)
Select Product,Grade,Term,Pipeline,[Index],LastTradeValue from inserted
end
I am assuming you only want to insert rows that don't yet exist in the other table. The way you have coded it will insert all rows from your insert even if a given row already exists in the second table. This is because sql servers triggers fire once per operation. You need to code your triggers to handle this. Something like this should be close.
CREATE trigger [dbo].[trgI_InsertINTOLastTrade] on [dbo].[tblCC] after insert as
begin
SET NOCOUNT ON;
insert into LastTrades(Product,Grade,Term,Pipeline,[Index],LastTradeValue)
Select i.Product
, i.Grade
, i.Term
, i.Pipeline
, i.[Index]
, i.LastTradeValue
from inserted i
left join LastTrades lt on lt.product = inserted.Product
and lt.grade = inserted.grade
and lt.Term = inserted.Term
and ISNULL(lt.Pipeline, '') = inserted.Pipeline
and ISNULL([Index], '') = inserted.[Index]
where lt.Product is not null
end

Resources