How to add multiple conditions in sql? - sql

Here is my stored procedure:
ALTER PROCEDURE sp_searchedstudentrecords
(
#condition varchar(20),
#searchtext varchar(50),
#searchclass int
)
AS
begin
If (#condition = 'startswith')
select * from student where name like #searchtext+ '% '
else if (#condition = 'endswith')
select * from student where name like '%' +#searchtext
else
select * from student where name like '%' +#searchtext+ '%'
End
I have been added extra one text box for search by class with the above query.
#searchclass int
May i now what should be the query for search by class look like?
I'm new sql query and .net,
I have been created dropdown contains startswith,endswith and contains and one text box for search by name.
I already done select record where search by name, with this i need to select record from table where search by class.
Can anyone guide me for query?
Thanks,

Like this
select *
from student
where name like (case
when #condition = 'startswith' then #searchtext+ '% '
else
case when #condition = 'endswith' then '%' + #searchtext
else '%' + #searchtext + '%'
end
end)
and studentid = isnull(#searchclass, studentid)
Above query to studentid has been extra search
If any id to search passing value other wise pass null
This query should be given result.

As already suggested, it is better to do this in your front-end by constructing a parameterized query as described here. Since you cannot use the protective power of parameterized with LIKE, you must be careful to sanitize your string (avoid Sql injection).
When implementing in .NET, it is best practice to avoid string comparisons. You can define your filters as a fixed list of id->name pairs.
enum LikeFilterType
{
Startswith = 1,
Endswith = 2,
Inside = 3
// maybe exactly can be added later
}
IList<SelectListItem> FilterOptions = new List<SelectListItem>()
{
new SelectListItem() { Value = (int) LikeFilterType.Startswith, Text = "Starts with" },
new SelectListItem() { Value = (int) LikeFilterType.Endswith , Text = "Ends with" },
new SelectListItem() { Value = (int) LikeFilterType.Inside, Text = "Inside" }
}
Your combo may "bind" directly to this list and use selected value, not the string in your logic (what you display may change over time, you do not want to change logic when changing a displayed name!)
Coding in ASP.NET allows to have a more readable and maintainable code.
NOTE: keep in mind that user should know or will be affected by LIKE special characters.

I assuming your parameters are nullable, therefore you can just do like this
SELECT * FROM student
WHERE name LIKE ( CASE WHEN #condition = 'startswith' THEN #searchtext + '%'
WHEN #condition = 'endswith' THEN '%'+#searchtext
ELSE '%'+#searchtext+'%'
END
) AND
(#searchclass IS NULL OR studentClass = #searchclass)
#searchclass IS NULL is for you to check is the parameter's value and it wont clash even if your #searchclass is NULL
Hope it help ya.

Refer below updated stored procedure with Class filter.
Change Class column based on exact column name:
ALTER PROCEDURE sp_searchedstudentrecords
(
#condition varchar(20),
#searchtext varchar(50),
#searchclass int
)
AS
BEGIN
IF (#condition = 'startswith')
SELECT * FROM student WHERE name like #searchtext+ '% ' AND Class = #searchclass
ELSE IF (#condition = 'endswith')
SELECT * FROM student WHERE name like '%' +#searchtext AND Class = #searchclass
ELSE
SELECT * FROM student WHERE name like '%' +#searchtext+ '%' AND Class = #searchclass
END

Related

How to get entities from table by name and another multiple nullable parameters from SQL Server table

I am making small e-shop for fun and want to filter results from searching entities by name and/or filter. If name is empty or null, it will get all entities (that works fine), but if I want filter it by category or discount or if its new (always just one filter and/or name), it ignores that completely. How to search it by name, by name and filter, or just filter correctly?
Code is here:
DECLARE #Name AS VARCHAR(100) = '',
#CategoryId AS INT = null,
#IsNew AS BIT = 0,
#IsDiscount AS BIT = 0;
SELECT
*
FROM
Products P
WHERE
(P.Name COLLATE Latin1_General_CI_AI LIKE '%' + COALESCE( #Name, '' ) + '%')
AND (P.CategoryId = #CategoryId OR P.New = #IsNew
OR IIF(P.PriceDiscount IS NULL, 0, 1) = #IsDiscount)
Thanks a lot.

When using CASE inside a WHERE clause, without ELSE, what is meant by NULL?

declare #Name varchar(45)
SELECT
*
FROM
table law
WHERE
--law.emp = case when isnumeric(#Name) = 1 then #Name else null end
law.emp = case when isnumeric(#Name) = 1 then #Name end
or coalesce(law.lname + ', ' + law.fname, '') like '%' + #Name + '%'
My question here is focusing on the CASE statement when it evaluates to something other than a numeric value...
If #Name is anything other than a numerical value, what is really happening? law.emp = null??? If so, it shouldn't return any results anyway, because the proper syntax is something like where law.emp is null, right?
So, just for clarification, my emp column doesn't actually contain any nulls.
I'm just trying to figure out what is really happening to my WHERE statement when #Name evaluates to something not numeric...
What actual evaluation is being done? Is SQL ignoring the condition?
That's kind of what I want: For SQL not to do anything with law.emp unless #Name is numeric. (I have other conditions that will use the #Name variable if it is text.)
The expression:
law.emp = NULL
always returns NULL. In a where clause, this is treated as false, and the row is not included in the result set.
I much prefer an explicit conversion:
law.emp = try_convert(int, #Name)
Or to whatever type emp is.

Add condition only if data exists

I want to add a condition to the WHERE clause ONLY if a variable has data.
I tried with the following case statement, but it has a syntax error.
Declare #last_name varchar(10) = null;
Select * from TABLE1
Where FirstName = 'John'
AND CASE WHEN #last_name IS NOT NULL THEN LastName = #last_name
Select * from TABLE1
where FirstName = 'John'
AND (#last_name IS NULL OR LastName = #last_name)
Others have already posted better ways to write the logic you are trying to express, but just in case you need to use the CASE syntax in the future, remember that the syntax requires you to include the word END. This tells SQL where the expression finishes.
This is what a basic CASE expression would look like:
CASE
WHEN MyField = 'MyValue' THEN 'MyResult'
WHEN MyField = 'MyOtherValue' THEN 'MyOtherResult'
ELSE 'NoResult'
END
Any CASE expression must have at least the CASE, WHEN, THEN, and END. The ELSE isn't strictly necessary - just be aware that if you don't include it, then the expression will return a NULL if none of the WHEN conditions are met.
You can try the following:
Declare #last_name varchar(10) = null;
Select * from TABLE1
Where FirstName = 'John'
AND LastName = ISNULL(#last_name, LastName)
You can also replace ISNULL with COALESCE too.

Build dynamic query according to variable value

I am using SQL Server 2008 R2.
I am facing problem while fetching records from database in Role Based Access.
I have a Table let us say TableA. I have 5 Columns in it i.e, ID (primary key), FirstName, LastName, RegistrationNumber, EmployeeIdent.
All the columns except ID are of Varchar type.
I have a stored procedure to search the records. I am passing string to it and finding matching records from all five columns.
Now, the problem I am facing is in Role Based Access.
The requirement is when user is of "Admin" type then find matching records from all five columns but when is of "naive" user type then search matching records from only ID column.
I have passed the variable #userType to stored procedure from which I can determine the user type.
One way to resolve this problem is If Condition. Like if (#userType) = 'Admin' then some query Else Some other.
But I don't want to write query in If Condition.
Another way to resolve this is to store query in varchar type of variable and then execute is using EXEC (), but I have heard that it creates more overhead on server (I am not sure about it).
So any other way to fulfill this requirement?
The query to search records is
DECLARE #SearchText VARCHAR(MAX)= ''
SELECT *
FROM TableA
WHERE
Convert(varchar,ID) LIKE CASE WHEN LEN(#SearchText) = 0 THEN Convert(varchar,ID) ELSE '%'+ ISNULL(#SearchText,'0') + '%' END OR
FirstName LIKE CASE WHEN LEN(#SearchText) = 0 THEN FirstName ELSE '%'+ ISNULL(#SearchText,'') + '%' END OR
LastName LIKE CASE WHEN LEN(#SearchText) = 0 THEN LastName ELSE '%'+ ISNULL(#SearchText,'') + '%' END OR
RegistrationNumber LIKE CASE WHEN LEN(#SearchText) = 0 THEN RegistrationNumber ELSE '%'+ ISNULL(#SearchText,'') + '%' END OR
EmployeeIdent LIKE CASE WHEN LEN(#SearchText) = 0 THEN EmployeeIdent ELSE '%'+ ISNULL(#SearchText,'') + '%' END
SELECT
*
FROM TABLEA
WHERE
(#userType = 'admin'
--add any other criteria for admin type here
) or (
#userType = 'naive'
--add any other criteria for naive type here
)

creating SQL command to return match or else everything else

i have three checkboxs in my application. If the user ticks a combination of the boxes i want to return matches for the boxes ticked and in the case where a box is not checked i just want to return everything . Can i do this with single SQL command?
I recommend doing the following in the WHERE clause;
...
AND (#OnlyNotApproved = 0 OR ApprovedDate IS NULL)
It is not one SQL command, but works very well for me. Basically the first part checks if the switch is set (checkbox selected). The second is the filter given the checkbox is selected. Here you can do whatever you would normally do.
You can build a SQL statement with a dynamic where clause:
string query = "SELECT * FROM TheTable WHERE 1=1 ";
if (checkBlackOnly.Checked)
query += "AND Color = 'Black' ";
if (checkWhiteOnly.Checked)
query += "AND Color = 'White' ";
Or you can create a stored procedure with variables to do this:
CREATE PROCEDURE dbo.GetList
#CheckBlackOnly bit
, #CheckWhiteOnly bit
AS
SELECT *
FROM TheTable
WHERE
(#CheckBlackOnly = 0 or (#CheckBlackOnly = 1 AND Color = 'Black'))
AND (#CheckWhiteOnly = 0 or (#CheckWhiteOnly = 1 AND Color = 'White'))
....
sure. example below assumes SQL Server but you get the gist.
You could do it pretty easily using some Dynamic SQL
Lets say you were passing your checkboxes to a sproc as bit values.
DECLARE bit #cb1
DECLARE bit #cb2
DECLARE bit #cb3
DECLARE nvarchar(max) #whereClause
IF(#cb1 = 1)
SET #whereClause = #whereClause + ' AND col1 = ' + #cb1
IF(#cb2 = 1)
SET #whereClause = #whereClause + ' AND col2 = ' + #cb2
IF(#cb3 = 1)
SET #whereClause = #whereClause + ' AND col3 = ' + #cb3
DECLARE nvarchar(max) #sql
SET #sql = 'SELECT * FROM Table WHERE 1 = 1' + #whereClause
exec (#sql)
Sure you can.
If you compose your SQL SELECT statement in the code, then you just have to generate:
in case nothing or all is selected (check it using your language), you just issue non-filter version:
SELECT ... FROM ...
in case some checkboxes are checked, you create add a WHERE clause to it:
SELECT ... FROM ... WHERE MyTypeID IN (3, 5, 7)
This is single SQL command, but it is different depending on the selection, of course.
Now, if you would like to use one stored procedure to do the job, then the implementation would depend on the database engine since what you need is to be able to pass multiple parameters. I would discourage using a procedure with just plain 3 parameters, because when you add another check-box, you will have to change the SQL procedure as well.
SELECT *
FROM table
WHERE value IN
(
SELECT option
FROM checked_options
UNION ALL
SELECT option
FROM all_options
WHERE NOT EXISTS (
SELECT 1
FROM checked_options
)
)
The inner subquery will return either the list of the checked options, or all possible options if the list is empty.
For MySQL, it will be better to use this:
SELECT *
FROM t_data
WHERE EXISTS (
SELECT 1
FROM t_checked
WHERE session = 2
)
AND opt IN
(
SELECT opt
FROM t_checked
WHERE session = 2
)
UNION ALL
SELECT *
FROM t_data
WHERE NOT EXISTS (
SELECT 1
FROM t_checked
WHERE session = 2
)
MySQL will notice IMPOSSIBLE WHERE on either of the SELECT's, and will execute only the appropriate one.
See this entry in my blog for performance detail:
Selecting options
If you pass a null into the appropriate values, then it will compare that specific column against itself. If you pass a value, it will compare the column against the value
CREATE PROCEDURE MyCommand
(
#Check1 BIT = NULL,
#Check2 BIT = NULL,
#Check3 BIT = NULL
)
AS
SELECT *
FROM Table
WHERE Column1 = ISNULL(#Check1, Column1)
AND Column2 = ISNULL(#Check2, Column2)
AND Column3 = ISNULL(#Check3, Column3)
The question did not specify a DB product or programming language. However it can be done with ANSI SQL in a cross-product manner.
Assuming a programming language that uses $var$ for variable insertion on strings.
On the server you get all selected values in a list, so if the first two boxes are selected you would have a GET/POST variable like
http://url?colors=black,white
so you build a query like this (pseudocode)
colors = POST['colors'];
colors_list = replace(colors, ',', "','"); // separate colors with single-quotes
sql = "WHERE ('$colors$' == '') OR (color IN ('$colors_list$'));";
and your DB will see:
WHERE ('black,white' == '') OR (color IN ('black','white')); -- some selections
WHERE ('' == '') OR (color IN ('')); -- nothing selected (matches all rows)
Which is a valid SQL query. The first condition matches any row when nothing is selected, otherwise the right side of the OR statement will match any row that is one of the colors. This query scales to an unlimited number of options without modification. The brackets around each clause are optional as well but I use them for clarity.
Naturally you will need to protect the string from SQL injection using parameters or escaping as you see fit. Otherwise a malicious value for colors will allow your DB to be attacked.