I currently have a query that will pull a bunch of information from my database based on whatever where condition that I want to use.
declare #CaseNum char(7),
#ImportId char,
#FormatId char,
#SessionId char(5)
set #CaseNum = '' --I can place the value that I want to search by in here
set #ImportId = ''
set #FormatId = ''
set #SessionId = ''
--------------------
query in here
--------------------
where
gr.[CaseNum] = #CaseNum --currently I have to comment the ones I'm not using out
--im.[ImportId] = #ImportId
--fr.[FormatId] = #FormatId
--se.[SessionId] = #SessionId
I want to be able to take the comment portion out and simply display all rows if the parameter = ''
For example if I use set #CaseNum = '1234567' then it will search by that parameter and if I use #FormatId = '12' it will search by that one.
I have tried using the following and a few other attempts but I am getting nowhere fast.
where
gr.[CaseNum] = '%' + #CaseNum + '%'
and im.[ImportId] = '%' + #ImportId + '%'
and fr.[FormatId] = '%' + #FormatId + '%'
and se.[SessionId] = '%' + #SessionId + '%'
With help from the link that #Norman posted I figured it out. I wanted to post my solution for others to see.
declare #CaseNum varchar(MAX),
#ImportId varchar(MAX)
set #CaseNum = ''
set #ImportId = ''
----------------------------------------------------------------------------
If(#CaseNum = '') --Sets the parameter to NULL for COALESCE to work
Begin
Select #CaseNum = NULL
End
If(#ImportId = '') --Sets the parameter to NULL for COALESCE to work
Begin
Select #ImportId = NULL
End
--------------------
query in here
--------------------
where
gr.[CaseNum] = COALESCE(#CaseNum, gr.[CaseNum])
and im.ImportId = COALESCE(#ImportId, im.ImportId)
This solution allows the query to use just a single parameter or all at the same time.
You might want to look into building your query.
DECLARE #Number varchar(10)
DECLARE #Where varchar(max)
DECLARE #Query varchar(max)
SET #Query = 'SELECT * FROM TestTable'
SET #Where = ''
SET #Number = '3'
IF ISNULL(#Number, '') != ''
BEGIN
SET #Where = #Where + 'and testNumber = ' + #Number
END
IF LEN(#Where) > 0
BEGIN
SET #Where = SUBSTRING(#Where, 4, LEN(#Where))
END
if ISNULL(#Where, '') != ''
BEGIN
SET #Query = #Query + ' WHERE ' + #Where
END
EXEC(#Query)
Check out this gentleman's article for reference: https://social.msdn.microsoft.com/forums/sqlserver/en-US/1ec6ddd9-754b-4d78-8d3a-2b4da90e85dc/dynamically-building-where-clauses
Related
The "Where" clause of my SQL will vary depending on the values provided. I wrote 2 versions (Dynamic and static). I read that Dynamic is the way to go if we have multiple parameters with a variable where clause. Also, this is just a sample, my real SQL has many more conditions, but something along these lines. Which among the two is the right choice for this scenario?
Dynamic SQL:
DECLARE #SQL NVARCHAR(max)='SELECT ID,Name,sex,street,city,state,zip,phone FROM Test';
DECLARE #whereSql VARCHAR(2000) = 'WHERE city= #City';
DECLARE #OrderBy VARCHAR(2000) = 'order by name';
IF(#Name IS NOT NULL)
BEGIN
SET #Name = #Name + '%'
SET #whereSql = #whereSql + ' ' + 'AND name like #Name';
end
IF(#Gender IS NOT NULL)
BEGIN
SET #whereSql = #whereSql + ' ' + 'AND sex =' + '#Gender';
END
IF(#Address IS NOT NULL)
BEGIN
SET #Address = '%' + #Address + '%'
SET #whereSql = #whereSql + ' ' + 'AND street like ' + '#Address';
END
SET #SQL = #SQL +' ' + #whereSql + ' '+ #OrderBy;
EXEC sp_executesql #SQL, N'#Gender VARCHAR(10), #Name VARCHAR(200), #Address VARCHAR(250)', #Gender,#Name,#Address;
Static SQL:
SELECT ID,Name,sex,street,city,state,zip,phone FROM Test T1 WHERE
(#Name IS NULL OR (T1.Name LIKE +'%'+ #Name + '%'))
AND
(#Gender is null OR (T1.sex = #Gender))
AND
(#Address is null or (T1.street LIKE +'%'+ #Address + '%'))
I have a SQL stored procedure which takes several parameters. In there I need to pass conditions as =, <, > and use them in the query.
Currently what I'm doing is I check what's the condition and change a part of the query according to it. I want to pass the condition as a parameter and use it directly in the query.
This is how I'm doing now,
I'm passing these parameters:
#software_type nvarchar(50),
#software_id nvarchar(50),
#condition char,
#version_id float
Query:
DECLARE
#BaseQuery nvarchar(max) = N'SELECT DISTINCT Installed_Software.vm_name FROM Installed_Software INNER JOIN Software ON Installed_Software.software_id = Software.software_id INNER JOIN Software_Version ON Installed_Software.software_id = Software_Version.software_id AND Installed_Software.version_id = Software_Version.version_id AND Software.software_id = Software_Version.software_id',
#WhereClause nvarchar(max) = ' WHERE 1=1',
#ParamList nvarchar(max) = N'#sfType nvarchar(50),#sfId nvarchar(50),#verId float,#cond char'
IF #software_type IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Software.software_type = #sfType';
END
IF #software_id IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Installed_Software.software_id=#sfId';
END
IF #version_id IS NOT NULL AND #condition IS NOT NULL
BEGIN
IF #condition = '='
BEGIN
SET #WhereClause = #WhereClause + ' AND Installed_Software.version_id = #verId';
END
ELSE IF #condition ='>'
BEGIN
SET #WhereClause = #WhereClause + ' AND Installed_Software.version_id > #verId';
END
ELSE IF #condition='<'
BEGIN
SET #WhereClause = #WhereClause + ' AND Installed_Software.version_id < #verId';
END
ELSE IF #condition = '>='
BEGIN
SET #WhereClause=#WhereClause + ' AND Installed_Software.version_id >= #verId';
END
ELSE IF #condition='<='
BEGIN
SET #WhereClause = #WhereClause + ' AND Installed_Software.version_id <= #verId';
END
ELSE
BEGIN
SET #WhereClause = #WhereClause + ' AND Installed_Software.version_id = #verId';
END
END
SET #BaseQuery = #BaseQuery + #WhereClause;
EXECUTE sp_executesql #BaseQuery, #ParamList, #sfType=#software_type, #sfId=#software_id, #verId=#version_id;
What I want to do is something like this:
IF #version_id IS NOT NULL AND #condition IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Installed_Software.version_id' + '#condition' + '#version_id';
END
Is this possible to do that?
I would suggest not using dynamic sql for this.
I believe that the following query should return the same results as the dynamic sql version:
SELECT DISTINCT Installed_Software.vm_name
FROM Installed_Software
INNER JOIN Software
ON Installed_Software.software_id = Software.software_id
INNER JOIN Software_Version
ON Installed_Software.software_id = Software_Version.software_id
AND Installed_Software.version_id = Software_Version.version_id
AND Software.software_id = Software_Version.software_id
WHERE
(
#software_type IS NULL
OR Software.software_type = #software_type
)
AND
(
#software_id IS NULL
OR Installed_Software.software_id = #software_id
)
AND
(
#version_id IS NULL
OR #condition IS NULL
OR (#condition = '=' AND Installed_Software.version_id = #version_id)
OR (#condition = '>' AND Installed_Software.version_id > #version_id)
OR (#condition = '<' AND Installed_Software.version_id < #version_id)
OR (#condition = '>=' AND Installed_Software.version_id >= #version_id)
OR (#condition = '<=' AND Installed_Software.version_id <= #version_id)
)
Is this possible to do that? YES
Just add single space between your condition to avoid syntactical error
SET #WhereClause = #WhereClause + ' AND Installed_Software.version_id ' + '#condition' + ' #version_id';
----^ -----^
Aim: I'm building a dynamic SQL string and want to make the search an AND function
Code type: SQL stored procedure within SQL Server Management Studio
Issue: If the first search is not required then I need to know this (I know because the default is '0' in this case. I feel I'm missing a sitter but don't seem to be able to stackoverflow/Google for the solution.
I set up #QueryString with a default of '' so the functionality will work.
What will fix this?:
I've thought about COALESCE and potential use of IF ELSE within the IF but I am hoping there is clean solution along the lines of
SET #QUERYSTRING = IF(#QUERYSTRING = '','', + + ' FIELD1 LIKE ''%' + LTRIM(RTRIM(#s1)) + '%' )
Current example (snippet):
ALTER PROCEDURE [dbo].[spGridSearchTest]
#s1 NVARCHAR(20),
#s2 VARCHAR(20)
AS
BEGIN
DECLARE #QUERY NVARCHAR(MAX) = ''
DECLARE #QUERYSTRING NVARCHAR(MAX) = ''
SET #QUERY = 'SELECT * FROM TblTable'
IF #s1 <> '1234xyz'
SET #QUERYSTRING = #QUERYSTRING + ' Field1 LIKE ''%' + LTRIM(RTRIM(#s1)) + '%'
IF #s2 <> '1234xyz'
SET #QUERYSTRING = #QUERYSTRING + ' Field2 LIKE ''%' + LTRIM(RTRIM#s2)) + '%'
IF LEN(LTRIM(RTRIM(#QUERYSTRING))) > 0
SET #QUERY = LTRIM(RTRIM(#QUERY)) + ' WHERE ' + LTRIM(RTRIM(#QUERYSTRING)) + ''''
EXECUTE(#QUERY)
END
If I understand better your issue:
Try this:
ALTER PROCEDURE [dbo].[spGridSearchTest]
#s1 NVARCHAR(20),
#s2 VARCHAR(20)
AS
BEGIN
DECLARE #QUERY NVARCHAR(MAX) = ''
DECLARE #QUERYSTRING NVARCHAR(MAX) = ''
DECLARE #conditionadded char(1) = 'N'
SET #QUERY = 'SELECT * FROM TblTable'
IF #s1 <> '1234xyz'
BEGIN
SET #QUERYSTRING = ' Field1 LIKE ''%' + LTRIM(RTRIM(#s1)) + '%'
SET #conditionadded = 'Y'
END
IF #s2 <> '1234xyz'
BEGIN
IF (#conditionadded = 'Y')
BEGIN
SET #QUERYSTRING = #QUERYSTRING + ' AND '
END
SET #QUERYSTRING = #QUERYSTRING + ' Field2 LIKE ''%' + LTRIM(RTRIM#s2)) + '%'
SET #conditionadded = 'Y'
END
IF (#conditionadded = 'Y')
BEGIN
SET #QUERY = LTRIM(RTRIM(#QUERY)) + ' WHERE ' + LTRIM(RTRIM(#QUERYSTRING)) + ''''
END
EXECUTE(#QUERY)
END
Do you really need a dynamic query? Why not use something like this:
select
Whatever
from MyTable
where
(#s1 = '1234xyz' or Field1 = #s1)
and
(#s2 = '1234xyz' or Field2 = #s2)
This avoids a security hole, and depending on your query patterns and data set, it might even be faster. And of course, it's pretty easy to read, and you don't have to deal with SQL in strings :)
I have a function which returns the comma separate values, but when I use
COALESCE(#Jiraids + ', ', '')
I get an error.
ALTER FUNCTION [dbo].[getCommonJiraIds](
#selct varchar(100),
#whereClause varchar(100),
#id varchar(100),
#TEST_RESULT_INFO_ID varchar(20) )
RETURNS varchar(max)
AS
BEGIN
DECLARE #Jiraids VARCHAR(8000)
DECLARE #sql varchar(max)
SET #whereClause = 'dbo.SNSTestResults.JIRA_ID <> '' AND dbo.SNSTestResults.'+#whereClause+ ''+ QUOTENAME(#id,'''') + 'AND dbo.SNSTestResults.Test_result_info_ID_FK LIKE '+QUOTENAME(#TEST_RESULT_INFO_ID,'''')
SET #sql = 'Select #Jiraids = COALESCE(#Jiraids + '', '', '') + case when (#selct LIKE Jira_ID_Maped) then Jira_ID_Maped else Jira_ID end
FROM dbo.TestCaseList INNER JOIN dbo.SNSTestResults ON dbo.TestCaseList.TestCaseListID = dbo.SNSTestResults.TestCaseListID_FK'
set #sql = #sql + #WhereClause
EXEC #sql
RETURN ( select #Jiraids);
END
When I execute the above function I got this error:
Msg 203, Level 16, State 2, Procedure GetDailyCrJiraTable, Line 159
The name 'Select #Jiraids =COALESCE(#Jiraids + ', ', ') + case when (#selct LIKE Jira_ID_Maped) then Jira_ID_Maped else Jira_ID end FROM dbo.TestCaseList INNER JOIN dbo.SNSTestResults ON dbo.TestCaseList.TestCaseListID = dbo.SNSTestResults.TestCaseListID_FKdbo.SNSTestResults.JIRA_ID <> ' AND dbo.SNSTestResults.Jira_ID_Maped'UIBUG-4533'AND dbo.SNSTestResu' is not a valid identifier.
Somebody please help me to fix this issue.
SET #whereClause = 'dbo.SNSTestResults.JIRA_ID <> '''' AND dbo.SNSTestResults.'+#whereClause+ ''+ QUOTENAME(#id,'''') + 'AND dbo.SNSTestResults.Test_result_info_ID_FK LIKE '+QUOTENAME(#TEST_RESULT_INFO_ID,'''')
you need more ' after dbo.SNSTestResults.JIRA_ID <>
You have to add more ' to your COALESCE function as below
Select #Jiraids = COALESCE(#Jiraids + '', '', '''')
and as I said in comment you have to change this dbo.SNSTestResults.JIRA_ID <> ''
to dbo.SNSTestResults.JIRA_ID <> '''' AND
ALTER FUNCTION [dbo].[getCommonJiraIds](
#selct varchar(100),
#whereClause varchar(100),
#id varchar(100),
#TEST_RESULT_INFO_ID varchar(20) )
-- your four inputs
RETURNS varchar(max)
AS
BEGIN
DECLARE #Jiraids VARCHAR(8000)
DECLARE #sql varchar(max)
SET #whereClause = 'dbo.SNSTestResults.JIRA_ID <> ''
AND dbo.SNSTestResults.'+#whereClause+ ''+ QUOTENAME(#id,'''')
+ 'AND dbo.SNSTestResults.Test_result_info_ID_FK LIKE '+QUOTENAME(#TEST_RESULT_INFO_ID,'''')
you do not know it yet, but your Query does not actually have a WHERE clause written in.
I hope you are not actually expecting the programmer to write extra
code in your function everytime it is used.
SET #sql = 'Select #Jiraids = COALESCE(#Jiraids + '', '', '') + case when (#selct LIKE Jira_ID_Maped) then Jira_ID_Maped else Jira_ID end
FROM dbo.TestCaseList INNER JOIN dbo.SNSTestResults ON dbo.TestCaseList.TestCaseListID = dbo.SNSTestResults.TestCaseListID_FK
Your #selct has not been correctly identified. SQL SERVER cannot know
at compile time that it is a #variable.
Also, are you sure your function will only return one row? In some cases, being explicit about the expected occurrence (should someone actually use a '%' in their PREDICATE) can prevent a future breakdown in the code.
set #sql = #sql + #WhereClause
EXEC #sql
Thankfully, SO exists to help people out. :D
A correct version could be like the following:
ALTER FUNCTION [dbo].[getCommonJiraIds](
#selct varchar(100),
#whereClause varchar(100),
#id varchar(100),
#TEST_RESULT_INFO_ID varchar(20) )
-- your four inputs
RETURNS varchar(max)
AS
BEGIN
DECLARE #Jiraids VARCHAR(8000)
DECLARE #sql varchar(max)
SET #sql = '
Select #Jiraids = TOP 1 COALESCE(#Jiraids + '', '', '') + CASE WHEN (' + #selct + ' = Jira_ID_Maped)
THEN Jira_ID_Maped
ELSE Jira_ID END
FROM dbo.TestCaseList
INNER JOIN dbo.SNSTestResults ON dbo.TestCaseList.TestCaseListID = dbo.SNSTestResults.TestCaseListID_FK'
SET #whereClause = 'WHERE dbo.SNSTestResults.JIRA_ID <> ''
AND dbo.SNSTestResults.'+#whereClause+ ''+ QUOTENAME(#id,'''')
+ 'AND dbo.SNSTestResults.Test_result_info_ID_FK LIKE '+QUOTENAME(#TEST_RESULT_INFO_ID, '')
set #sql = #sql + #WhereClause
EXEC #sql
RETURN ( select #Jiraids);
END
I don't know how exactly I should frame my Question as even I don't know what exactly I have to search. May be this is the best place to put my question. I want to use If condition in where clause this can be done using case but my problem is I don't want to use it after a column name instead I want to avoid entire execution of that column. You can understand it by going through my procedure in the last I have commented, So I want to achieve something like that as I want to write the same procedure again for that condition which i think can be achievable by doing something like that. I searched on internet what I got is to use case in where which doesn't satisfy my purpose. Please look the last lines to understand the problem. Thanx
USE [overseascrm]
GO
/****** Object: StoredProcedure [dbo].[candidatesearch] Script Date: 05-07-2014 00:48:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[candidatesearch]
#candidate_id varchar(50),
#firstname varchar(50),
#lastname varchar(50),
#emailid_1 varchar(100),
#mobile_1 varchar(20),
#from varchar(50),
#to varchar(50),
#agentid varchar(50),
#passportno varchar(50),
#profession int,
#isactive bit
as
begin
DECLARE #candidateid_var varchar(50)
DECLARE #firstname_var varchar(50)
DECLARE #lastname_var varchar(50)
DECLARE #emailid1_var varchar(100)
DECLARE #mobile_1_var varchar(20)
DECLARE #agentid_var varchar(50)
IF(#agentid = '')
begin
SET #agentid_var = '%'
END ELSE BEGIN
SET #agentid_var = #agentid
END
IF (#candidate_id = '') BEGIN
SET #candidateid_var = '%'
END ELSE BEGIN
SET #candidateid_var = #candidate_id
END
IF (#firstname = '') BEGIN
SET #firstname_var = '%'
END ELSE BEGIN
SET #firstname_var = #firstname
END
IF (#lastname = '') BEGIN
SET #lastname_var = '%'
END ELSE BEGIN
SET #lastname_var = #lastname
END
IF (#emailid_1 = '') BEGIN
SET #emailid1_var = '%'
END ELSE BEGIN
SET #emailid1_var = #emailid_1
END
IF (#mobile_1 = '') BEGIN
SET #mobile_1_var = '%'
END ELSE BEGIN
SET #mobile_1_var = #mobile_1
END
IF (#from = '') BEGIN
SELECT
*
FROM candidate C
LEFT JOIN candidate_profession_map CM
ON C.candidate_id = CM.candidate_id
LEFT JOIN passport_details PD
ON C.candidate_id = PD.candidate_id
WHERE C.candidate_id LIKE '' + #candidateid_var + '%'
AND firstname LIKE '' + #firstname_var + '%'
AND lastname LIKE '' + #lastname_var + '%'
AND emailid_1 LIKE '' + #emailid1_var + '%'
AND mobile_1 LIKE '' + #mobile_1_var + '%'
AND agent_id LIKE '' + #agentid_var + '%'
AND CM.profession_id = #profession
AND C.isactive = #isactive
AND PD.passport_no = #passportno
END ELSE BEGIN
SELECT
*
FROM candidate C
LEFT JOIN candidate_profession_map CM
ON C.candidate_id = CM.candidate_id
LEFT JOIN passport_details PD
ON C.candidate_id = PD.candidate_id
WHERE C.candidate_id LIKE '' + #candidateid_var + '%'
AND firstname LIKE '' + #firstname_var + '%'
AND lastname LIKE '' + #lastname_var + '%'
AND emailid_1 LIKE '' + #emailid1_var + '%'
AND mobile_1 LIKE '' + #mobile_1_var + '%'
AND agent_id LIKE '' + #agentid_var + '%'
AND C.addedon BETWEEN CONVERT(DATETIME, #from, 103) AND CONVERT(DATETIME, #to, 103)
--IF (#profession <> 0)BEGIN
--AND CM.profession_id = #profession
--END
AND C.isactive = #isactive
OR PD.passport_no = #passportno
END
END
You could use dynamic sql execution where you create your select statement as varchar to your liking, executing it at the end using sp_executesql
http://msdn.microsoft.com/en-us/library/ms188001.aspx
ALTER procedure [dbo].[candidatesearch]
#candidate_id varchar(50),
#firstname varchar(50),
#lastname varchar(50),
#emailid_1 varchar(100),
#mobile_1 varchar(20),
#from varchar(50),
#to varchar(50),
#agentid varchar(50),
#passportno varchar(50),
#profession int,
#isactive bit
AS Begin
SELECT *
FROM candidate C
LEFT JOIN candidate_profession_map CM ON C.candidate_id = CM.candidate_id
LEFT JOIN passport_details PD ON C.candidate_id = PD.candidate_id
WHERE (#candidateid='' or C.candidate_id LIKE #candidateid + '%')
AND (#firstname = '' or firstname LIKE #firstname + '%')
AND (#lastname = '' or lastname LIKE #lastname + '%')
AND (#emailid_1='' or emailid_1 LIKE #emailid1 + '%')
AND (#mobile_1 = '' or mobile_1 LIKE #mobile_1 + '%')
AND (#agentid='' agent_id LIKE #agentid + '%')
AND C.isactive = #isactive
And ((#from=''
AND CM.profession_id = #profession
AND PD.passport_no = #passportno)
or (#from<>''
And C.addedon BETWEEN CONVERT(DATETIME, #from, 103) AND CONVERT(DATETIME, #to, 103)
OR PD.passport_no = #passportno)
End