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).
Related
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 + '%'
I'm writing a stored procedure about searching the database based on aspx page textbox input text.
This stored procedure works well, but I have a problem.
Sometimes #DeptName and #DutyName parameters are empty or null.
So I want to skip or ignore where clauses when that parameter values are empty. But I am confused as to how to handle this situation.
Please give me your advice.
My stored procedure code:
DECLARE
#CompanyCode varchar(20)
, #DeptName nvarchar(20)
, #DutyName nvarchar(20)
SELECT
#CompanyCode = 'h101'
, #DeptName = 'IT'
, #DutyName = 'Manager'
SELECT
U.ADDisplayName AS UserName
, LOWER(U.UserID) AS EmpID
, ISNULL(CPN.CompanyName, '') AS CompanyCode
, ISNULL(U.DisplayName_Eng, '') AS DisplayName_Eng
, ISNULL(DT.DisplayName, '') AS DeptName
, ISNULL(DTY.DutyName, '') AS DutyName
, ISNULL(U.CellPhone, '') AS CellPhone
, ISNULL(U.ExtensionNumber, '') AS ExtensionNumber
, ISNULL(U.FaxNumber, '') AS FaxNumber
, ISNULL(U.ChargeJob, '') AS ChargeJob
, ISNULL(LOC.LocationName, '') AS LocationName
, ISNULL(U.Workplace, '') AS Workplace
, ISNULL(U.EMail, '') AS EMail
FROM dbo.tb_User U
INNER JOIN dbo.tb_Dept DT
ON U.MainDeptCode = DT.DeptCode
INNER JOIN dbo.tb_Company CPN
ON U.CompanyCode = CPN.CompanyCode
INNER JOIN dbo.tb_Location LOC
ON U.LocationCode = LOC.LocationCode
AND U.CompanyCode = LOC.CompanyCode
AND U.GroupCode = LOC.GroupCode
AND U.DetailCode = loc.DetailCode
INNER JOIN dbo.tb_Duty DTY
ON U.DutyCode = DTY.DutyCode
AND U.CompanyCode = DTY.CompanyCode
AND U.GroupCode = DTY.GroupCode
AND U.DetailCode = DTY.DetailCode
WHERE U.CompanyCode = #companyCode
AND DT.DisplayName like '%' + #DeptName + '%'
AND DTY.DutyName like '%' + #DutyName + '%'
Order by DeptName desc
Thank you.
A very common construction is :
WHERE U.CompanyCode = #companyCode
AND (#DeptName is null or DT.DisplayName like '%' + #DeptName + '%')
AND (#DutyName is null or DTY.DutyName like '%' + #DutyName + '%')
...
...
with (recompile)
The with (recompile) hint at the end of your statement is telling SQL Server to check the optimization plan "after" replacing the variables by their values. Doing so it allows to completely ignore a condition when its parameter is null, resulting normally in an optimal execution (only on very complex statements you will need to do more in order to help the SQL engine to find the better execution plan).
It's also worth noting that using the with (recompile) clause forces to check for a new plan at every execution (instead of reusing an existing one), so if your sentence is going to be executed several times for second, then you will be better suited using an alternative, like parameterized dynamic SQL. Although this is not the most usual situation.
PS: If your parameter can also be an empty string, then use isnull to check both options. You still need to add the recompilation hint to execute it optimally.
WHERE U.CompanyCode = #companyCode
AND (isnull(#DeptName, '') = '' or DT.DisplayName like '%' + #DeptName + '%')
AND (isnull(#DutyName, '') = '' or DTY.DutyName like '%' + #DutyName + '%')
...
...
with (recompile)
Add an extra #DeptName is null and #DeptName ="" to each clause:
WHERE U.CompanyCode = #companyCode
AND ((DT.DisplayName like '%' + #DeptName + '%') or (#DeptName is null) or (#DeptName =''))
AND ((DTY.DutyName like '%' + #DutyName + '%') or (#DeptName is null) or (#DeptName = ''))
Order by DeptName desc
You can try this.
Using ISNULL you can replace NULL with a specified replacement value.
In this case, IF #DeptName is null then replace it with value of DT.DisplayName. same applies to #DutyName.
The Logical Function IIF is used to check empty value but this applies starting SQL2012 version, otherwise CASE expression for SQL2008 or later versions.
WHERE U.CompanyCode = #companyCode
AND DT.DisplayName like '%' + ISNULL(IIF(#DeptName = '',NULL,#DeptName),DT.DisplayName) + '%'
AND DTY.DutyName like '%' + ISNULL(IIF(#DutyName = '',NULL,#DutyName),DTY.DutyName) + '%'
Order by DeptName desc
I am creating a store procedure and in which am I stuck in a problem. I want to query two columns based on condition. If parameter is numeric then query to one column and if it is nonnumeric then query to other column. Following is the procedure.
$
declare #result AS varchar(50)
DECLARE #peopleId AS varchar(50)
if('232332' NOT LIKE '%[^0-9]%')
BEGIN
SET #result='Numeric'
PRINT #result
END
ELSE
BEGIN
set #result='nonNumeric'
print #result
END
select isnull(class.grade,'') as grade,ISNULL(class.room,'') as room,student.prefix as prefix,student.student_id as student_id,(person.first_name+' '+person.last_name) as name,
person.dob as dob,person.people_id as people_id,quit_on,
case when student.student_status='30' then
N'พักการเรียน'
when student.student_status='31' then
N'น.ร.ไปเรียนโครงการฯ'
else ''
end
as quit_reason from school_student student
inner join people_person person on student.person_id=person.id
left join school_classroom_students classStudent on classStudent.student_id=student.id
left join school_classroom class on class.id =classStudent.classroom_id
where student.student_status in('30','31') and student.system_status = 'DC' and student.school_id=#schoolId
AND case
WHEN
#result='nonNumeric' then-- this should execure
person.people_id=#peopleId
else---- this should work
person.first_name+' '+ person.last_name LIKE '%'+#peopleId+'%'
Please help me out on this
Why would use use a separate variable? You can do:
WHEN (person.people_id = try_convert(int, #peopleId) or
try_convert(int, #peopleId) is null and
person.first_name + ' ' + person.last_name LIKE '%' + #peopleId + '%'
)
I question why you are passing a value that is used for both a string and numeric comparison. If I were using a variable, I would do:
declare #personid int;
declare #personname varchar(255);
if #peopleid not like '%[^0-9]%'
set #personname = #peopleid;
else
set #personid = convert(int, #peopleid);
where (personid = #personid or
person.first_name + ' ' + person.last_name LIKE '%' + #personname + '%'
)
The code just seems easier to follow.
Since SQL Server doesn't treat results of CASE expressions as booleans, you have to add an extra comparison. The way to do that is like this:
WHERE 1 = CASE WHEN x THEN 1 WHEN y THEN 0 ELSE 1 END
Conditions which result in rows being included in the result must evaluate to 1, and conditions which don't, must evaluate to something other than 1 (like 0). So the whole CASE expression returns either 0 or 1, and that is compared to 1.
In your code, it would look like this:
AND 1 = case
WHEN
#result='nonNumeric' then case when person.person_id = #peopleId then 1 else 0 end
else when person.first_name+' '+person.last_name LIKE '%'+#peopleId+'%' then 1 else 0 end
end
I added the END.
Just do like that
DECLARE #IsNumeric INT = NULL
DECLARE #IsNotNumeric INT = NULL
DECLARE #peopleId Varchar(50)
SET #peopleId = '123'
IF ISNUMERIC(#peopleId) = 1
BEGIN
SET #IsNumeric = 1
END
ELSE
BEGIN
SET #IsNotNumeric = 1
END
IN WHERE Condition Just Check
AND (#IsNumeric IS NULL OR CONVERT(VARCHAR(500),person.people_id)=#peopleId)
AND (#IsNotNumeric IS NULL OR person.first_name+' '+ person.last_name LIKE '%'+#peopleId+'%')
I am trying to MERGE values from one table to another. One of the values is a conditional value, but it looks like I am not getting the syntax correctly. Initially, I was using an IF-THEN-ELSE statement but was advise to use a CASE statement instead.
Here is the gist the syntax that is failing:
CREATE PROCEDURE EmployeeMerge
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO Employee AS t1
USING
(SELECT
EmployeeName,
Zip,
UpdateDate
FROM table2) AS t2
ON (t1.EmployeeID = t2.EmployeeID)
WHEN MATCHED AND t2.UpdatedDate > t1.UpdatedDate THEN
UPDATE
SET
t1.EmployeeName = s.EmployeeName,
t1.Zip =
(CASE
WHEN t2.ZipExt IS NULL OR t2.ZipExt = '' THEN t2.Zip
ELSE (t2.Zip + '-' + t2.ZipExt)
END),
t1.UpdatedDate = t2.UpdateDate
WHEN NOT MATCHED THEN
INSERT (EmployeeName,
Zip,
ModDate)
VALUES
(t2.Name,
(CASE
WHEN t2.ZipExt IS NULL OR t2.ZipExt = '' THEN t2.Zip
ELSE (t2.Zip + '-' + t2.Zip_Ext)
END),
t2.UpdatedDate)
OUTPUT
deleted.*,
$action,
inserted.*
END; **-- A MERGE statement must be terminated by a semi-colon (;)**
GO
This MERGE statement works just fine if I do not implement the condition, i.e. simply set the t1.Zip = t2.Zip, but of course, this is avoiding the t2.ZipExt field.
A MERGE statement must be terminated by a semi-colon (;)
You haven't terminated the MERGE with a semicolon. You have terminated BEGIN-END. Move the semicolon.
I never really cared for the merge command. There are times where I can see using it, but for the most part, it's more complicated than I like my SQL.
UPDATE e
SET e.EmployeeName=t1.EmployeeName
, e.Zip=CASE
WHEN t1.ZipExt IS NULL OR t1.ZipExt = '' THEN t1.Zip
ELSE (t1.Zip + '-' + t1.ZipExt)
END
, e.UpdatedDate=t1.UpdatedDate
FROM Employee e
INNER JOIN Table t1 ON e.EmployeeID = t1.EmployeeID
WHERE t1.UpdatedDate > e.UpdatedDate
INSERT INTO Employee (EmployeeName,Zip,UpdatedDate)
SELECT
t1.EmployeeName
, t1.Zip=CASE
WHEN t1.ZipExt IS NULL OR t1.ZipExt = '' THEN t1.Zip
ELSE (t1.Zip + '-' + t1.ZipExt)
END
, t1.UpdatedDate
FROM Table t1
LEFT JOIN Employee e ON e.EmployeeID = t1.EmployeeID
WHERE e.EmployeeID IS NULL
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 + '%'
)
)