Passing Parameter in Stored Procedure 1 - sql

The SP is not treating #AgeBand parameter correctly.
How do i pass that parameter?
Alter Procedure sp_Dialer_Analysis
#AgeBand Varchar(50),
#Gender Varchar(50),
#Weekday Varchar(50)
AS
BEGIN
Select #AgeBand,#Gender,#Weekday,SUM(RPC)
from TableA a
left join TableB b
on a.[Contact Info] = b.MSI
where a.date >= '2017-01-01'
and b.gender = #Gender and b.AgeBand in (#AgeBand)
and DATENAME(WEEKDAY,a.date) = #Weekday
END
Exec sp_Dialer_Analysis "'50-54','55-59'",'F','Monday'
"'50-54','55-59'" is the issue.
Kindly suggest some alternative.

Condition b.AgeBand in (#AgeBand) will not work,
try using CHARINDEX(b.AgeBand,#AgeBand) > 0

You cannot pass an array in to stored procedure like that, doubly so using double quotes (")
Your best bet is to either run the procedure multiple times (yuck, performance hit) or split the array out using either a home brewed Split function or the new String_Split function in Sql Server 2016
Perhaps something like this (not tested, off the top of my head)
Alter Procedure sp_Dialer_Analysis
#AgeBand Varchar(50),
#Gender Varchar(50),
#Weekday Varchar(50)
AS
BEGIN
Select #AgeBand,#Gender,#Weekday,SUM(RPC)
from TableA a
Cross Apply String_Split(#AgeBand, ',') As s
left join TableB b
on a.[Contact Info] = b.MSI
where a.date >= '2017-01-01'
and b.gender = #Gender
And b.ageband = s.value
and DATENAME(WEEKDAY,a.date) = #Weekday
END
Exec sp_Dialer_Analysis '50-54,55-59','F','Monday'
Not tried SHD's answer but prima-facia I think it deserves merit... and may be a better answer

I think OP is asking about escape characters.
Please try this : Exec sp_Dialer_Analysis '''50-54'',''55-59''','F','Monday'

Related

Not Supplying Value to Parameter In SP throwing Error- sql server 2008

i have a SP as given below.
CREATE PROCEDURE CHKIndex
#count DECIMAL(10,2) ,
#ID INT = NULL,
#DATE VARCHAR (MAX)
AS
SELECT DISTINCT
COL1,
COL2
FROM
(
SELECT COL1,COL2,rn
FROM TAB1 T1
INNER JOIN TAB2 T2 ON T1.SNO = T2.PNO
)t
where t.rn = 1
AND DATE = #DATE
AND t.ID = #ID
GO
When i executed like EXEC CHKIndex 20,71,22082016
It is working fine when i supplied value for all three parameter,
but
starts giving error when not supplied any value for date as
Procedure or function 'uspECP_Competitive_Index' expects parameter '#DATE', which was not supplied.
i am trying to modify in such a way that if user want to see data based on only #count and #ID
they can able to do so.
if i assign default NULL for #date even than not getting any records in the output.
Please suggest.
A quick and dirty way could be to modify your where clause to be:
WHERE
t.rn = 1
AND DATE = ISNULL(#DATE, DATE)
AND t.ID = #ID
A couple of other points to note are
You are not using the parameter #count
It would make much more sense to use the datetime type for your #Date parameter, rather than varchar(max).

Receiving 0 results from my stored procedure

I am trying to run a stored procedure in SQL Server and I'm getting 0 results. I initially had this running just fine (attached to SSRS) but then users requested a multiple value input for the ProviderName parameter and I realized I was in over my head. I contacted our vendor who provided a KnowledgeBase article which I essentially copied and pasted right in. See below...
ALTER PROCEDURE [dbo].[Test]
(#dStartDate DATETIME
,#dEndDate DATETIME
,#nProviderName VARCHAR(MAX)
,#nAllProviderName VARCHAR(1) = 'N')
AS
BEGIN
DECLARE #dStart AS DATETIME = CONVERT(DATETIME,CONVERT(DATE,#dStartDate)) ;
DECLARE #dEnd AS DATETIME = DATEADD(ms,-3, DATEADD(day,1,CONVERT(DATETIME,CONVERT(DATE,#dEndDate))))
DECLARE #cProviderName AS VARCHAR(MAX) = #nProviderName
DECLARE #tProviderName AS TABLE (PCPID VARCHAR(MAX) NOT NULL);
IF UPPER(#nAllProviderName) = 'N'
BEGIN
INSERT INTO #tPCPName ( PCPID )
SELECT LTRIM(RTRIM(Item))
FROM [dbo].[Auto_Split]('|',#nProviderName ) ;
END;
SELECT ...
WHERE
([TestMnemonic] = 'GLU' OR
[TestMnemonic] = '%HA1C')
AND [Status] != 'DIS CLI'
AND [TextLine] IS NOT NULL
AND [DateTime] BETWEEN #dStart AND #dEnd
AND (UPPER(#nAllProviderName) = 'Y' OR
[PCPID] COLLATE DATABASE_DEFAULT
IN (SELECT PCPID FROM #tProviderName ) ) ;
END
So if I comment out the last 4 lines of code it runs fine. So it's something in that last bit (or something at the top?) I'm hoping this is a quick fix, any and all help is appreciated!
Thanks!
I'm curious about the Collate statement at the bottom. What us your system default and do you really need that when comparing against a temp table you made?
Without Collate
OR [PCPID] IN (SELECT PCPID FROM #tProviderN
I think you need to switch #tProviderName with #tPCPName in last line.
If your #nAllProviderName is "N" than you search PCPID from memory table called #tPCPName
And there is some code missing, so I didn't get the full picture .. If you could put your from and joins statments and your missing "where clause", when your #nAllProviderName is "Y"
and you don't need this part in your SQL
IF UPPER(#nAllProviderName) = 'N'
BEGIN
INSERT INTO #tPCPName ( PCPID )
SELECT LTRIM(RTRIM(Item))
FROM [dbo].[Auto_Split]('|',#nProviderName ) ;
END
if you switch your last line with
AND (UPPER(#nAllProviderName) = 'Y' OR
[PCPID] COLLATE DATABASE_DEFAULT
IN ( SELECT LTRIM(RTRIM(Item))
FROM [dbo].[Auto_Split]('|',#nProviderName ) ) ) ;

TSQL Number of reads significantly different after query and stored procedure execution

After query optimization I got results that are ok and I wanted to alter stored procedure, but got much worst results after SP execution, than it was after query execution!
Firstly, I think at number of reads. What can be reason for so different results?
Query is identical like in SP, only difference is that in query I declared parameter, but in SP that was input parameter. Value that is set to parameter is also same. To avoid 'recorded data' first I recompiled SP and after that done DROP and CREATE, but results were also much different.
Query is like this (table and column names are changed because of simplification, and number of columns is reduced):
DECLARE #Var1 varchar(20)
SET #Var1 = #Var1 + '%'
DECLARE #Var2 TIMESTAMP
SELECT #Var2 = CONVERT(TIMESTAMP, ID, 0)
FROM
X_TIMESTAMPS (NOLOCK)
WHERE
TABLE = 'T1'
declare #Var3 varbinary(8)
SELECT #Var3 = max(IdTimeStamps)
FROM
T1 (NOLOCK)
SELECT o.c1
, o.c2
, o.c3
, v.c4
, v.c5
, p.c6
, p.c7
, va.c8
, isnull(s.c9, '') AS c9
, CASE o.c10
WHEN 1 THEN
0
ELSE
1
END c10
, o.c11
FROM
T1 o (NOLOCK)
JOIN T2 p (NOLOCK)
ON o.c1 = p.c12
JOIN T3 i (NOLOCK)
ON (o.c13 = i.c14)
JOIN T4 v (NOLOCK)
ON (v.c4 = i.c15)
LEFT JOIN T5 s (NOLOCK)
ON (o.c16 = s.c17)
JOIN T6 va (NOLOCK)
ON o.c11 = va.c18
WHERE
o.c1 LIKE #Var1
AND o.c2 > #Var2
And procedure is like this:
CREATE PROCEDURE [dbo].[SP1] #Var1 varchar(20) =''
WITH RECOMPILE
AS
BEGIN
PREVIOUS QUERY WITHOUT DECLARATION FOR #Var1
END
TnX in advance!
Nemanja
It's because different execution plans are used for query with constants and sp with parameeters. You can try a few tricks
Create inline table function and try it
create function sf_test
(
#param1 int
)
returns table
as
return
your query using #in_param1
or
declare additional parameters in your procedure like this
create procedure sp_test
(
#param1 int
)
as
begin
declare #in_param1 int
select #in_param1 = #param1
your query using #in_param1
end
you can also try using option with recompile in your procedure, or use dynamic SQL
This is almost certainly a parameter sniffing issue. Personally, I liked the dummy variable option to work around this issue and (only when I run into this problem) create variable(s) that are set to the value of the incoming parameter(s).

UDF inside an SP performance issue on ms sql

I have the following SP
PROCEDURE [dbo].[order_s]
(
#user Uniqueidentifier
)
AS
BEGIN
SET NOCOUNT ON;
SELECT
id,
name,
[begin],
[end]
FROM
orders
WHERE
#user = dbo.hasAccess(#user,id,'select')
END
This SP calls a this UDF
FUNCTION [dbo].[hasAccess]
(
#user uniqueidentifier,
#orderId bigint,
#AccessType nchar(10)
)
RETURNS uniqueidentifier
AS
BEGIN
DECLARE #Result uniqueidentifier
SELECT
Top 1 #Result = [user]
FROM
access
WHERE
orderId = #orderId AND
[user] = #user AND
role >= CASE
WHEN #AccessType = 'select' then 1
WHEN #AccessType = 'insert' then 5
WHEN #AccessType = 'update' then 7
WHEN #AccessType = 'delete' then 10
END
RETURN #Result
END
My question is, calling an UDF from an SP have any performance issues?
Is there a better way to achieve the same functionality?
Thanks for your advise...
Yes this is a bad use of scalar UDFs. This should perform much better.
SELECT
id,
name,
[begin],
[end]
FROM
orders o
WHERE EXISTS(
SELECT *
FROM access
WHERE orderId = o.id AND [user] = #user AND role >= 1
)
Some discussion on Scalar UDFs and performance here
As always with questions re: performance- profile, profile, profile.
Other than that, the only reason I can see that a UDF would cause any performance problems was if it, itself, was particularly inefficient. It should be no less efficient than calling GetDate() in a Stored Proc.

Executing a WHERE clause conditionally in SQL

I have an application on a SQL Server 2008 database. This database has a stored procedure that queries one of the tables. This stored procedure takes two parameters: userName and ID
The userName parameter will always be passed. However, the ID field will either be NULL or an actual value. If the value is something other than NULL, I need to consider it in the WHERE clause of my query. Unfortunately, I'm not positive how to do this. Currently, I'm trying
SELECT
*
FROM
TaskTicket t
WHERE
t.[UserName]=#userName AND
-- This is where I am stumped
Thank you for your help!
SELECT
*
FROM
TaskTicket t
WHERE
t.[UserName]=#userName
AND (#ID IS NULL OR t.[ID] = #ID)
Try this:
SELECT
*
FROM
TaskTicket t
WHERE
t.[UserName]=#userName AND
(#ID is null
or -- replace this comment with your logic
)
Group the conditionals together
select *
from TaskTicket t
Where t.[UserName]=#userName AND
((t.Id is null and (conditions_when_id_is_null))
or
(t.Id is not null and (conditions_when_id_is_not_null)))
SELECT
<column list>
FROM
TaskTicket T
WHERE
T.[UserName] = #username AND
(T.id = #id OR #id IS NULL)
Just be aware that this may cause a non-optimal query plan in some cases. That's probably not a big deal in this case unless your table is huge and you don't have an index on UserName and ID.
Hopefully more efficient than using an OR condition:
SELECT
*
FROM
TaskTicket t
WHERE
t.[UserName]=#userName AND
t.[ID] LIKE COALESCE(#ID,'%')
NB: will only work if ID is a non-NULLable, character field. (You can use CAST and COALESCE on t.[ID] otherwise, but then it's unlikely to be more efficient than an OR condition.)
Alternatively, use dynamic SQL in your stored procedure to completely omit the t.[ID] condition, if #ID is NULL.
declare #SQL nvarchar(max)
declare #WHERE_ID nvarchar(20)
set #WHERE_ID =
(
CASE
WHEN #ID is null THEN ''
ELSE ' AND ID = ' + CAST(#ID as nvarchar(10))
END
)
set #SQL = 'SELECT * FROM TaskTicket WHERE UserName = ' + #userName + #WHERE_ID
EXEC #SQL
Create procedure Procedure1
(
#Param1 nvarchar(100)=null,
)
AS
BEGIN
SELECT
ColumnName1,ColumneName2
FROM TableName
WHERE
(#Param1 IS NULL OR ColumnName1=#Param1)
END