SQL server execute SP from sql table and update - sql-server

The table below stores sql insert statements and I run those from a sp. I need to also add an insert to the last_run_dt column. I put the code together via existing stackoverflow questions. I need help implementing this in my code, any feedback will be helpful.
How can I update my code to update the last_run_dt column?
Table:
audit_sql_id audit_sql last_run_dt
1 select * from <<need to add last run_dt value>>
2 select * from <<need to add last run_dt value>>
Code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter proc [dbo].[sp_sqlAudit]
#packagename as varchar(255)
as
begin
set nocount on;
if #packagename='SQL_DM_AUDIT'
begin
declare #queries table (audit_sql_id int identity(1,1),sqlscript varchar(max))
declare #str_query varchar(max);
declare #startloop int
declare #endloop int
insert into #queries
select audit_sql
from dw.dbo.audit_sql with(nolock)
select #endloop = max(audit_sql_id), #startloop = min(audit_sql_id)
from #queries
while #startloop < = #endloop
begin
select #str_query = sqlscript
from #queries
where audit_sql_id = #startloop
exec (#str_query)
set #startloop = #startloop + 1
end
end
end

I would suggest a slight refactor something like the below. There's no need to bring the entire list of sql statements into TemDB, just iterate over it and get each statement in turn. I would also always add a #debug parameter to print the sql instead if executing.
create or alter procedure dbo.sqlAudit
#packagename as varchar(255)
as
set nocount on;
declare #str_query varchar(max), #Id int
declare #AuditID table (Id int)
if #packagename='SQL_DM_AUDIT'
begin
insert into #AuditID (Id) /* Get list of IDs */
select audit_sql_id
from dw.dbo.audit_sql
while exists(select * from #AuditID) /* Continue while there are IDs in the list */
begin
select top (1) #Id=Id from #AuditID /* Get an ID */
select #str_query=audit_sql /* Get the sql for the ID */
from dw.dbo.audit_sql
where audit_sql_id=#Id
delete from #AuditID where Id=#Id /* Remove this ID from the list */
begin try
exec (#str_query)
if ##Error=0
begin
update dw.dbo.audit_sql set last_run_dt=GetDate() /* Update date for ID if run successful */
where audit_sql_id=#Id
end
end try
begin catch
/*handle error*/
end catch
end
end
go

Related

Insert trigger: set value from procedure ends with 3609 error

I have to check if a specific value of an insert is null. If it is null, I want to give it a value from a stored procedure. This procedure returns a number like a sequence, but because I have SQL Server 2008 I had to create it myself:
CREATE PROCEDURE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE ( #value BIGINT OUTPUT)
AS
BEGIN TRANSACTION;
INSERT dbo.BAV_Personalarchiv_Sequence WITH (TABLOCKX) DEFAULT VALUES;
ROLLBACK TRANSACTION;
SELECT #value = SCOPE_IDENTITY();
GO
I want to use the created value in my Insert Trigger if 'SYSROWID' is null (if it is null, it should be the only record with it) :
ALTER TRIGGER [dbo].[NT_BAV_PERSONALARCHIV_MITARBEITER_INSERT]
ON [dbo].[NT_BAV_PERSONALARCHIV_MITARBEITER]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
If (SELECT SYSROWID FROM INSERTED) IS NULL
Begin
DECLARE #value BIGINT;
EXECUTE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE #value OUTPUT;
Update dbo.NT_BAV_PERSONALARCHIV_MITARBEITER
SET SYSROWID = #value
where SYSROWID IS NULL
End
END
But sadly it returns with an 3609 error and rolls back the transaction.
Testing only the Execute and Update works without a problem:
DECLARE #value BIGINT;
EXECUTE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE #value OUTPUT;
Update dbo.NT_BAV_PERSONALARCHIV_MITARBEITER
SET SYSROWID = #value
where SYSROWID IS NULL
What am I missing? Thank you for your help!
Ok, I found out that the rollback in the procedure causes the trigger to end with the error. My workaround is to delete the values of the "sequence"-table before I create a new value:
ALTER PROCEDURE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE ( #value BIGINT OUTPUT)
AS
delete from dbo.BAV_Personalarchiv_Sequence
INSERT dbo.BAV_Personalarchiv_Sequence WITH (TABLOCKX) DEFAULT VALUES;
SELECT #value = SCOPE_IDENTITY();
GO

Delete statement not working in Stored Procedure

I am trying delete multiple records from store procedure SQL-Server 2012. I have select and then delete statement, apparently my delete statement is not been called
ALTER PROCEDURE [dbo].[DeleteFunctionsNavigation]
#FunctionName nvarchar(250),
#Function_identity INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT Navigation_Functions.Function_ID
FROM Navigation_Functions
WHERE Navigation_Functions.FunctionName = #FunctionName
SET #Function_identity=SCOPE_IDENTITY()
DELETE FROM Navigation_FunctionHierarchy
WHERE Navigation_FunctionHierarchy.Function_IDs = #Function_identity
RETURN
END
The usage of SCOPE_IDENTITY() is incorrect in this context. Try this
ALTER PROCEDURE [dbo].[DeleteFunctionsNavigation]
#FunctionName nvarchar(250),
#Function_identity INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT #Function_identity = Navigation_Functions.Function_ID
FROM Navigation_Functions
WHERE Navigation_Functions.FunctionName = #FunctionName
DELETE FROM Navigation_FunctionHierarchy
WHERE Navigation_FunctionHierarchy.Function_IDs = #Function_identity
RETURN
END

Invalid Object Name #tablename at second call of #tablename sql server 2005

When I execute the code :
declare #result int
exec recostcos #result
select #result
I get 'Msg 208, Level 16, State 0, Procedure RecostCOS, Line 138
Invalid object name '#rLB'.'
The strange thing is The first reference to #rLB did not produce any error but the second reference on line 138 produces the error above.
Please find below the code for recostcos :
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[RecostCOS](#result int output)
as
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON
--variables
declare #itemName varchar(50)
declare #invoiceNo varchar(50)
declare #customerName varchar(100)
declare #recordedBy varchar(100)
declare #transDate datetime
declare #supCode varchar(50)
declare #decemQty1 decimal(18,6)
declare #decemQty2 decimal(18,6)
declare #decemQty3 decimal(18,6)
declare #recostQty decimal(18,6)
declare #count int
declare #innerCount int
declare #outputCode int
declare #outputCounter int
declare #recId int
declare #innerId int
create table #supcodes(supcode varchar(50),item_name varchar(50),
qty decimal(18,6),id int identity(1,1))
create table #recostList(invoice_no varchar(50),qty decimal(18,6), id int identity(1,1))
create table #rLB(invc_no varchar(50),qty decimal(18,6), id int identity(1,1))
--check for supplyCode needing reprocessing
select #count=count(*) from someTable where recosted=0;
if(#count<=0)
begin
commit
set #result=0
return #result
end
--
insert into #supcodes(supcode,item_name,qty)
select supply_code,item_name,quantity from someTable
where recosted=0
--recost each supply code needing recosting
while(#count>0)
begin
select top 1 #supCode=supcode,#itemName=item_name,#decemQty1=qty,#recId=id
from #supcodes
select #decemQty2=sum(current_qty) from someTable2 where item_name=#itemName
select #decemQty3=quantity from someTable3 where item_name=#itemName
if(#decemQty2 is null)
set #decemQty2=0
if(#decemQty3 is null)
set #decemQty3=0
--debug
if(#decemQty2<>#decemQty3)
begin
--check if there is a log of this error
select #count=count(*) from someTable4 where error_code=1 and
item_name=#itemName and supply_code=#supCode and resolved=0
if(#count<=0)
--error in stock quantities (this must be resolved b4 any recosting)
insert into someTable4(supply_code,item_name,error_code,error_source,error_detail)
values(#supCode,#itemName,1,'re-costing','Mismatch in stock quantities in stock state and supply codes tables')
end
else if(#decemQty1>#decemQty2)
begin
--check if there is a log of this error
select #count=count(*) from someTable4 where error_code=2 and
item_name=#itemName and supply_code=#supCode and resolved=0
--insufficient stock for recosting
if(#count<=0)
insert into someTable4(supply_code,item_name,error_code,error_source,error_detail)
values(#supCode,#itemName,2,'re-costing','insufficient stock for recosting')
end
else
begin
--recost cost of sales of item involved
--get list of invoices of item to be recosted
set #recostQty=#decemQty1
insert into #recostList(invoice_no,qty)
select invoice_no,quantity from someTable5
where supply_code=#supCode and item_name=#itemName
insert into #rLB(invc_no,qty) select invoice_no,qty from #recostList
--delete cost of sales relating to supcod and item in stock account
select #innerCount=count(*) from #recostList
while(#innerCount>0)
begin
select top 1 #invoiceNo=invoice_no,#decemQty2=qty,#innerId=id
from #recostList
delete someTable6 where description
like 'sales of '+ltrim(rtrim(convert(varchar(20),#decemQty2)))+'%'+
#itemName+'%'+#invoiceNo
delete someTable5 where supply_code=#supCode and item_name=#itemName
and quantity=#decemQty2
delete #recostList where id=#innerId
set #innerCount=#innerCount-1
end
--call costByFIFO to recost item
select #innerCount=count(*) from #rLB
set #outputCounter=#innerCount
while(#innerCount>0)
begin
select top 1 #invoiceNo=invc_no,#decemQty2=qty,#innerId=id
from #rLB
select #customerName=customer_name, #transDate=trans_date,
#recordedBy=recorded_by from someTable7 where invoice_no=#invoiceNo
exec #outputCode=costByFIFO #itemName,#invoiceNo,#customerName,
#decemQty2,#transDate,#recordedBy
--ensure each invoice is costed or reverse entire process
if(#outputCounter=0)
begin
set #outputCounter=#outputCounter-1
end
else
begin
set #result=3 --failed to cost all invoices involved
rollback
end
delete #rLB where id=#innerId
set #innerCount=#innerCount-1
end
--outputCounter must be 0 to indicate all invoices where costed
if(#outputCounter<>0)
begin
set #result=3 --failed to cost all invoices involved
rollback
end
else
begin
update someTable set recosted=1 where supply_code=#supCode
and item_name=#itemName
end
end
delete #supcodes where id=#recId
set #count=#count-1
end
SET NOCOUNT OFF
drop table #supcodes
drop table #recostList
drop table #rLB
set #result=0
COMMIT
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() ErrorNBR, ERROR_SEVERITY() Severity,
ERROR_LINE () ErrorLine, ERROR_MESSAGE() Msg
set #result=2 --unexpected error occured
ROLLBACK
END CATCH

MSSQL nvarchar IF PROCEDURE exec with nvarchar input

I want know how to release IF with update and how to exec procedure with nvarchar input.
There are table Dictionary with 2 values ('Orig','Translated')
I need procedure that adds or replace "Trasnslated' depending on input. There must be 2 inputs, no more and no less. For example
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
UPDATE Dictionary
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
SET Dictionary.Translated=#Translated
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
SET #Orig = N'Orig'
SET #Translated = N'traslated'
EXEC Translate_Orig (#Orig,#Translated);
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
BEGIN
UPDATE Dictionary
SET Dictionary.Translated=#Translated
END
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
SET #Orig = N'Orig'
SET #Translated = N'traslated'
EXEC Translate_Orig (#Orig,#Translated);
Make sure you are just running the CREATE PROCEDURE through GO as a statement.
There EXEC that works fine. No brackets.
And "SET Dictionary.Translated=#Translated WHERE Dictionary.Orig=#Orig"
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
BEGIN
UPDATE Dictionary
SET Dictionary.Translated=#Translated WHERE Dictionary.Orig=#Orig
END
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
DECLARE #Orig nvarchar(32);
DECLARE #Translated nvarchar(32);
SET #Orig = N'Name'
SET #Translated = N'Name_Translated'
EXEC Translate_Orig #Orig,#Translated;

SQL Server stored procedure avoid cursor

I have the following SQL Server stored procedure :
BEGIN TRAN
CREATE TABLE #TempTable (
SampleOrderID int,
SampleOrderNo varchar(512),
ChallanNoAndChallanDate varchar(MAX)
)
CREATE NONCLUSTERED INDEX #IX_Temp2_1 ON #TempTable(SampleOrderID)
DECLARE
#SQL as varchar(MAX)
SET #SQL=' SELECT SampleOrderID, SampleOrderNo FROM SampleOrder WHERE SampleOrderID IN (37808,37805,37767,37571,37745,37772,37843,37394,37909,37905,37903) '
INSERT INTO #TempTable (SampleOrderID, SampleOrderNo)
EXEC (#SQL)
DECLARE
#SampleOrderID as int,
#ChallanNoAndChallanDate as varchar(max)
DECLARE Cur_AB1 CURSOR GLOBAL FORWARD_ONLY KEYSET FOR
SELECT SampleOrderID FROM #TempTable
OPEN Cur_AB1
FETCH NEXT FROM Cur_AB1 INTO #SampleOrderID
WHILE(##Fetch_Status <> -1)
BEGIN--2
SET #ChallanNoAndChallanDate=''
SELECT #ChallanNoAndChallanDate= COALESCE(#ChallanNoAndChallanDate+ ',', '') + CONVERT(VARCHAR(12),ChallanDate,106)+':'+ChallanNo FROM Challan WHERE OrderID =#SampleOrderID AND OrderType=2
UPDATE #TempTable SET ChallanNoAndChallanDate=#ChallanNoAndChallanDate WHERE SampleOrderID=#SampleOrderID
FETCH NEXT FROM Cur_AB1 INTO #SampleOrderID
END--2
CLOSE Cur_AB1
DEALLOCATE Cur_AB1
SELECT * FROM #TempTable
DROP TABLE #TempTable
COMMIT TRAN
Output :
SamID SamNo ChallanNoAndDaet
37394 37394 ,31 May 2012:151592
37571 37571 ,31 May 2012:151580
37745 37745 ,31 May 2012:151582
37767 37767 ,30 May 2012:151507,31 May 2012:151576
37772 37772 ,31 May 2012:151587
37805 37805 ,31 May 2012:151574
37808 37808 ,31 May 2012:151573
37843 37843 ,31 May 2012:151588
37903 37903 ,31 May 2012:151597
37905 37905 ,31 May 2012:151596
37909 37909 ,31 May 2012:151593
It works successfully for small volume of data but When i try to execute it on a Large volume (i.e. more then 500,000 record) my C# interface throws the time out exception.
Can anyone help me edit my stored procedure to avoid the cursor?
Thanks for response.
I use this to avoid cursor in everywhere I need
DECLARE #num_rows int
DECLARE #cnt int
DECLARE #selected int
DECLARE #table1 TABLE (Id int not null primary key identity(1,1), col1 int )
INSERT into #table1 (col1) SELECT col1 FROM table2
SET #num_rows=##ROWCOUNT
SET #cnt=0
WHILE #cnt<#num_rows
BEGIN
SET #cnt=#cnt+1
SELECT
#selected=col1
FROM #table1
WHERE Id=#cnt
--do your stuff here--
END
I usually use something like the following:
SELECT #SampleOrderID = MIN (SampleOrderID) FROM #TempTable
WHILE #SampleOrderID IS NOT NULL
BEGIN
SET #ChallanNoAndChallanDate=''
SELECT #ChallanNoAndChallanDate= COALESCE(#ChallanNoAndChallanDate+ ',', '') + CONVERT(VARCHAR(12),ChallanDate,106)+':'+ChallanNo FROM Challan WHERE OrderID =#SampleOrderID AND OrderType=2
UPDATE #TempTable SET ChallanNoAndChallanDate=#ChallanNoAndChallanDate WHERE SampleOrderID=#SampleOrderID
SELECT #SampleOrderID = MIN (SampleOrderID) FROM #TempTable WHERE SampleOrderID > #SampleOrderID
END
This code would replace the cursor stuff you have.

Resources