I have one table which consists of one trigger which will be called if any insert or update operation performed on that table.
This trigger will insert a new row in other physical table.
First I am taking the entire data to be inserted into a temporary table and then I am inserting data into my physical table(which has trigger).
After performing insert operation all the records in the temporary table are getting inserted into physical table but the trigger is executing for only first record, for rest of the records it is not executing.
Can anyone please help me with this issue.
NOTE : With cursor it is working fine but for performance issue I don't want to use cursor.
ALTER TRIGGER [dbo].[MY_TRG]
ON [dbo].[T_EMP_DETAILS]
FOR INSERT , UPDATE
AS
BEGIN
IF UPDATE(S_EMPLOYEE_ID)OR UPDATE(S_GRADE_ID)OR UPDATE(D_EFFECTIVE_DATE) OR UPDATE(S_EMPLOYEE_STATUS)
BEGIN
DECLARE #EmpId varchar(6)
DECLARE #HeaderId Int
DECLARE #FYStartYear varchar(4)
DECLARE #EffDate Smalldatetime
DECLARE #UpdatedBy varchar(10)
DECLARE #ActionType varchar(1)
DECLARE #RowCount Int
DECLARE #EmpRowCount Int
DECLARE #AuditRowsCount Int
DECLARE #EMP_STATUS VARCHAR(1)
DECLARE #D_FIN_START_YEAR DATETIME
DECLARE #Food_Count int
SELECT #FYStartYear = CAST(YEAR(D_CURRENT_FY_ST_DATE)AS VARCHAR) FROM dbo.APPLICATION WHERE B_IS_CURRENT_FY = 1
SELECT #UpdatedBy = 'SHARDUL'
select #EmpId = S_EMPLOYEE_ID from inserted
select #HeaderId = N_HEADER_TXN_ID from inserted
select #EffDate = D_EFFECTIVE_DATE from inserted
select #FLEXI_AMT = N_FLEX_BASKET_AMT from inserted
select #EMP_STATUS = S_EMPLOYEE_STATUS from inserted
select #D_FIN_START_YEAR=D_FIN_START_DATE from inserted
SELECT #RowCount = count(*) from T_EMP_DETAILS
WHERE S_EMPLOYEE_ID = #EmpId and
SUBSTRING(CAST(D_EFFECTIVE_DATE AS VARCHAR),1,11) = SUBSTRING(CAST(#EffDate AS VARCHAR),1,11)
BEGIN
exec INSERT_DEFAULT_VALUES #EmpId,#HeaderId,#UpdatedBy
END
That's one of many reasons Bulk is so fast :). Read Bulk Insert syntax and you'll see FIRE_TRIGGERS parameter. Use it.
As I wrote in my comment - you are using inserted in improper way. As written now it will work only for 1 row.
The second one is a WEIRD number of variables, and only few are used, why?
Third - you are using SP in the end of batch, you need to post it's code, I bet there is some insert in it, maybe you could avoid using this SP and insert directly in some table from inserted.
Related
I need to write a SQL trigger that displays the data from columns from two tables. I need this trigger to flow once my Transactions table has a new row added or an existing row updated. this is what I have so far but it isn't working its just printing blank table whenever the table is amended.
create or alter trigger TransactionInfo
on [dbo].[Transactions]
after insert, update
as
begin
declare #pickupDate date;
declare #returnDate date;
declare #Make varchar (25);
declare #model varchar (25);
declare #tID int;
select #pickupDate, #returnDate, #Make, #model, #tID
from[dbo].[Transactions], [dbo].[CAR]
end
Once I insert default values in the table I store the result of scope identity in a variable
insert into OrderPlaced default values;
declare #id bigint;
set #id = SCOPE_IDENTITY();
After this, I have to run some other pieces of code that change the value of scope identity and after running those pieces of code I have to use the value of #id again but it shows an error saying that I must declare the variable which I have already done above.
EXEC dbo.GetRecieptById #ID = #id;
Unfortunately, I can't just select the whole code block and execute it at once as this is for a presentation and I have to show each individual steps.
Your request is how to persist the variable across batches - not within a batch.
One way would be to use SESSION_CONTEXT
declare #id bigint;
insert into OrderPlaced default values;
set #id = SCOPE_IDENTITY();
EXEC sys.sp_set_session_context #key= N'#id',#value = #id
GO
declare #id bigint = CAST(SESSION_CONTEXT(N'#id') AS BIGINT)
EXEC dbo.GetRecieptById #ID = #id;
What you wanna do ?
If you want to access the latest data in your Order Table, you can access the latest data with this code.
SELECT MAX(ID) FROM OrderPlaced
The local variable can not be used in a separate execution. You have to store all values in a temporary table.
These tables are stored in tempdb. Use local temporary table with one # or global temporary table with two ## at the beginning of the table name as follow:
create table #local_temp_table
(Id bigint not null);
...
insert into #local_temp_table ...
...
select Id from #local_temp_table;
OR
create table ##global_temp_table
(Id bigint not null);
...
insert into ##global_temp_table ...
...
select Id from ##global_temp_table;
They are automatically dropped when they go out of scope, however, you can drop them manually.
Take a look at the following link:
Temporary Tables in SQL Server
Update: This still remain a mystery. Checked the calling code and we did not find anything that would make the SP run in a loop.
For now we have split the SP into two which seems to have arrested the issue although not able to reason how that has helped out.
Database: MS SQL Server.
I have a SP which performs few operations - i.e inserts a row into 3 tables based on certain status as part of that SP being called.
It is getting called from our web application based on a user action.
We have cases, few times a day where the same row gets inserted multiple times (sometime more than 50+) with the same values in each row except that if you look at the datetime when the row was inserted there is a difference of few milliseconds. So it is unlikely that the user is initiating that action.
This SP is not running in a Transaction or with any locks however it is getting called probably concurrently multiple times as we have many concurrent users on the web application invoking this action.
My question is what is causing the same row to insert so many times? If concurrent execution of SP was an issue where we are updating same row then it is understood one may overwrite the other. However in this case each user calls in the SP with different parameters.
I have put the said operation in a Transaction to monitor the behavior however was looking to find out what exactly causes these kind of multiple inserts with same value just a few milliseconds apart?
USE [ABC]
GO
/****** Object: StoredProcedure [dbo].[AddProcessAdmittedDocUploadScrutinyWithLog] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[AddProcessAdmittedDocUploadScrutinyWithLog]
(
--Insert using bulk
#stdfrm_id int,
#course_id int,
#stdfrm_scrt_apprvby int,
#stdfrm_scrt_apprvcomment varchar(max),
#sRemainingDocs varchar(max),
#DTProcessAdmittedDocUploadScrutiny AS dbo.MyDTProcessAdmittedDocUploadScrutiny READONLY
)
AS
BEGIN
DECLARE #result char
SET #result='N'
--New
declare #AuditCount int=0;
select #AuditCount=count(scrtaudit_id) from tbl_ProcessAdmittedScrutinyAuditLog
where stdfrm_id=#stdfrm_id and stdfrm_scrt_apprvby=#stdfrm_scrt_apprvby
and stdfrm_scrt_apprvcomment=#stdfrm_scrt_apprvcomment and convert(date,stdfrm_scrt_apprvon,103)=convert(date,getdate(),103)
--Checked extra conditon to avoid repeatation
if(#AuditCount=0)
BEGIN
--Call Insert
BEGIN TRY
/*Remaining Documents----------*/
DECLARE #sdtdoc_id Table (n int primary key identity(1,1), id int)
if(#sRemainingDocs is not null)
begin
--INSERT INTO #sdtdoc_id (id) SELECT Name from splitstring(#sRemainingDocs)
INSERT INTO #sdtdoc_id (id) SELECT [Value] from dbo.FN_ListToTable(#sRemainingDocs,',')
end
Declare #isRemaining int=0;
SELECT #isRemaining=Count(*) FROM #sdtdoc_id
/*Calculate stdfrm_scrt_apprvstatus*/
Declare #stdfrm_scrt_apprvstatus char(1)='A';--Approved
Declare #TotalDescripancies int;
select #TotalDescripancies=count(doc_id) from #DTProcessAdmittedDocUploadScrutiny where doc_id_scrtyn='Y'
if(#isRemaining>0)
begin
set #stdfrm_scrt_apprvstatus='H';--Discrepancies Found
end
else if exists (select count(doc_id) from #DTProcessAdmittedDocUploadScrutiny where doc_id_scrtyn='Y')
begin
if(#TotalDescripancies>0)
begin
set #stdfrm_scrt_apprvstatus='H';--Discrepancies Found
end
end
/* Check if Discrepancies Found first time then assign to Checker o.w assign to direct college like grievance*/
if(#stdfrm_scrt_apprvstatus='H')
begin
declare #countAuditLog int=0;
select #countAuditLog=count(stdfrm_id) from tbl_ProcessAdmittedScrutinyAuditLog where stdfrm_id =#stdfrm_id
if (#countAuditLog=0)
begin
set #stdfrm_scrt_apprvstatus='G'--'E';--Discrepancies Found set Edit request assign to Checker
end
--else if (#countAuditLog=1)
-- begin
--set #stdfrm_scrt_apprvstatus='G';--Discrepancies Found set Grievance assign to college
-- end
end
/*----------------------*/
/*Update status in original table-----*/
Update tbl_ProcessAdmitted set stdfrm_scrt_apprvstatus=#stdfrm_scrt_apprvstatus
,stdfrm_scrt_apprvon=getdate(),stdfrm_scrt_apprvby=#stdfrm_scrt_apprvby
,stdfrm_scrt_apprvcomment=#stdfrm_scrt_apprvcomment
where stdfrm_id =#stdfrm_id
/*Add in Main Student Log-----------*/
/********* The row here gets inserted multiple times *******************/
INSERT into tbl_ProcessAdmittedScrutinyAuditLog
(stdfrm_id, stdfrm_scrt_apprvstatus, stdfrm_scrt_apprvon, stdfrm_scrt_apprvby, stdfrm_scrt_apprvcomment )
values
(#stdfrm_id, #stdfrm_scrt_apprvstatus, getdate(), #stdfrm_scrt_apprvby, #stdfrm_scrt_apprvcomment)
DECLARE #scrtaudit_id int =##identity
/*Completed -------------------------*/
DELETE FROM tbl_ProcessAdmittedDocUploadScrutiny WHERE stdfrm_id =#stdfrm_id
SET NOCOUNT ON;
/********* The row here gets inserted multiple times *******************/
INSERT tbl_ProcessAdmittedDocUploadScrutiny
(stdfrm_id, course_id, doc_id, doc_id_scrtyn, doc_id_scrtrmrk, doc_id_comment)
SELECT #stdfrm_id, #course_id, doc_id, doc_id_scrtyn, doc_id_scrtrmrk, doc_id_comment
FROM #DTProcessAdmittedDocUploadScrutiny;
/*Scrutiny Document Log -------------------------*/
/********* The row here gets inserted multiple times *******************/
INSERT tbl_ProcessAdmittedDocUploadScrutinyAuditLog
(scrtaudit_id,stdfrm_id, course_id, doc_id, doc_id_scrtyn, doc_id_scrtrmrk, doc_id_comment)
SELECT #scrtaudit_id,#stdfrm_id, #course_id, doc_id, doc_id_scrtyn, doc_id_scrtrmrk, doc_id_comment
FROM #DTProcessAdmittedDocUploadScrutiny;
/*Remaining Documents Insert into table*/
DELETE FROM tbl_ProcessAdmittedDocUploadScrutinyRemiaing WHERE stdfrm_id =#stdfrm_id
DECLARE #Id int,#doc_id int
WHILE (SELECT Count(*) FROM #sdtdoc_id) > 0
BEGIN
Select Top 1 #Id = n,#doc_id=id From #sdtdoc_id
--Do some processing here
insert into tbl_ProcessAdmittedDocUploadScrutinyRemiaing(stdfrm_id, doc_id )
values (#stdfrm_id,#doc_id)
insert into tbl_ProcessAdmittedDocUploadScrutinyRemiaingAuditLog
(scrtaudit_id, stdfrm_id, doc_id )
values (#scrtaudit_id,#stdfrm_id,#doc_id)
DELETE FROM #sdtdoc_id WHERE n = #Id
END --Begin end While
/*End Remaining Documents-----------*/
SET #result=#stdfrm_scrt_apprvstatus
END TRY
BEGIN CATCH
SET #result='N'
insert into tbl_ErrorSql( ErrorMessage, stdfrm_id)
values(coalesce(Error_Message(),ERROR_LINE()),#stdfrm_id)
END CATCH;
--End of Call Insert
END
SELECT #result
END
I created a stored procedure that should do 2 inserts in one
First step I want to create a new entry per insert into.
Second step I will catch the created Id from this entry
Third step I want to copie multiple entries per select from one table and insert those to the same table with the Id
Create PROCEDURE dbo.Rolle_Copie
#Id as int,
#newId as int = 0,
#Name AS nvarchar(50)
AS
INSERT INTO Rollen (RolleName)
VALUES (#Name)
#newId = SCOPE_IDENTITY()
INSERT INTO Berechtigung_Rolle (RefRolleId,RefBerechtigungId)
SELECT
RefBerechtigungId, #newId
FROM
Berechtigung_Rolle
WHERE
RefRolleId = #Id
RETURN
but I get an error
Wrong syntax next to #newId
Could somebody please enlight me what's wrong?
Any advice is greatly appreciated
don't forget to use SET
SET #newId = SCOPE_IDENTITY()
I have a stored procedure that returns an unique Id. I need to call this sp to get the unique ID for each row. I must use this SP because an application also uses this.
How can I select for each row a ID that is returned from the SP?
CREATE procedure [dbo].[SelectNextNumber]
#TableName nvarchar(255)
as
begin
declare #NewSeqVal int
set NOCOUNT ON
update Number --This is a table that holds for each table the max ID
set #NewSeqVal = Next = Next + Increase
where TableNaam= #TableName
if ##rowcount = 0
begin
Insert into Number VALUES (#TableName, 1, 1)
return 1
end
return #NewSeqVal
The number table:
CREATE TABLE [dbo].[Number](
[TableName] [varchar](25) NOT NULL,
[Next] [int] NULL,
[Increase] [int] NULL
I have seen that a While loop is usable for this but in my situation I don't know how to use a while loop.
You can't use stored procedures inside a SELECT statement, only functions.
You can iterate on a resultset with a cursor if you really have to use a stored procedure:
http://msdn.microsoft.com/library/ms180169.aspx
EDIT:
To be honest I'm not very sure to have understood what you really need, it looks like you are building a IDENTITY by yourself ( http://msdn.microsoft.com/library/ms174639(v=sql.105).aspx );
still, if you really need to run a cursor here's an example which uses your stored procedure:
http://sqlfiddle.com/#!3/2b81a/1
Taking the singular INSERT INTO.. SELECT apart:
Temporarily store the SELECT results away
declare #rc int, #NewSeqVal int;
SELECT ..
INTO #tmp -- add this
FROM ..
Store the rowcount and get that many numbers
set #rc = ##rowcount;
For which you have to use the code in the SP directly:
update Number --This is a table that holds for each table the max ID
set #NewSeqVal = Next = Next + #rc
where TableNaam= 'sometbl';
Finally, the insert
INSERT ...
SELECT ID = #NewSeqVal + 1 - row_number() over (ORDER BY col1)
, {all the other columns}
FROM #tmp;
ORDER by Col1 is arbitrary, choose something sensible, or make it ORDER BY NEWID() if you don't care.