Related
I have the a Requirement where I have to Delete in batches in sql server , and also track the number of count affected in the end. My Sample Code is as Follows:
Declare #count int
Declare #deletecount int
set #count=0
While(1=1)
BEGIN
BEGIN TRY
BEGIN TRAN
DELETE TOP 1000 FROM --CONDITION
SET #COUNT = #COUNT+##ROWCOUNT
IF (##ROWCOUNT)=0
Break;
COMMIT
END CATCH
BEGIN CATCH
ROLLBACK;
END CATCH
END
set #deletecount=#COUNT
Above Code Works fine, but how to keep track of #deletecount if Rollback happens in one of the batch.
Some potential issues with the code :
while loop never exits/breaks
declare #tbl table(foo bit); --deleting from an empty table
declare #COUNT int;
declare #iteration int = 0;
While(1=1)
BEGIN
--loop safety net
if #iteration >= 100
begin
break --exit after 100 iterations
end
select #iteration = #iteration+1
BEGIN TRY
DELETE TOP (1000) FROM #tbl; --#tbl is empty
SET #COUNT = #COUNT+##ROWCOUNT;-- <-- this always sets ##rowcount = 1
IF (##ROWCOUNT)=0 -- ... so this can never be 0 --> will never exit the loop
Break;
END TRY
BEGIN CATCH
END CATCH
END --end while
select #iteration as iterations;
Open transaction at the end of the batch
declare #tbl table(foo bit); --<-- empty table
declare #COUNT int;
declare #myrowcount int;
declare #iteration int = 0;
While(1=1)
BEGIN
--loop safety net
if #iteration >= 100
begin
break --exit after 100 iterations
end
select #iteration = #iteration+1
BEGIN TRY
BEGIN TRAN --<-- transaction begins on each iteration
DELETE TOP (1000) FROM #tbl; --#tbl is empty
set #myrowcount = ##rowcount;
SET #COUNT = #COUNT+#myrowcount;
IF (#myrowcount)=0
Break; --<-- if this breaks... transaction is neither committed nor rolledback
COMMIT --<-- commited on each iteration, when no error
END TRY
BEGIN CATCH
ROLLBACK --<-- or rolled back on each iteration error
END CATCH
END --end while
select #iteration as iterations, ##trancount as open_transactions;
rollback transaction;
loop keeps trying to delete the same erroneous batch (over and over again) and never exits
create table parent (id int primary key clustered);
create table child (parentid int references parent(id));
go
--some parents
insert into parent(id)
select top (200) row_number() over(order by ##spid)
from sys.all_objects;
--and a child
insert into child(parentid) values (75)
go
declare #COUNT int;
declare #myrowcount int;
declare #errormsg nvarchar(max);
declare #iteration int = 0;
While(1=1)
BEGIN
--loop safety net
if #iteration >= 100
begin
break --exit after 100 iterations
end
select #iteration = #iteration+1
BEGIN TRY
DELETE TOP (10) t --changed the batch size..for the example
from (select top (10000) * from parent order by id) as t;
set #myrowcount = ##rowcount;
SET #COUNT = #COUNT+#myrowcount;
IF (#myrowcount)=0
Break;
END TRY
BEGIN CATCH
select #errormsg = isnull(#errormsg, '') + error_message();
END CATCH
END --end while
select #iteration as iterations, #errormsg as errormsg;
--some parents have been deleted (8th batch kept failing, there is an fk to parent 75)
select *
from parent
go
drop table child
drop table parent
go
You could rectify all the above issues...(last one, to skip erroneous batches being a bit more "difficult"), by implementing logic in the where clause (eg. exclude rows which are referenced etc) according to your model. Trying to implement a straight deletion, without any rules, and skipping failures makes it a bit harder.
Just an example: when a batch fails, after 3 attempts, take another deletion route. Since each deletion is atomic, transactions are not really needed here (besides, if the batch is called from a parent module, a plain ROLLBACK in the batch would "invalidate" any transactions opened in the parent module, before the batch execution)
create table parent (id int primary key clustered);
create table child (parentid int references parent(id));
go
--some parents
insert into parent(id)
select top (200) row_number() over(order by ##spid)
from sys.all_objects;
--and two children
insert into child(parentid) values (75), (115) --, (9), (18) --: add 9 and 18 and nothing gets deleted, alternative route in the example does not work
go
declare #COUNT int;
declare #myrowcount int;
declare #iteration int = 0;
declare #errormsg nvarchar(max);
declare #ierrorcnt int=0;
declare #deletedids table(id int);
declare #lastsuccessfullydeletedid int = 0;
select #COUNT = 0;
While(1=1)
BEGIN
--loop safety net
if #iteration >= 100
begin
break --exit after 100 iterations
end
select #iteration = #iteration+1
BEGIN TRY
--when 10 consecutive errors in a single iteration..just quit the loop
if #ierrorcnt >= 10
begin
break;
end
BEGIN TRAN --<-- transaction begins on each iteration
if #ierrorcnt >= 3 --when 3 consecutive errors in the iteration..try to bypass the current batch
begin
delete top (10) t
output deleted.id into #deletedids(id)
from (select top (10) * from (select top (2*10) * from parent where id > #lastsuccessfullydeletedid order by id) as a order by id desc) as t
select #myrowcount = count(*), #lastsuccessfullydeletedid = max(id)
from #deletedids;
delete from #deletedids;
end
else
begin
DELETE TOP (10) FROM parent where id > #lastsuccessfullydeletedid;
set #myrowcount = ##rowcount;
end
SET #COUNT = #COUNT+#myrowcount;
COMMIT --<-- commited on each iteration, when no error
IF (#myrowcount)=0 and #ierrorcnt = 0
Break;
set #ierrorcnt = 0; --everything ok, set iteration error counter to 0
END TRY
BEGIN CATCH
ROLLBACK --<-- or rolled back on each iteration error
if #ierrorcnt = 0
begin
select #errormsg = isnull(#errormsg, '') +';'+ error_message();
end
set #ierrorcnt = #ierrorcnt + 1; --error, increase the iteration error counter
END CATCH
END --end while
select #iteration as iterations, ##trancount as open_transactions;
select #iteration as iterations, #errormsg as errormsg;
--some parents have been deleted
select * /*2 failed batches, 20 rows left*/
from parent
select #COUNT as [count/deleted] --<--this is also the deleted count
go
drop table child
drop table parent
go
..without any errors, in your original code, #count = #deletedcount
declare #tbl table(foo int); --<-- empty table
insert into #tbl(foo)
select top (100000) row_number() over(order by ##spid)
from sys.all_objects as a
cross join sys.all_objects as b;
--batch 1000, max iterations for the #tbl count
declare #maxiterations int;
select #maxiterations = 1+count(*) / 1000
from #tbl
declare #COUNT int;
declare #deletedcount int;
declare #myrowcount int;
declare #iteration int = 0;
select #COUNT = 0, #deletedcount = 0;
While(1=1)
BEGIN
--loop safety net
if #iteration >= #maxiterations
begin
break --exit after #maxiterations
end
select #iteration = #iteration+1;
BEGIN TRY
BEGIN TRAN
DELETE TOP (1000) FROM #tbl
where foo%5 = 0 ;
set #myrowcount = ##rowcount;
SET #COUNT = #COUNT+#myrowcount;
set #deletedcount = #deletedcount + #myrowcount;
COMMIT
IF #myrowcount=0
Break;
END TRY
BEGIN CATCH
ROLLBACK
END CATCH
END --end while
select #iteration as iterations, ##trancount as open_transactions;
select #count as _count, #deletedcount as deletedcount;
I have table with a myNumber varchar(50) column which stores values with lead zero, like a '0000001111'.
Now I want to replace leading '0000' with '12', like '12001111'.
I tried this statement:
UPDATE myDB.dbo.myTable
SET myNumber = REPLACE(myNumber, '0000', '12')
WHERE myNumber LIKE '0000%'
But this caused an error:
Msg 248, Level 16, State 1, Procedure trplist_for_Inserted_Updated_Deleted Line 80
The conversion of the varchar value "831116399075' overflowed an int column.
Why this error caused if all columns are the varchar?
What should I do?
UPDATED
Sorry guys, the reason of error it is the tables trigger.
Here is triggers logic
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER TRIGGER [dbo].[trplist_for_Inserted_Updated_Deleted]
ON [dbo].[pList]
FOR Insert, Update, Delete
NOT FOR REPLICATION
AS
SET NOCOUNT ON
Declare #Result_check Int
Declare #NameTable nvarchar(30)
set #NameTable='plist'
Declare #FieldName nvarchar(30)
set #FieldName='ChangeTime'
Declare #Columns varbinary(MAX)
set #Columns=COLUMNS_UPDATED()
Execute CheckChangeFields #Columns, #NameTable, #FieldName, #Result_check
if #Result_check = 1
begin
return
end
set #FieldName='DateTimeInArchive'
Execute CheckChangeFields #Columns, #NameTable, #FieldName, #Result_check
if #Result_check = 1
begin
return
end
Declare #stateRecord Int
IF EXISTS(SELECT * FROM inserted)
IF EXISTS(SELECT * FROM deleted)
BEGIN
SET #stateRecord = 1 --Update
--PRINT 'Update'
END
ELSE
BEGIN
--PRINT 'Insert'
SET #stateRecord = 0 --Insert
END
ELSE
BEGIN
--PRINT 'Is DELETE'
IF EXISTS(SELECT * FROM deleted)
BEGIN
SET #stateRecord = 2 --Delete
--PRINT 'DELETE'
END
ELSE
BEGIN
SET #stateRecord = -1
--PRINT 'No DELETE'
END
END
IF #stateRecord = -1
RETURN
declare #id_value int
Declare #status_record int
declare #inn int
declare #Company int
declare #tabnumber varchar(50)
if (#stateRecord in (0,1))
BEGIN
--inserted or updated
--проверка на изменение поля StatusRecord
declare #Result_check_status_record int
if Exists(select * from Deleted where checksum(StatusRecord) In (select Checksum(StatusRecord) from Inserted))
select #Result_check_status_record= 1--одинаковые
else
select #Result_check_status_record= 0--разные
DECLARE cursor_inserted_trpList_Inserted_Updated_Delete_logs CURSOR LOCAL FOR select id, StatusRecord, INN, TabNumber, Company from inserted
OPEN cursor_inserted_trpList_Inserted_Updated_Delete_logs
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value, #status_record,#inn, #tabnumber, #Company
WHILE ##FETCH_STATUS = 0
BEGIN
if (#inn<>'')
begin
if Exists(select id from plist where (id<> #id_value) and (INN=#inn))
begin
RollBack
RAISERROR('Данный INN уже имеется в базе', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
end
if (#tabnumber<>'') and (#tabnumber<>'0')
begin
if #Company = 0
begin
if Exists(select id from plist where (id<> #id_value) and (TabNumber=#tabnumber) and (Company<=0))
begin
RollBack
RAISERROR('Данный TabNumber уже имеется в базе', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
end
else
begin
if Exists(select id from plist where (id<> #id_value) and (TabNumber=#tabnumber) and (Company=#Company))
begin
RollBack
RAISERROR('Данный TabNumber уже имеется в базе в данном подразделении', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
end
end
if ((#status_record&1)>0)
begin
if (#Result_check_status_record=0)
begin
Execute GustIsRelease #id_value
update guest set IDNoFace=0 where PListID=#id_value
Declare #dmtm datetime
if Exists(select id from plist where (id=#id_value) and (IsNull(DateTimeInArchive, '')=''))
begin
Update plist set DateTimeInArchive=GetDate() where (id=#id_value) and (IsNull(DateTimeInArchive, '')='')
end
end
end
else
begin
if Exists(select id from plist where (id=#id_value) and (IsNull(DateTimeInArchive, 1)<>1))
Update plist set DateTimeInArchive=Null where (id=#id_value) and (IsNull(DateTimeInArchive, 1)<>1)
end
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value, #status_record,#inn, #tabnumber, #Company
END
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
END
if (#stateRecord=2)
BEGIN
DECLARE cursor_inserted_trpList_Inserted_Updated_Delete_logs CURSOR LOCAL FOR select id from deleted
OPEN cursor_inserted_trpList_Inserted_Updated_Delete_logs
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value
WHILE ##FETCH_STATUS = 0
BEGIN
if Exists(select id from pmark where owner=#id_value)
begin
RollBack
RAISERROR('У сотрудника остались активные пароли', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
if Exists(select id from guest where IDNoFace=#id_value)
begin
RollBack
RAISERROR('Сотрудник привязан к посетителю', 16,2)
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
return
end
update guest set IDNoFace=0 where IDNoFace=#id_value
update guest set ReceiveListId=0 where ReceiveListId=#id_value
FETCH NEXT FROM cursor_inserted_trpList_Inserted_Updated_Delete_logs INTO #id_value
END
CLOSE cursor_inserted_trpList_Inserted_Updated_Delete_logs
END
You could use STUFF
UPDATE myDB.dbo.myTable
SET myNumber=stuff(myNumber, 1,4, '12')
WHERE myNumber LIKE '0000%'
Use can use SUBSTRING/STUFF as below:
SUBSTRING:
UPDATE #tblTest
SET Number='12'+SUBSTRING(Number,5,LEN(NUMBER))
WHERE LEFT(Number,4)='0000'
AND LEN(Number)>4
STUFF:
UPDATE #tblTest
SET Number=STUFF(Number, 1,4, '12')
WHERE LEFT(Number,4)='0000'
AND LEN(Number)>4
Use substring function to accomplish the result u want
UPDATE myDB.dbo.myTable
SET Number='12'+SUBSTRING(myNumber,5)
WHERE SUBSTRING(myNumber,1,4)='0000';
I need to improve the performance ofa stored procedure in SQL Server 2014.
Here is my procedure and I want optimise this procedure because this running to slowly.
Can anybody explain with some examples, which kind of query is better over what and in what situation?
CREATE PROCEDURE [dbo].[sp_Customer_SendMoney]
#CustomerId bigint,
#MobileNo nvarchar(15),
#Amount money,
#Comment nvarchar(250),
#PassPhrase nvarchar(50),
#Type varchar(50) = null
AS
BEGIN
DECLARE #returnCode INT
DECLARE #RetVal BIGINT, #CustomerBalance MONEY,
#CustomerMoneyRequestedId BIGINT,
#ToCustomerId BIGINT = 0,
#TransactionId BIGINT, #CustomerAccount BIGINT,
#FromCustomerBalance MONEY = 0,
#ToCustomerBalance MONEY = 0
IF EXISTS (SELECT Id FROM Customer
WHERE Id = #CustomerId AND IsDeleted = 0 AND IsActive = 1)
BEGIN
SELECT
#CustomerBalance = Balance
FROM
Customer
WHERE
Id = #CustomerId AND IsDeleted = 0 AND IsActive = 1
select #ToCustomerId = Id, #CustomerAccount = AccountNo,#ToCustomerBalance=Balance From Customer where convert(nvarchar,DecryptByPassPhrase(#PassPhrase, MobileNo)) = #MobileNo and IsDeleted = 0 and IsActive = 1
if(#ToCustomerId > 0)
begin
if( lower(isnull(#Type,'regular')) <> 'suspention')
begin
set #ToCustomerBalance=#ToCustomerBalance+#Amount
end
END
set #FromCustomerBalance=#CustomerBalance-#Amount
if((#CustomerBalance > 0) and (#CustomerBalance >= #Amount) )
Begin
BEGIN TRAN TxnsenMoney
BEGIN TRY
select #TransactionId = TransactionW2W+1 from MstGenerateTransactionID
where [year]=datepart(yyyy,getdate()) and [month]=DATENAME(month,getdate())
update MstGenerateTransactionID set TransactionW2W= #TransactionId
where [year]=datepart(yyyy,getdate()) and [month]=DATENAME(month,getdate())
--set #TransactionId = CONVERT(bigint,replace(convert(varchar, getdate(),111),'/','') + replace(convert(varchar, getdate(),114),':',''))
IF(#ToCustomerId > 0)
BEGIN
--Update sender Customer
update Customer set Balance = Balance - #Amount where Id = #CustomerId
--Update receiver Customer
if(lower(isnull(#Type,'regular')) <> 'suspention')
begin
update Customer set Balance = Balance + #Amount where Id = #ToCustomerId
end
else
begin
update Customer set SuspentionAccount = isnull(SuspentionAccount,0) + #Amount where Id = #ToCustomerId
end
INSERT INTO [TransactionW2W]
([TransactionId]
,[FromCustomerId]
,[ToCustomerId]
,[MobileNo]
,[Amount]
,[Comments]
,[CreatedOn]
,[FromCustomerBalance]
,[ToCustomerBalance])
VALUES
(#TransactionId
,#CustomerId
,#ToCustomerId
,#MobileNo
,#Amount
,#Comment
,GETDATE()
,#FromCustomerBalance
,#ToCustomerBalance)
End --end IF #ToCustomerId > 0
ELSE
BEGIN
--Update sender Customer
update Customer set Balance = Balance - #Amount where Id = #CustomerId
--print 'ELSE'
INSERT INTO [TransactionW2W]
([TransactionId]
,[FromCustomerId]
,[ToCustomerId]
,[MobileNo]
,[Amount]
,[Comments]
,[CreatedOn]
,[FromCustomerBalance])
VALUES
(#TransactionId
,#CustomerId
,#ToCustomerId
,#MobileNo
,#Amount
,#Comment
,GETDATE()
,#FromCustomerBalance)
INSERT INTO [NewCustomer]
([FromCustomerId]
,[MobileNo]
,[Amount]
,[CreatedOn]
)
VALUES
(#CustomerId
,#MobileNo
,#Amount
,GETDATE()
)
END --end ELSE #ToCustomerId > 0
print #RetVal
IF(##TRANCOUNT >0 )
begin
set #RetVal = #TransactionId
print #RetVal
end
else
begin
RAISERROR('records not executed',16,1)
END
COMMIT TRAN TxnsenMoney
END TRY
BEGIN CATCH
ROLLBACK TRAN TxnsenMoney
set #RetVal = -1
declare #error varchar(max)
set #error= ERROR_MESSAGE()
-- RAISERROR(#error,16,1)
print #error
END CATCH
select #RetVal
End
END
End
CREATE PROCEDURE [dbo].[sp_Customer_SendMoney]
#CustomerId bigint,
#MobileNo nvarchar(15),
#Amount money,
#Comment nvarchar(250),
#PassPhrase nvarchar(50),
#Type varchar(50) = null
AS
Begin
DECLARE #returnCode INT ,#RetVal bigint,#CustomerBalance money, #CustomerMoneyRequestedId bigint,#ToCustomerId bigint = 0,#TransactionId bigint,#CustomerAccount bigint,
#FromCustomerBalance money=0,#ToCustomerBalance money=0
IF EXISTS (select Id from Customer WITH(NOLOCK) where Id = #CustomerId and IsDeleted = 0 and IsActive = 1) Begin
select #CustomerBalance = Balance from Customer WITH(NOLOCK) where Id = #CustomerId and IsDeleted = 0 and IsActive = 1
select #ToCustomerId = Id, #CustomerAccount = AccountNo,#ToCustomerBalance=Balance From Customer WITH(NOLOCK)
where convert(nvarchar,DecryptByPassPhrase(#PassPhrase, MobileNo)) = #MobileNo and IsDeleted = 0 and IsActive = 1
IF(#ToCustomerId > 0)
BEGIN
if( lower(isnull(#Type,'regular')) <> 'suspention')
BEGIN
SET #ToCustomerBalance=#ToCustomerBalance+#Amount
END
END
SET #FromCustomerBalance=#CustomerBalance-#Amount
if((#CustomerBalance > 0) and (#CustomerBalance >= #Amount) )
Begin
BEGIN TRAN TxnsenMoney
BEGIN TRY
SELECT #TransactionId = TransactionW2W+1
FROM MstGenerateTransactionID WITH(NOLOCK)
WHERE [year]=datepart(yyyy,getdate()) and [month]=DATENAME(month,getdate())
update MstGenerateTransactionID set TransactionW2W= #TransactionId
where [year]=YEAR(GETDATE()) and [month]= MONTH(GETDATE())
--set #TransactionId = CONVERT(bigint,replace(convert(varchar, getdate(),111),'/','') + replace(convert(varchar, getdate(),114),':',''))
IF(#ToCustomerId > 0) BEGIN
--Update sender Customer
UPDATE Customer set Balance = Balance - #Amount where Id = #CustomerId
--Update receiver Customer
if(lower(isnull(#Type,'regular')) <> 'suspention') BEGIN
UPDATE Customer set Balance = Balance + #Amount where Id = #ToCustomerId
END ELSE BEGIN
UPDATE Customer set SuspentionAccount = isnull(SuspentionAccount,0) + #Amount where Id = #ToCustomerId
END
INSERT INTO [TransactionW2W]
([TransactionId] ,[FromCustomerId],[ToCustomerId] ,[MobileNo] ,[Amount],[Comments],[CreatedOn],[FromCustomerBalance],[ToCustomerBalance])
SELECT #TransactionId ,#CustomerId ,#ToCustomerId ,#MobileNo ,#Amount ,#Comment,GETDATE(),#FromCustomerBalance ,#ToCustomerBalance
END --end IF #ToCustomerId > 0
ELSE BEGIN
--Update sender Customer
UPDATE Customer set Balance = Balance - #Amount where Id = #CustomerId
--print 'ELSE'
INSERT INTO [TransactionW2W]
([TransactionId] ,[FromCustomerId],[ToCustomerId] ,[MobileNo] ,[Amount] ,[Comments] ,[CreatedOn],[FromCustomerBalance])
SELECT #TransactionId ,#CustomerId ,#ToCustomerId ,#MobileNo ,#Amount ,#Comment ,GETDATE() ,#FromCustomerBalance
INSERT INTO [NewCustomer]
([FromCustomerId] ,[MobileNo] ,[Amount] ,[CreatedOn] )
SELECT #CustomerId,#MobileNo ,#Amount,GETDATE()
END --end ELSE #ToCustomerId > 0
print #RetVal
IF(##TRANCOUNT >0 )BEGIN
set #RetVal = #TransactionId
print #RetVal
END ELSE BEGIN
RAISERROR('records not executed',16,1)
END
COMMIT TRAN TxnsenMoney
END TRY
BEGIN CATCH
ROLLBACK TRAN TxnsenMoney
SET #RetVal = -1
DECLARE #error varchar(max)
SET #error= ERROR_MESSAGE()
-- RAISERROR(#error,16,1)
print #error
END CATCH
select #RetVal
End
END
End
I have this trigger that after insert update and insert data in a table, using the if as paramter for the insert or update, at the same time i have another trigger after update that changes another register. The problem is that the first trigger when does the update it trigger the update trigger... So occours that I had to protect the first trigger by checking if there´s a register there before the insert BUT I have a cursor to insert the data in the middle of all this, after I did checking the insert of one register occurs BUT the others inside the cursor aren´t inserted in the table just one register of the list in the cursor... I cannot find the problem, please help...
this is my trigger:
ALTER TRIGGER [dbo].[tr_inclusao_dupla] ON [dbo].[tb_patrimonio]
AFTER INSERT
AS
BEGIN
begin try
IF EXISTS (SELECT * FROM INSERTED) AND EXISTS (SELECT * FROM DELETED)
BEGIN
declare #id as int
declare #count as int
declare #qtd as int
declare #emlote as bit
declare #nr_serie as varchar(100)
declare #nr_patrimonio as varchar(100)
declare #dm_identificado as bit
declare #nr_inventario as varchar(100)
set #nr_patrimonio = (select nr_patrimonio_efetivo from inserted)
set #nr_serie = (select nr_serie from inserted)
set #nr_inventario = (select nr_inventario from inserted)
/*single insert*/
if (#nr_patrimonio is not null or #nr_serie is not null or #nr_inventario is not null)
begin
set #emlote =0
declare registros cursor for
select cd_patrimonio , nr_qtd_lote,nr_serie, nr_patrimonio_efetivo from inserted
open registros
fetch next from registros into #id, #qtd, #nr_serie, #nr_patrimonio
while( ##fetch_status = 0)
begin
set #dm_identificado = 1
update tb_patrimonio set dm_identificado = #dm_identificado, dm_em_lote = #emlote
where cd_patrimonio = #id
end
fetch next from registros into #id, #qtd,#nr_serie, #nr_patrimonio
close registros
deallocate registros
end
END
ELSE
BEGIN
/*multiple insert*/
begin
set #emlote =0
set #dm_identificado = 0
declare registros2 cursor for
select cd_patrimonio , nr_qtd_lote,nr_serie, nr_patrimonio_efetivo from inserted
open registros2
fetch next from registros2 into #id, #qtd, #nr_serie, #nr_patrimonio
while( ##fetch_status = 0)
begin
print #qtd
set #count = 1
update tb_patrimonio set dm_identificado = #dm_identificado, dm_em_lote = #emlote
where cd_patrimonio = #id
while (#count <= (#qtd-1))
begin
INSERT INTO [dbo].[tb_patrimonio]
([dm_patrimonio]
,[dm_em_lote]
,[nr_qtd_lote]
,[cd_grupo_produto]
,[nm_patrimonio]
,[nr_patrimonio_efetivo]
,[nr_patrimonio_antigo]
,[nr_serie]
,[ds_descricao]
,[nr_lacre]
,[cd_barra]
,[dm_tipo_entrada]
,[nr_garantia]
,[cd_nota_fiscal]
,[ds_garantia]
,[img_patrimonio]
,[cd_situacao_patrimonio]
,[cd_orgao]
,[cd_local]
,[dm_situacao]
,[cd_usuario_inc]
,[cd_estado_patrimonio]
,[cd_tipo_posse]
,[cd_usuario_alt]
,[dt_alteracao]
,[cd_usuario]
,[dt_inclusao]
,[cd_estado_equipamento]
,[cd_fornecedor]
,[nr_termo]
,[img_termo]
,[dm_identificado]
,[dt_instalacao_equipamento]
,[nr_inventario])
SELECT
[dm_patrimonio]
,#emlote
,[nr_qtd_lote]
,[cd_grupo_produto]
,[nm_patrimonio]
,[nr_patrimonio_efetivo]
,[nr_patrimonio_antigo]
,[nr_serie]
,[ds_descricao]
,[nr_lacre]
,[cd_barra]
,[dm_tipo_entrada]
,[nr_garantia]
,[cd_nota_fiscal]
,[ds_garantia]
,[img_patrimonio]
,[cd_situacao_patrimonio]
,[cd_orgao]
,[cd_local]
,[dm_situacao]
,[cd_usuario_inc]
,[cd_estado_patrimonio]
,[cd_tipo_posse]
,[cd_usuario_alt]
,[dt_alteracao]
,[cd_usuario]
,[dt_inclusao]
,[cd_estado_equipamento]
,[cd_fornecedor]
,[nr_termo]
,[img_termo]
,#dm_identificado
,[dt_instalacao_equipamento]
,[nr_inventario]
FROM inserted where cd_patrimonio = #id
set #count = #count + 1
end
fetch next from registros2 into #id, #qtd,#nr_serie, #nr_patrimonio
end
close registros2
deallocate registros2
end
END
end try
begin catch
declare #errormessage nvarchar(4000)
declare #errorseverity int
declare #errorstate int
select
#errormessage = ERROR_MESSAGE(),
#errorseverity = ERROR_SEVERITY(),
#errorstate = ERROR_STATE()
raiserror (
#errormessage,
#errorseverity,
#errorstate
)
end catch end
I am using the following trigger to track inserts and updates on multiple tables and log it in a log table.
CREATE TRIGGER tr_TestTable1]
ON [TestTable_1]
AFTER INSERT, UPDATE
AS
DECLARE #keyid int, #tn nvarchar(50), #recEditMode nvarchar(50), #trstat nvarchar(50)
BEGIN
SET NOCOUNT ON;
SET #tn = 'TestTable_1'
IF EXISTS(SELECT 1 FROM INSERTED)
BEGIN
SET #recEditMode = (Select REC_EDIT_MODE FROM inserted)
SET #trstat = 'PENDING'
SET #keyid = (Select prkeyId FROM inserted)
IF (#recEditMode = 'MANUAL')
BEGIN
IF NOT EXISTS (SELECT * FROM [logTable_1] WHERE SourceKeyId = #keyid AND TrStatus = 'PENDING' AND SourceTableName = #tn)
BEGIN
INSERT INTO [logTable_1](SourceKeyId,SourceTableName,TrStatus)
VALUES (#keyid, #tn, #trstat)
END
END
END
END
This works fine on single row insert and single row update. I am unable to optimize this code to handle multi row inserts and updates. Looking for some help in handling this.
Thanks.
I modified the trigger as below and it seems to be working fine now...
CREATE TRIGGER tr_TestTable1]
ON [TestTable_1]
AFTER INSERT, UPDATE
AS
DECLARE #keyid int, #tn nvarchar(50), #trstat nvarchar(50)
BEGIN
IF ##ROWCOUNT = 0
RETURN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM INSERTED)
BEGIN
SET #tn = 'TestTable_1'
SET #trstat = 'PENDING'
BEGIN
INSERT INTO LogTable_1 (SourceKeyId, SourceTableName, TrStatus)
SELECT I.prKeyId, #tn, #trStat FROM INSERTED AS I
WHERE (I.REC_EDIT_MODE = 'MANUAL' AND NOT EXISTS(SELECT * FROM LogTable_1 WHERE SourceKeyId = I.prKeyId AND SourceTableName = #tn AND TrStatus = 'PENDING'))
END
END
END