How to from query escaping comma and other special character in SQL Server stored procedure - sql

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

Related

Dynamic vs Static SQL with multiple conditions

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 + '%'))

How to pass Server Name dynamically in SQL Server

SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX),
#servername NVARCHAR(255)
SET #servername = '[s-printstream]'
--Drop Table #Actual
CREATE TABLE #Actual
(
jobnumber INT,
firstNameCounts VARCHAR(25),
lastNameCounts VARCHAR(25),
address1Counts VARCHAR(25),
address2Counts VARCHAR(25),
cityCounts VARCHAR(25),
stateCounts VARCHAR(25),
zipCounts VARCHAR(25),
inHomeDateCounts VARCHAR(25)
)
SET #sql = 'INSERT INTO #actual (jobnumber,firstNameCounts,lastNameCounts , address1Counts, address2Counts, cityCounts, stateCounts, zipCounts, inHomeDateCounts) '
SET #sql = #sql + ' Select s.jobnumber, count(s.firstName) AS [firstNameCounts], Count (s.lastName) AS [lastNameCounts], Count (s.Address1) As [address1Counts], Count (s.address2)-Count (address2) AS '
SET #sql = #sql + ' [address2Counts], Count (s.City) AS [cityCounts], Count (s.State) AS [stateCounts], Count (s.Zip) AS [zipCounts], Count (jb.inHomeDate) AS [inHomeDateCounts] '
SET #sql = #sql + ' From' + ' #servername ' + '.[tdis_417133]' + '.[dbo].[tblStandardFinal] s '
SET #sql = #sql + ' INNER JOIN [s-printstream].[tdSchedule2].[dbo].[tblJobTicketActions] jb '
SET #sql = #sql + ' ON jb.psFlagJobNumber = s.jobNumber '
SET #sql = #sql + ' where jobNumber = #jobNumber '
SET #sql = #sql + ' group by jobNumber '
PRINT #SQL
EXEC sp_executesql #sql
,N'#JobNumber Varchar(25)'
,#JobNumber = 417133
Could anyone please help me find out how I would pass my server name dynamically as well as the database name? When I try to do it, I get this error:
Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "#servername"
Any help is appreciated.
Thanks
or pass #servername value into sql command
EXEC sp_executesql #sql
,N'#JobNumber Varchar(25),#servername nvarchar(255)'
,#JobNumber = 417133,#servername=#servername

why such so many single quote used in query

I am searching a query which generate html table. I found this query, but I can not understand what is use of such so many single quote used here and
why all code create in variable. I am new in sql please help me.
BEGIN
SET NOCOUNT ON;
IF #orderBy IS NULL
BEGIN
SET #orderBy = ''
END
SET #orderBy = REPLACE(#orderBy, '''', '''''');
DECLARE #realQuery NVARCHAR(MAX) = ' //this is variable which take all query as string
DECLARE #headerRow nvarchar(MAX);
DECLARE #cols nvarchar(MAX);
SELECT * INTO #dynSql FROM (' + #query + ') sub; -- how this temp table create
SELECT #cols = COALESCE(#cols + '', '''''''', '', '''') + ''['' + name + ''] AS ''''td''''''
FROM tempdb.sys.columns
WHERE object_id = object_id(''tempdb..#dynSql'')
ORDER BY column_id;
SET #cols = ''SET #html = CAST(( SELECT '' + #cols + '' FROM #dynSql ' + #orderBy + ' FOR XML PATH(''''tr''''), ELEMENTS XSINIL) AS nvarchar(max))''
EXEC sys.sp_executesql #cols, N''#html nvarchar(MAX) OUTPUT'', #html=#html OUTPUT
--in coalesce why so many '''' used
SELECT #headerRow = COALESCE(#headerRow + '''', '''') + ''<th>'' + name + ''</th>''
FROM tempdb.sys.columns
WHERE object_id = object_id(''tempdb..#dynSql'')
ORDER BY column_id;
SET #headerRow = ''<tr>'' + #headerRow + ''</tr>'';
SET #html = ''<table border="1">'' + #headerRow + #html + ''</table>'';
';
EXEC sys.sp_executesql #realQuery
,N'#html nvarchar(MAX) OUTPUT'
,#html = #html OUTPUT
END
Above query is working fine, but I can't understand it.

SQL with AND statements, dynamically building up

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 :)

Multiple conditional Where clause

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