Select all data when passing parameters with null - sql-server

I am using SQL Server 2012. This is my stored procedure code:
select *
from tbl_Events te
where te.MainEventID = ISNULL(#EventID, te.MainEventID)
and te.EventCityID = ISNULL(#CityID, te.EventCityID)
and te.OwnerPassNo = ISNULL(#PassNo, te.OwnerPassNo)
and te.[Owner] LIKE '%' + #Owner + '%'
and te.isActive = 'true'
When I try to execute it with the following
exec sp_GetEvents #Owner=N''
it returns 0 rows, though I have some data in my table.
What am I doing wrong?

Please try:
select * from tbl_Events te
where
(#EventID IS NULL OR te.MainEventID = #EventID) AND
(#CityID IS NULL OR te.EventCityID = #CityID) AND
(#PassNo IS NULL OR te.OwnerPassNo = #PassNo) AND
te.[Owner] like '%' + #Owner + '%' AND
te.isActive = 'true'
And check if 'isActive' expects 'true' or 1

Related

SQL Server Case Statement Query

I am writing a stored procedure which has some parameters and want to write a case statement
in query giving me syntax error. Can you help me how to write case statement?
Select *
FROM table1 ssr
left join table2 sse on ssr.case_nbr=sse.case_nbr
left join table3 m on m.MemberId=sse.memberid
where
(
#searchValue IS NULL Or
concat(last_name, first_name) like '%' + #searchValue + '%'
or mrn like '%' + #searchValue + '%' or FIN like '%' + #searchValue + '%'
)
AND (#searchFirst IS NULL Or first_name like '%' + #searchFirst + '%')
//i want to write a case statement
AND (#statusfilter IS NULL OR
CASE
WHEN CHARINDEX('NEW', #statusfilter) = 0
THEN
(sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter,'|')))
ELSE
(sse.Status is Null OR sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter,'|')))
END
)
You have to return value from the CASE, You can use IIF inside THEN and return 1 or 0 and compare that value.
AND (
#statusfilter IS NULL
OR
1 = CASE
WHEN CHARINDEX('NEW', #statusfilter) = 0
THEN IIF(sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter,'|')), 1, 0)
ELSE IIF((sse.Status is Null OR sse.Status in select splitdata from dbo.fnSplitString(#statusfilter,'|')), 1, 0)
END
)
You can just use normal boolean logic, which after cleaning up becomes this:
AND (
#statusfilter IS NULL OR
(
(
(CHARINDEX('NEW', #statusfilter) > 0 AND sse.Status IS NULL)
)
OR sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter, '|'))
)
)
Note that I strongly recommend you use a Table Valued Parameter instead of a split string.
At the very least, you should use the built-in string splitting function STRING_SPLIT (and I hope you are not on an unsupported version which doesn;t have it).

How can I use LIKE operator instead of IN operator for multiple commas contains string in stored procedure

I just made the stored procedure for search items before the procedure I was doing this all via LINQ in C# e.g
//orders
if (objParam.OrderNumber != null && objParam.OrderNumber.Count > 0)
{
foreach (var orderNumber in objParam.OrderNumber)
{
orderNumbersBuilder.Append(',' + orderNumber.ToString());
}
}
var orderNbrs = orderNumbersBuilder.ToString().Trim(',').Split(',');
//Searching
(objParam.OrderNumber.Count == 0 || orderNbrs.Any(a => i.tblOrderMaster.OrderNumber.Contains(a)))
Now I want to do with the stored procedure. I'm getting the result with IN operator but I want to use LIKE operator e.g
SELECT * FROM tblOrderMaster WHERE TrxNumber LIKE '%' + (SELECT * FROM STRING_SPLIT('1330,1329',',')) + '%'
I've multiple filters so I don't want to use function and subqueries e.g
--Params
#Account NVARCHAR(MAX) = NULL,
#OrderNumber NVARCHAR(MAX) = NULL,
#Carrier NVARCHAR(MAX) = NULL,
#ItemCode NVARCHAR(MAX) = NULL,
#OrderType NVARCHAR(MAX) = NULL,
#PONumber NVARCHAR(MAX) = NULL,
#SONumber NVARCHAR(MAX) = NULL
--columns start
--columns end
--Where condtions
(#ACCOUNT IS NULL OR #Account = '' OR partners.PartnerCode IN (select * from string_split(#ACCOUNT,','))) -- multi select filters started
AND
(#OrderNumber IS NULL OR #OrderNumber = '' OR orderMaster.OrderNumber IN (select * from string_split(#OrderNumber,',')))
AND
(#Carrier IS NULL OR #Carrier = '' OR carrier.Description IN (select * from string_split(#Carrier,',')))
AND
(#ItemCode IS NULL OR #ItemCode = '' OR itemMaster.ItemCode IN (select * from string_split(#ItemCode,',')))
AND
(#OrderType IS NULL OR #OrderType = '' OR orderMaster.OrderType IN (select * from string_split(#OrderType,',')))
AND
(#PONumber IS NULL OR #PONumber = '' OR orderMaster.PONumber IN (select * from string_split(#PONumber,',')))
AND
(#SONumber IS NULL OR #SONumber = '' OR orderMaster.SONumber IN (select * from string_split(#SONumber,',')))
You would need to use subqueries; the fact you don't want to doesn't change this with your current design. Using the query with the literal values you have, it would look like this:
SELECT *
FROM dbo.tblOrderMaster OM
WHERE EXISTS (SELECT 1
FROM STRING_SPLIT('1330,1329', ',') SS
WHERE OM.TrxNumber LIKE '%' + SS.[Value] + '%')
If you really don't want to use subqueries, then use table type parameters and then you can perform a JOIN:
SELECT OM.*
FROM dbo.tblOrderMaster OM
JOIN #YourTableVariable YTV ON OM.TrxNumber LIKE '%' + YTV.SearchValue + '%'

What is best way to search from optional parameter to SQL query in a stored procedure?

When it comes to search record with optional parameter in SQL stored procedure, out of these two queries. Both return the same results. Considering performance, which one will you use and why?
I have a stored procedure which has multiple search parameters and will be searching in multiple tables, with joins from a huge record set.
DECLARE #EventName VARCHAR(100)
--SET #EventName = ''
--SET #EventName = NULL
SET #EventName = 'Coffee in Coffee Bean'
-- Query - 1
SELECT *
FROM EventDetails
WHERE
1 = CASE
WHEN #EventName IS NULL OR #EventName = '' THEN 1
WHEN EventName LIKE '%'+ #EventName +'%' THEN 1 ELSE 0
END
-- Query - 2
SELECT *
FROM EventDetails
WHERE
EventName LIKE '%' + CASE
WHEN LEN(LTRIM(#EventName)) > 0
THEN #EventName
ELSE EventName
END + '%'
You can try this by writing a single query
SELECT *
FROM EventDetails
WHERE ((#EventName IS NULL OR #EventName) OR (EventName LIKE '%'+ #EventName +'%'))
My money is on this:
IF ISNULL(#EventName), '') = ''
SELECT * FROM EventDetails
ELSE
SELECT * FROM EventDetails WHERE EventName = '%' + #EventName + '%'
If you can't consider dynamic SQL, then try to use as less functions and data tampering as possible. The most common approach for this would be something like the following:
DECLARE #OptionalFilter1 INT
DECLARE #OptionalFilter2 VARCHAR(100)
-- ...
DECLARE #OptionalFilterN BIT
SELECT
YourColumns
FROM
YourTable AS T
WHERE
(#OptionalFilter1 IS NULL OR #OptionalFilter1 = T.Filter1Column) AND
(#OptionalFilter2 IS NULL OR #OptionalFilter2 = T.Filter2Column) AND
-- ...
(#OptionalFilterN IS NULL OR #OptionalFilterN = T.FilterNColumn)
For your example would be:
DECLARE #EventName VARCHAR(100) = 'Coffee in Coffee Bean'
SELECT
*
FROM
EventDetails AS E
WHERE
(#EventName IS NULL OR E.Event LIKE '%' + #EventName + '%')
If this is gonna end in a procedure, consider using OPTION (RECOMPILE) on the query with many filters and/or assigning the stored procedure parameters to new local scope variables to prevent parameter sniffing. You can read about parameter sniffing problem (with an example similar to yours) in this post.

Get name from variable using index in T-SQL

Using the following two queries
Query 1:
DECLARE #ContentColumnNamesSRC NVARCHAR(4000) = NULL,
SELECT
#ContentColumnNamesSRC = COALESCE(#ContentColumnNamesSRC + ', ', '') + '[' + name + ']'
FROM
tempdb.sys.columns
WHERE
1 = 1
AND object_id = OBJECT_ID('tempdb..#tempTable')
AND column_id < 9 -- First 8 columns are ID data, which is what I am after
Query 2:
DECLARE #ContentColumnNamesDST NVARCHAR(4000) = NULL,
SELECT
#ContentColumnNamesDST = COALESCE(#ContentColumnNamesDST + ', ', '') + '[' + name + ']'
FROM
tempdb.sys.columns
WHERE
1 = 1
AND object_id = OBJECT_ID('Import.dbo.ContentTable')
AND column_id < 9 -- First 8 columns are ID data, which is what I am after
I can get the first 8 columns from each table into a variable.
What I would like to do is find a way to get the values out of the variable, such that I can match the column names.
They should be identical in each table, and I need it to be able to create a dynamic merge statement, such that the columnsnames from each variable
#ContentColumnNamesSRC
and
#ContentColumnNamesDST
line up, so I can use it in a merge statement.
The point of this is to be able to use it in a loop, and all i would have to do is change which tables it looks at and the merge statements would still work.
Ideally, id like to end up with something like the following:
SELECT #StageSQLCore = N'USE Staging;
BEGIN TRANSACTION
MERGE '+#StageTableCore+' AS DST
USING '+#ImportTableCore+' AS SRC
ON (SRC.[Key] = DST.[Key])
WHEN NOT MATCHED THEN
INSERT ('+#StageTableCoreColumns+')
VALUES (
'+#ImportTableCoreColumns+',GETDATE())
WHEN MATCHED
THEN UPDATE
SET
DST.'+#ContentColumnNamesDST[i]' = SRC.'+#ContentColumnNamesSRC[i] +'
,DST.'+#ContentColumnNamesDST[i]' = SRC.'+#ContentColumnNamesSRC[i] +'
,DST.'+#ContentColumnNamesDST[i]' = SRC.'+#ContentColumnNamesSRC[i] +'
,DST.'+#ContentColumnNamesDST[i]' = SRC.'+#ContentColumnNamesSRC[i] +'
,DST.[ETLDate] = GETDATE()
;
COMMIT'
EXEC (#StageSQLCore)
You can generate Merge SQL like this if both the ordinal are matching
DECLARE #MergeSQL NVARCHAR(4000) = NULL
SELECT --*--,
#MergeSQL = COALESCE(#MergeSQL + ', DST.=', '') + QUOTENAME(bc.column_name) + ' = SRC.' + QUOTENAME(bc.COLUMN_NAME) + char(13)
FROM
test.INFORMATION_SCHEMA.COLUMNS tc
inner join testb.INFORMATION_SCHEMA.COLUMNS bc
on tc.TABLE_NAME = bc.TABLE_NAME
and tc.ORDINAL_POSITION = bc.ORDINAL_POSITION
and tc.TABLE_NAME = 'History'
WHERE
tc.ORDINAL_POSITION < 5 -- First 8 columns are ID data, which is what I am after
and bc.ORDINAL_POSITION < 5
select #MergeSQL

Stored procedure search parameter in MS SQL

I have got the MS SQL stored procedure, which is designed to return the results in XML showing all the applicants who are 'sales'.
There are filters on the page to drill down the results one being a search (sString).
The desired behavior is:
If sString is null, it should return all the results;
If sString is not null, it should make sString to the show the found fields.
The SP does not work as expected: it always returns all the results regardless of sString value.
MS SQL Code of the SP:
WITH OrderedMatches AS
(
SELECT ROW_NUMBER() OVER (ORDER BY MB.Member_Registered DESC) AS RowNumber,
MB.Member_ID,
MB.Member_Name, MB.Member_Mobile, MB.Member_Propertytosell, MB.Member_Propertytosell_Details, MB.Member_ExistingBuytoLet, MB.Member_TalkingPoints,
MB.Member_Registered, MB.Member_Funding, MB.Member_Active, MB.Member_Last_Contacted, MB.Member_Situation
FROM dbo.Member_Base MB INNER JOIN dbo.Member_Criteria MC ON MC.Member_ID = MB.Member_ID
WHERE MB.Member_Active = 1 AND MC.Criteria_Section = 'sales'
AND (
#sType = 'a'
OR (
#sType = 'b' AND MB.Member_Propertytosell = 1
)
OR (
#sType = 'c' AND MB.Member_ExistingBuytoLet = 1
)
)
OR (
MB.Member_Name LIKE '%' + #sString + '%' OR MB.Member_Mobile LIKE '%' + #sString + '%' OR MB.Member_Propertytosell_Details LIKE '%' + #sString + '%'
)
)
SELECT
(
SELECT
OM.Member_ID as "#id",
OM.Member_Name as "#appname",
OM.Member_Mobile as "#contact",
OM.Member_Propertytosell as "#propts",
OM.Member_Propertytosell_Details as "#proptsdetails",
OM.Member_ExistingBuytoLet as "#existingBTL",
OM.Member_TalkingPoints as "#talkingpoints",
OM.Member_Registered as "#registered",
OM.Member_Funding as "#funding",
OM.Member_Active as "#active",
OM.Member_Last_Contacted as "#lastcontact",
OM.Member_Situation as "#situation"
FROM OrderedMatches OM
WHERE OM.RowNumber Between #nstart AND #nend
FOR XML path ('applicant'), TYPE
),
(
SELECT COUNT(*) as "#titems"
FROM OrderedMatches
FOR XML path ('meta')
)
FOR XML PATH ('')
END
I suppose the SP is wrong but cant see at which part exactly.
Does anyone have any suggestions?
It's returning everything because you have OR between your sString condition and the rest of conditions in WHERE. Change your WHERE clause to:
WHERE MB.Member_Active = 1 AND MC.Criteria_Section = 'sales'
AND (
#sType = 'a'
OR (
#sType = 'b' AND MB.Member_Propertytosell = 1
)
OR (
#sType = 'c' AND MB.Member_ExistingBuytoLet = 1
)
)
AND (#sString IS NULL
OR
(
MB.Member_Name LIKE '%' + #sString + '%' OR MB.Member_Mobile LIKE '%' + #sString + '%' OR MB.Member_Propertytosell_Details LIKE '%' + #sString + '%'
)
)

Resources