I have a stored procedure like this:
ALTER procedure [dbo].[delivary1]
#dedate nvarchar(100),
#carid nvarchar(100)
AS
BEGIN
declare #transid int
declare #status int
declare #count int,
#currentdate nvarchar(50)
select #currentdate = GETDATE()
SET NOCOUNT ON;
select #count = count(*)
from Transaction_tbl
where TBarcode = #carid
if #count=0
begin
return -1
end
else
begin
select #status = t1.Status
from Transaction_tbl t1
where t1.TBarcode = #carid
if #status = 4
begin
select #transid = t.transactID
from Transaction_tbl t
where t.TBarcode = #carid
update Transaction_tbl
set DelDate = '' + #currentdate + '', Status=5
where TBarcode = #carid
update KHanger_tbl
set Delivered = 1
where transactid = #transid
return 4
end
if #status = 5
begin
return 5
end
if #status=0
begin
return 0
end
if #status=1
begin
return 1
end
if #status = 2
begin
return 2
end
if #status = 3
begin
return 3
end
end
end
My database has more than 10 lack of records. Sometimes this takes a long time to execute..
Is there any way to write this stored procedure any simpler than this way?
Any help is very much appreciated.
Thanks in advance
Execution plan of my stored procedure
Well, lets get serious.
Your end of the SP is redundant, jsut return #status.
The update is badly programming in using string for the date, but that is not relevant forspeed.
The speed is just in the Select. Interesting enough you miss an index which is shown in the screenshot you sent - which tells me you never bothered to even look at it before posting.
Please start considering indices and planning them. In your case you defintiely miss an index.
You do not need to return the value for status, it just doent make any sense,
also add the missing index which suggests you will get around 93% improvement in your performance.
you can write this procedure with an OUTPUT parameter something like this...
ALTER procedure [dbo].[delivary1]
#dedate nvarchar(100),
#carid nvarchar(100),
#status INT OUTPUT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #transid int, #count int,#currentdate nvarchar(50)
SET #currentdate = GETDATE();
select #count = count(*) from Transaction_tbl where TBarcode = #carid
if (#count = 0)
begin
SET #status = -1;
end
else
begin
select #status = t1.[Status] from Transaction_tbl t1 where t1.TBarcode = #carid
if (#status = 4)
begin
select #transid = t.transactID
from Transaction_tbl t
where t.TBarcode = #carid
update Transaction_tbl
set DelDate = '' + #currentdate + ''
, [Status] = 5
where TBarcode = #carid
update KHanger_tbl
set Delivered=1
where transactid = #transid
end
end
END
How to add Missing Index
Go to your execution plan Right Click where it is showing Missing Index, and the click on the Missing Index Details
And it will Give you the Index Definition in a new query window that SQL Server thinks will help it to improve the performance of this query. All you need to do now is Just execute the Statement and it will create the index for you.
Index Definition
/*
Missing Index Details from SQLQuery1.sql - ALI-PC.AdventureWorks2008R2 (My Server\UserName (59))
The Query Processor estimates that implementing the following index could improve the query cost by 95.7414%.
*/
/*
USE [AdventureWorks2008R2]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [Sales].[SalesOrderHeader] ([TerritoryID],[ShipMethodID],[SubTotal],[Freight])
INCLUDE ([SalesOrderNumber],[CustomerID])
GO
*/
Related
This is my stored procedure, this is working:
/*
#CRM_Ref - This is the only required input port for this SP
#North_Ref - Output port, returns the North_Ref for a valid CRM_Ref input
#Output_Message - Output port, Returns the output of the SP, either 'Success' or 'North_Ref not found'
*/
ALTER PROCEDURE [dbo].sp_Get_North_Reference
#CRM_Ref NVARCHAR(255),
#North_Ref VARCHAR(255) OUTPUT,
#Output_Message VARCHAR(255) OUTPUT
AS
DECLARE #var_North_Ref VARCHAR(255); -- Variable used to store the North_Ref
DECLARE #var_Output_Message VARCHAR(255); -- Variable to carry the Output_Message
DECLARE #COUNTER INT; -- Counter for the amount of times the while loop should run
SET #COUNTER = 100;
-- Loop will run 10 times with a 10 second delay between each loop
WHILE #COUNTER >= 1
BEGIN
SET #var_North_Ref = (SELECT TOP 1 North_Ref FROM DEV.dbo.Address__ADDRESS WHERE CRM_Ref = #CRM_Ref ORDER BY PUBLICATION_INSTANCE_DATE DESC)
IF #var_North_Ref IS NULL
BEGIN
SET #COUNTER = #COUNTER - 1; -- Counter is decremented by 1
SET #var_Output_Message = 'North_Ref not found';
WAITFOR DELAY '00:00:10'; -- Wait is triggered if no North_Ref is found
END
ELSE
BEGIN
SET #COUNTER = 0; -- Counter is set to 0 to end the while loop
SET #var_Output_Message = 'Success';
END
END
SET #Output_Message = #var_Output_Message; -- Format Output_Message
SET #North_Ref = #var_North_Ref; -- Format North_Ref
;
GO
I would like to add another parameter into this stored procedure (#TableName VARCHAR(255)) which I want to pass to the SELECT statement.
So I would like something like:
SELECT TOP 1 North_Ref
FROM #Table_Name
WHERE CRM_Ref = #CRM_Ref
ORDER BY PUBLICATION_INSTANCE_DATE DESC
I have tried doing this as it is above but I am getting errors as I don't think you can use parameters as a table name in stored procedures
how about try this concept :
CREATE TABLE #tempTable(abc int);
declare #strSQL nvarchar(255)
SET #strSQL = 'insert into #tempTable select 123'
EXEC sp_executesql #strSQL
declare #abc int
select top 1 #abc = abc from #tempTable
drop table #tempTable
select #abc
For example:
CREATE PROCEDURE [dbo].[procGetTable]
(
#SetUPDLOCK BIT,
#RecordId BigInt
)
AS
SELECT *
FROM MYTABLE WITH (CASE WHEN #SetUPDLOCK = 1 THEN 'UPDLOCK' ELSE '' END)
WHERE MYTABLE.RecordId = #RecordId
/* P.S. I Know the above does not work it conceptual only */
CREATE PROCEDURE [dbo].[procGetTable]
#SetUPDLOCK BIT,
#RecordId BigInt
AS
BEGIN
SET NOCOUNT ON;
IF (#SetUPDLOCK = 1 )
BEGIN
SELECT *
FROM MYTABLE WITH (UPDLOCK)
WHERE MYTABLE.RecordId = #RecordId
END
ELSE
BEGIN
SELECT *
FROM MYTABLE
WHERE MYTABLE.RecordId = #RecordId
END
END
I am using Dynamic SQL to retrieve datasets from multiple tables in order to monitor our daily data extraction from the iSeries system.
I have the below dynamic SQL code which works fine, but I want to only run the data to get each tables records if data has been extracted for the day
-- Create a table variable to store user data
DECLARE #myTable TABLE
(
docID INT IDENTITY(1,1),
docRef VARCHAR(50),
letterDir VARCHAR(500)
);
insert #myTable select docRef, saveDir from alpsMaster.dbo.uConfigData
-- Get the number of rows in the looping table
DECLARE #RowCount INT, #SQL nvarchar(500), #LoopSQL nvarchar(2000), #Date varchar(20)
set #Date='29 Oct 2013'
SET #RowCount = (SELECT COUNT(docID) FROM #myTable)
-- Declare an iterator
DECLARE #I INT
-- Initialize the iterator
SET #I = 1
-- Loop through the rows of a table #myTable
WHILE (#I <= #RowCount)
BEGIN
-- Declare variables to hold the data which we get after looping each record
DECLARE #docRef VARCHAR(10), #saveDir VARCHAR(500)
-- Get the data from table and set to variables
SELECT #docRef = docref FROM #myTable WHERE docID = #I
SELECT #saveDir = letterDir FROM #myTable WHERE docID = #I
-- Display the looped data
--PRINT 'Row No = ' + CONVERT(VARCHAR(2), #I) + '; docRef = ' + #docRef
select #LoopSQL='
use alpsProduction;
declare #SQL nvarchar(500);
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(''[dbo].['+#docRef+']''))
begin
if exists(select * from sys.columns
where Name = ''YPTMPID'' and Object_ID = OBJECT_ID(''[dbo].['+#docRef+']''))
begin
set #SQL=''SELECT t.template_name,'''''+#saveDir+''''', Y.*
FROM [alpsProduction].[dbo].'+#docRef+' Y, alpsMaster.dbo.uDocumentTemplates t
where DTEINP='''''+#Date+''''' and t.template_Id=y.YPTMPID and t.docRef='''''+#docRef+'''''''
exec sp_executesql #SQL
end
end
'
--print #LoopSQL
exec sp_executesql #LoopSQL
-- Increment the iterator
SET #I = #I + 1
END
so I tried using
IF ##ROWCOUNT >0
Begin
exec sp_executesql #SQL
end
but it seems to never populate the ##Rowcount.
Whats the best way to only run that statement (exec sp_executesql #SQL) if the current table (identified by #docRef) has records in it for todays date (in the format dd mmm yyyy)
Create job to execute a sql script in which u must check inserted data on current day then execute your sp. like this.
IF EXISTS ( SELECT * FROM #TABLE T WHERE DATEDIFF(DD, GETUTCDATE(), T.CREATEDON) = 0 )
BEGIN
EXEC SP_EXECUTESQL #SQL
END
I have created a stored procedure to retrieve some details based on the certain values passed to a parameter. THis requires switching between the SQLs to be executed by stored procedure. Following is the code:
USE [DFS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[DAFS]
#EmailID Nvarchar(128),
#clientID int,
#userType Varchar(50),
#Success numeric output,
#msg varchar(100) output
AS
BEGIN
if #userType='Normal User'
IF EXISTS (SELECT 1 FROM dbo.Allcdn
WHERE EmailID = #EmailID AND ClientID = #clientID)
begin
set #Success=0
set #msg='Carry on ....'
end
else
begin
set #Success=6
set #msg='Not allowed ...'
END
end
else
Begin
IF EXISTS (SELECT 1 FROM dbo.Alcon
WHERE EmailID = #EmailID AND ClientID = #clientID)
BEGIN
set #Success=0
set #msg='Carry on...'
END
END
End
end
END
The entire processing is based on the variable #userType. Not sure why the stored procedure is not compiling.
Formatting is your friend, just with a quick glance, it appears you have too many ENDs -- See SQL Fiddle with working Demo:
CREATE PROCEDURE [dbo].[DAFS]
#EmailID Nvarchar(128),
#clientID int,
#userType Varchar(50),
#Success numeric output,
#msg varchar(100) output
AS
BEGIN
if #userType='Normal User'
IF EXISTS (SELECT 1 FROM dbo.Allcdn
WHERE EmailID = #EmailID AND ClientID = #clientID)
begin
set #Success=0
set #msg='Carry on ....'
end
else
begin
set #Success=6
set #msg='Not allowed ...'
END
else
Begin
IF EXISTS (SELECT 1 FROM dbo.Alcon
WHERE EmailID = #EmailID AND ClientID = #clientID)
BEGIN
set #Success=0
set #msg='Carry on...'
END
END
end
I have a table named Table1 which contains an ID and TimeStamp.
Table structure
ID TimeStamp
1 0x0000000000047509
But when I compare the combination of these fields, it always shows false. What is the reason for this?
My Query is :
DECLARE #ID int
DECLARE #TimeStamp timestamp
SET #ID = 1
SET #TimeStamp = 0x0000000000047509
If EXISTS(SELECT 1 FROM Table1 WHERE ID = #ID AND TimeStamP = #TimeStamp)
BEGIN
SELECT 1 AS RetVal
END
ELSE
BEGIN
SELECT -1 AS RetVal
END
My stored procedure is as follows
CREATE PROCEDURE [dbo].[Check] (
#XMLDoc ntext
)AS
BEGIN
SET NOCOUNT ON
SET XACT_ABORT ON
DECLARE #ID bigint
DECLARE #TimeStamp timestamp
DECLARE #hDoc int
EXEC sp_xml_PrepareDocument #hDoc OUT, #XMLDoc
SELECT #ID = ID
,#TimeStamp = [TimeStamp]
FROM OPENXML (#hdoc,'/XML')
WITH ( ID bigint 'ID'
,[TimeStamp] timestamp 'TStamp')
IF ##ERROR<>0
BEGIN
EXEC sp_xml_RemoveDocument #hDoc
SELECT -620 AS RetVal
RETURN
END
IF NOT EXISTS(SELECT 1 FROM Table1 WHERE ID= #ID AND Timestamp = #TimeStamp )
BEGIN
SELECT -1 AS RetVal
END
ELSE
BEGIN
SELECT 1 AS RetVal
END
END
That's odd, the query works fine for me in SQL Server 2005, compatibility mode 80.
The only thing that jumps out to me is that Timestamp is a reserved word, so to be on the safe side you might want to add brackets around Timestamp to escape it as follows:
If EXISTS(SELECT 1 FROM Table1 WHERE [ID] = #ID AND [TimeStamP] = #TimeStamp) ...
#TimeStamp is not being resolved correctly from the XML. Try CASTing it to binary(8).
The stored proc does not match the query you posted earlier