Dyanamic SQL Query not working - sql

I have a table called procedure look up which stores medical procedures
and have multiple company table for which i had to calculate the procedure fees so i had created a dynamic query for it
below is the query
declare #TableProviderName varchar(500)
,#SQLQuery1 nvarchar(max)
,#MaxRecordSize Int
,#Name varchar(250) = null
,#code varchar(50) = null
set #Name = 'sug'
set #TableProviderName = 'PRD_Tata_Details'
set #MaxRecordSize = 50
set #SQLQuery1 = '
;WITH CTE_Procedure AS
(
select top (#MaxRecordSize1)
GPL_ID_PK as ProcedureID
,GPL_ProcedureType as ProcedureType
,GPL_Code as ProcedureCode
,coalesce(Name,GPL_Name,null)as Procedurename
,GPL_CurrencyType_FK as CurrencyType
,ISNULL(GPL_Description,''NIL'') as ProcedureDescription
,ISNULL(GPL_PatientInstruction,''NIL'')as PatientInstructions
,GPL_ProcedureCategory_FK as ProcedureCategory
,GPL_CategorySpecialization_FK as ProcedureSpecialization
,coalesce(PatientPayable,GPL_ProcedureFee,0) as PatientPayable
,0 as InsurancePayable
,0 as InsuranceDiscount
,1 as ProcedureCount
,0 as IndBillingStatus
,Case
when GeneralProcedureID is not null then ''Insurance Supported''
else ''Insurance not Supported''
end as InsuranceStatus
,ROW_NUMBER( ) OVER ( ORDER BY GPL_Name ASC) as RowNumber
from
dbo.PRD_GeneralProcedure_Lookup
left join '
+ #TableProviderName +
'
on
GeneralProcedureID = GPL_ID_PK
where
GPL_ProcedureType = #ProcedureType1
and
(#Name1 is null or GPL_Name like %#Name1%)
and
(#code1 is null or GPL_Code like %#code1%)
)
Select
*
from
CTE_Procedure
'
Execute sp_executesql #SQLQuery1, N'#MaxRecordSize1 int, #ProcedureType1 tinyint,#Name1 varchar(250)
, #code varchar(50)' ,#MaxRecordSize1 = #MaxRecordSize, #ProcedureType1 = 1 , #Name1 = #Name, #code1 = #code
but when executing error occurs saying
"Incorrect syntax near '#Name1'"
can anyone help me with that where condition side issue

I think It may have something to do with your like statement and the way you pass the parameter.
Have a look at this question Parameters & Like statement.
#Name1 = "'%yourvalue%'"

Related

I am having the error with a Subquery returning more than one value. How do I reduce to one?

At the very end of the Stored procedure a SELECT statement is made to display the contents of the Table including function that will simultaneously populate fields in the table.
Here is the Select Statement:
IF #type = 'SH'
SELECT DISTINCT *
FROM #History
ORDER BY 1, 2, 3, 4, 5
ELSE
SELECT DISTINCT AmhazName
,Activity
,ServiceName
,Sarid
,PerformedDate
,UserRole
,Details
,dbo.ufn_SarHistoryActionText(sarid, status, performeddate) AS [ActionText]
,FullName
,CategoryDescription
,StatusDescription
,ActionPerformed
,Case
when Details like '%ProjManagerId%'
Then dbo.ufn_GetUserForHistoryReport (PerformedDate, SarId, '%ProjManagerId%')
Else
--when Details like '%UserId%'
dbo.ufn_GetUserForHistoryReport (PerformedDate, SarId, '%UserId%')
--(select 'no user') as [AssignedUser]
End as [AssignedUser]
--,dbo.ufn_GetPMForHistoryReport(PerformedDate, SarId) as [AssignedUser]
FROM #history
ORDER BY 1, 2, 3, 4, 5
DROP TABLE #Historyw
Here is the function I believe is causing problems:
ALTER FUNCTION [dbo].[ufn_SarHistoryActionText]
(
-- Add the parameters for the function here
#sarID int
, #status varchar(6)
, #statusDate datetime
)
RETURNS varchar(100)
AS
BEGIN
-- Declare the return variable here
DECLARE #Result varchar(100)
set #Result = (
SELECT C.ActionText
from LuStatusChange as C
WHERE C.FromStatus = dbo.ufn_SarHistoryPriorStatus(#sarID,#status,#statusDate)
AND C.ToStatus = #status
)
-- Return the result of the function
RETURN #Result
END
GO
As I debug and walk through loads of values, I haven't come across anything that resulted in multiple values. maybe I'm missing something.
Add TOP 1 in the select inside the function:
SELECT TOP 1 C.ActionText
Can you replace
set #Result = (
SELECT C.ActionText
from LuStatusChange as C
WHERE C.FromStatus = dbo.ufn_SarHistoryPriorStatus(#sarID,#status,#statusDate)
AND C.ToStatus = #status
)
as below:
#Result ***IN*** (
SELECT C.ActionText
from LuStatusChange as C
WHERE C.FromStatus = dbo.ufn_SarHistoryPriorStatus(#sarID,#status,#statusDate)
AND C.ToStatus = #status
)
If functionally your query should not written more than 1 row, something is wrong with your query.

Sending same parameter twice in exec

I have a simple stored procedure like this:
[dbo].[getStatusList]
#Extended NVARCHAR(255) = 'Project Status',
#Exclude NVARCHAR(255) = '',
#All BIT = 0
AS
SET NOCOUNT ON
IF (#All = 0)
BEGIN
SELECT
[GeneralKey],
[Label]
FROM
[General]
WHERE
[Extended] = #Extended
AND [Label] <> #Exclude
ORDER BY
[OrderID];
END
ELSE
BEGIN
IF (#All = 1)
BEGIN
SELECT
0 AS [GeneralKey],
'Any' AS [Label],
0 AS [OrderID]
UNION ALL
SELECT
[GeneralKey],
[Label],
[OrderID]
FROM
[General]
WHERE
[Extended] = #Extended
AND [Label] <> #Exclude
ORDER BY
[OrderID];
END
END
That I want to do is exec this stored procedure sending twice #Extended parameter like:
exec getStatusList #Extended = 'title1' AND #Extended = 'title2'
It is not possible to do something like this on exec? To only way to solve this is to add another parameter to stored procedure?
Update
As comments below mentioned, I tried this:
CREATE OR ALTER PROCEDURE usp_Get_StatusListByDesignType
-- Add the parameters for the stored procedure here
#Extended NVARCHAR(MAX),
#Exclude NVARCHAR(255) = '',
#All BIT = 0
AS
SET NOCOUNT ON
IF (#All = 0)
BEGIN
DECLARE #Parameter1 VARCHAR(50)
DECLARE #Parameter2 VARCHAR(50)
;WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) rn
FROM
STRING_SPLIT (#Extended,',')
)
SELECT
#Parameter1 = MAX(CASE WHEN rn = 1 THEN VALUE END),
#Parameter2 = MAX(CASE WHEN rn = 2 THEN VALUE END)
FROM
CTE
SELECT
[GeneralKey], [Label]
FROM
[General]
WHERE
[Extended] IN (SELECT #Parameter1, #Parameter2)
AND [Label] <> #Exclude
ORDER BY
[OrderID];
END
ELSE
BEGIN
IF (#All = 1)
BEGIN
SELECT
0 AS [GeneralKey],
'Any' AS [Label],
0 AS [OrderID]
UNION ALL
SELECT
[GeneralKey],
[Label],
[OrderID]
FROM
[General]
WHERE
[Extended] IN (SELECT #Parameter1, #Parameter2)
AND [Label] <> #Exclude
ORDER BY
[OrderID];
END
RETURN;
But I get this error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
You can let pass your parameter like para1Val1,para1Val2... connected with , comma.
then use STRING_SPLIT function to split it from , comma then get the parameter.
DECLARE #Extended varchar(max)='title1,titl2'
Here is a simple
DECLARE #Extended varchar(max)='title1,titl2'
select *,row_number() over(order by (select NULL)) rn
from STRING_SPLIT (#Extended,',')
Then you can set parameters in SP.
declare parameters variable, then use row_number make your parameter row number.
next step use condition aggregate function set the parameter in select clause.
declare #parameter1 varchar(50)
declare #parameter2 varchar(50)
;with cte as (
select *,row_number() over(order by (select NULL)) rn
from STRING_SPLIT (#Extended,',')
)
select #parameter1 = MAX(case when rn = 1 then value end),
#parameter2 = MAX(case when rn = 2 then value end)
from cte
sqlfiddle
This method :
exec getStatusList #Extended='title1' AND #Extended = 'title2'
it's not going to work at all as a parameter or a variable in general can only hold one value and nothing more. So, you can't do that unless you execute the store procedure twice and specify the parameters on each one of them. Or you may use loops to do it. But i'm not fan of loops and I always suggests to avoid them as much as possible.
The method that I see it fits your situation is a TVP with some modifications on the store procedure itself.
So, you'll pass the values in comma separate values in #Extended and from the store procedure you'll use IN() and NOT IN() instead of = and <> this will extend it to have more values to compare rather than one value.
Then you can use XML to split the values and turn them into rows.
So we will use this :
SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)')))
FROM (
SELECT CAST('<XMLRoot><RowData>' + REPLACE(#Extended,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) Extended
) D
CROSS APPLY Extended.nodes('/XMLRoot/RowData')m(n)
You can inject it directly into the store procedure with modifying the operators that I mentioned above, and it will work just fine. but for the code reuse, we will use it as TVP.
CREATE FUNCTION SplitToRows
(
#Extended VARCHAR(MAX)
)
RETURNS TABLE
AS
RETURN
(
SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) Extended
FROM (
SELECT CAST('<XMLRoot><RowData>' + REPLACE(#Extended,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) Extended
) D
CROSS APPLY Extended.nodes('/XMLRoot/RowData')m(n)
)
Now, you can modify the store procedure to the following :
[dbo].[getStatusList]
#Extended NVARCHAR(255) = 'Project Status'
, #Exclude NVARCHAR(255) = ''
, #All BIT = 0
AS
SET NOCOUNT ON
IF(#All = 0)
BEGIN
SELECT
[GeneralKey]
, [Label]
FROM [General]
WHERE
[Extended] IN( SELECT * FROM dbo.SplitToRows(#Extended) )
AND [Label] NOT IN( SELECT * FROM dbo.SplitToRows(#Exclude) )
ORDER BY
[OrderID];
END
ELSE
BEGIN
IF(#All = 1)
BEGIN
SELECT
0 AS [GeneralKey]
, 'Any' AS [Label]
, 0 AS [OrderID]
UNION ALL
SELECT
[GeneralKey]
, [Label]
, [OrderID]
FROM [General]
WHERE
[Extended] IN( SELECT * FROM dbo.SplitToRows(#Extended) )
AND [Label] NOT IN( SELECT * FROM dbo.SplitToRows(#Exclude) )
ORDER BY
[OrderID];
END
END
Now, you can pass multiple separated values in #Extended and #Exclude at the same time like this :
#Extended = 'title1, title2, title3'
#Exclude = 'title5, title8'
so both parameters will use the same method.

select statement blocking another select statement

I'm not quite sure what is happening here. I have an alert that goes out if #StoreOrderID >1.
It goes like this:
declare #message varchar(1000)
#StoreID --(retrieves info from StoreOrders tables)
BEGIN
select #message = 'store' + storename
from StoreOrders as so
join Distributors as ds
on ds.DistributorID = so.StoreOrderID
where ds.SDistributorID = #StoreID
select #message = brandID
from StoreOrders a
join Brandtitles as b
on b.branddistributorID = a.StoreOrderID
where b.brandNum = #DistributorNum and b.branddistributorID = #StoreID
select #message = 'date' + ISNULL(convert(varchar, #Date),'')
select #message = 'cost' + ISNULL(Convert(varchar,#Cost),'')
Also for some reason if i try to concatenate a string unto the 'brand' select it throws an error. I can do it for the 'storename'. I think this may have something to do with it.
If I comment out the storename select it will send the alert for brandID, if I comment out the other one it does the other one. However, if I leave both of them, it will only show one of them. What am I doing wrong here?
As a user mentioned in the comments, you are overwriting the #message variable everytime you assign it a new value, you are not concatenating any of the values. A much simpler and cleaner way would be something like....
declare #message varchar(1000)
#StoreID [DataType]--(retrieves info from StoreOrders tables)
BEGIN
Declare #storename VARCHAR(100)
, #brandID VARCHAR(100)
, #Date VARCHAR(100)
, #Cost VARCHAR(100);
select #storename = 'store' + ISNULL(storename , 'Unknown')
from StoreOrders as so
join Distributors as ds
on ds.DistributorID = so.StoreOrderID
where ds.SDistributorID = #StoreID;
select #brandID = ISNULL(CAST( brandID AS VARCHAR(100) , 'Unknown')
from StoreOrders a
join Brandtitles as b
on b.branddistributorID = a.StoreOrderID
where b.brandNum = #DistributorNum
and b.branddistributorID = #StoreID;
select #Date = 'date' + ISNULL(convert(varchar, #Date),'');
select #Cost = 'cost' + ISNULL(Convert(varchar,#Cost),'');
SET #message = #storename + #brandID + #Date + #Cost;
I Assume the code "alerting" the message is after the snipped you showed.
Then, as you use the same variable #message as target for both assignments, you overwrite the contents you assigned the first time when doing the second assignment. Only the values from the second assignment make it to the "alerting" command.
Use two different variables or "alert" your message after each assignment.

How to filter data based on different values of a column in sql server

I am stuck at a point.
I want to select based on the column entitytype if entitytype value is Booking or JOb then it will filter on its basis but if it is null or empty string('') then i want it to return all the rows containing jobs and bookings
create proc spproc
#entityType varchar(50)
as
begin
SELECT TOP 1000 [Id]
,[EntityId]
,[EntityType]
,[TenantId]
FROM [FutureTrakProd].[dbo].[Activities]
where TenantId=1 and EntityType= case #EntityType when 'BOOKING' then 'BOOKING'
when 'JOB' then 'JOB'
END
end
Any help would be appreciable
Thankyou
create proc spproc
#entityType varchar(50)
as
begin
SELECT TOP 1000 [Id]
,[EntityId]
,[EntityType]
,[TenantId]
FROM [FutureTrakProd].[dbo].[Activities]
where TenantId=1 and (#EntityType is null OR EntityType= #EntityType)
end
You don't need to use case expression you can do :
SELECT TOP 1000 [Id], [EntityId], [EntityType], [TenantId]
from [FutureTrakProd].[dbo].[Activities]
WHERE TenantId = 1 AND
(#EntityType IS NULL OR EntityType = #EntityType)
ORDER BY id; -- whatever order you want (asc/desc)
For your query procedure you need to state explicit ORDER BY clause otherwise TOP 1000 will give random Ids.
You don't need a CASE expression for this, you just need an OR. The following should put you on the right path:
WHERE TenantId=1
AND (EntityType = #EntityType OR #EntityType IS NULL)
Also, note it would also be wise to declare your parameter as NULLable:
CREATE PROC spproc #entityType varchar(50) = NULL
This means that someone can simply exclude the paramter, value than having to pass NULL (thus EXEc spproc; would work).
Finally, if you're going to have lots of NULLable parameters, then you're looking at a "catch-all" query; the solution would be different if that is the case. "Catch-all" queries can be notoriously slow.
You can execute a dynamic sql query.
Query
create proc spproc
#entityType varchar(50)
as
begin
declare #sql as nvarchar(max);
declare #condition as nvarchar(2000);
select = case when #entityType is not null then ' and [EntityType] = #entityType;' else ';' end;
select #sql = 'SELECT TOP 1000 [Id], [EntityId], [EntityType], [TenantId] FROM [FutureTrakProd].[dbo].[Activities] where TenantId = 1 ';
exec sp_executesql #sql,
N'#entityType nvarchar(1000)',
#entityType = #entityType
end

Return condition (in operator) in case statement in SQL

declare #code varchar(1)
set #code = null
select
*
from
Employee
where
Emp_Id in
(
case
when #code = null then 1,2,3
then #code = 1 then 1,3
when #code = 2 then 2,3
end
)
I mean if "code = null", the query will be like this:
select
*
from
Employee
where
Emp_Id in (1,2,3)
If "code = 1", the query will be like this:
select
*
from
Employee
where
Emp_Id in (1,3)
I don't want use other operator like OR, need use IN operator.
Any idea ?
You can't return a list type from a case, but you can do this:
select *
from Employee
where (
(#code is null and Emp_Id in (1,2,3)) or
(#code = 1 and Emp_Id in (1,3)) or
(#code = 2 and Emp_Id in (2,3))
)
Note also your attempt included when #code = null, which is never true - you must use is null when testing for null (not = null).
Dynamic-sql:
declare #code varchar(1)
, #sql nvarchar(max)
set #code = null
set #sql = N'
select *
from Employee
where Emp_Id in (' +
case
when #code is null then '1,2,3'
when #code = 1 then '1,3'
when #code = 2 then '2,3'
end +
')'
exec sp_executesql #sql