SQL: Conditional AND in where - sql

I'm trying to create a stored procedure that allows parameters to be omitted, but ANDed if they are provided:
CREATE PROCEDURE
MyProcedure
#LastName Varchar(30) = NULL,
#FirstName Varchar(30) = NULL,
#SSN INT = NULL
AS
SELECT LastName, FirstName, RIGHT(SSN,4) as SSN
FROM Employees
WHERE
(
(LastName like '%' + ISNULL(#LastName, '') + '%')
AND
(FirstName like '%' + ISNULL(#FirstName, '') + '%')
)
AND
(SSN = #SSN)
I only want to do the AND if there's an #SSN provided. Or is there some other way to do this?
If an SSN is provided, all records are returned by the LastName/FirstName part of the query. If just a lastname/firstname is provided, the AND makes it so no records are returned since the SSN won't validate.
Ideas?
Additional Clarification
Assume a basic recordset:
First Last SSN
Mike Smith 123456789
Tom Jones 987654321
IF we ALTER the Procedure above so it doesn't include this chunk:
AND
(SSN = #SSN)
then everything works great, provided we're passed a FirstName or LastName. But I want to be able to include SSN, if one is provided.
If I change the AND to an OR, then I get a bad result set since the FirstName/LastName portion of the query evalute to:
WHERE (LastName like '%%' and FirstName like '%%')
(which will, of course, return all records)
If I can't conditionally abort the AND, I'm hoping for something like:
AND
(SSN like ISNULL(#SSN, '%'))
:-)

Change:
AND (SSN = #SSN)
to:
AND (SSN = #SSN or #SSN is null)
If SSN is never null, you could also do:
AND SSN = ISNULL(#SSN, SSN)

You can also try:
(ISNULL(SSN, #SSN) = #SSN)

You could put both versions of the statement in an if block.
AS
IF #SSN IS NULL
/*regular statement*/
ELSE
/*Statement with #SSN*/
or
AND
SSN = ISNULL(#SSN, SSN)
I have never used the 2nd option but I know it exists.

HERE's THE BIBLE on dynamic search parameters in SQL Server. You should write it like this
SELECT LastName, FirstName, RIGHT(SSN,4) as SSN
FROM Employees
WHERE (NULLIF(#LastName,'') IS NULL OR LastName LIKE '%' + #LastName + '%')
AND (NULLIF(#FirstName,'') IS NULL OR FirstName LIKE '%' + #FirstName + '%')
AND (#SSN is null or SSN = #SSN)
-- or if not provided means blank, then
-- (#SSN = '' or SSN = #SSN)
OPTION (RECOMPILE)
BTW, there's no such thing as a short circuit boolean in SQL Server. Yes it does stop at the first conclusion, but there's no guarantee the condition on the left is processed before the right. e.g. this code is NOT SAFE. I'm using 'ABC.123' but that could just as well be a column.
WHERE ISNUMERIC('ABC.123') = 1 OR CAST('ABC.123' AS INT) > 10
To illustrate on the AND (#SSN is null or SSN = #SSN) clause, for when #SSN is not provided, i.e. NULL
AND (#SSN is null or SSN = NULL)
=> AND (NULL IS NULL or SSN = NULL)
=> AND (TRUE or SSN = NULL)
=> AND (TRUE)
-- In other words, this filter is "dissolved" and appears as if it never existed.
-- (in the scheme of a series of AND conditions)

CREATE PROCEDURE
MyProcedure
#LastName Varchar(30) = NULL,
#FirstName Varchar(30) = NULL,
#SSN INT = -1
AS
SELECT LastName, FirstName, RIGHT(SSN,4) as SSN
FROM Employees
WHERE
(
(LastName like '%' + ISNULL(#LastName, '') + '%')
AND
(FirstName like '%' + ISNULL(#FirstName, '') + '%')
)
AND
(SSN = #SSN or #SSN = -1)
Just give #SSN a default value and you can use the AND all the time and worry about it.

Related

Case Statement in Where Clause NULL case [duplicate]

This question already has answers here:
CASE in WHERE, SQL Server
(5 answers)
Closed 4 years ago.
I'm creating a query (to eventually be used in a stored procedure) with multiple variations on what criteria is entered in a form. Sometimes there can be an entry, sometimes not. Sometimes the data field has a value, sometimes it's NULL.
The fields in my form are NAME, SSN, and DRLICENSE.
DECLARE #name VARCHAR(30);
DECLARE #ssn VARCHAR(10);
DECLARE #drlic VARCHAR(10);
--(if for example, someone enters data in two of the fields like this...)
SET #name = 'SMITH'
SET #drlic = 'D'
(In stored procedure)
SET #name = #name + '%'
SET #ssn = #ssn + '%'
SET #drlic = #drlic + '%'
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
NAME LIKE CASE WHEN LEN(#name) > 1 THEN #name ELSE NAME END
AND SSN LIKE CASE WHEN len(#ssn) > 1 THEN #ssn ELSE SSN END
AND DRLICENSE LIKE CASE WHEN LEN(#drlic) > 1 THEN #drlic ELSE DRLICENSE END
The idea behind my case statement is to check the variable for usage and perform a like if the name, ssn, or drlicense are partial entries.
My question is: how do I account for the case of NULL in the table column (i.e. SSN LIKE SSN does not work when SSN is NULL because SSN IS NULL needs to be there).
This isn't going to perform well, especially since you are using LIKE but parentheses are important here
where ((#name is null or name like '%' + #name + '%') or ( name is null))
and ((#ssn is null or ssn like '%' + #ssn + '%') or (ssn is null))
and ((#drlic is null or DRLICENSE like '%' + #drlic + '%') or (DRLICENSE is null))
This will return the NULL values in those columns regardless if a parameter is passed in or not. If you don't want the NULL then just remove the or ( name is null)) section from each line. I wasn't certain from your post.
if length(#foo) <= 1
set #foo = NULL
if length(#bar) <= 1
set #bar = NULL
...
WHERE (#foo is NULL or t.foo = #foo)
AND (#bar is NULL or t.bar like #bar)
OPTION (RECOMPILE)
This should do it:
WHERE (#name IS NULL OR name LIKE #name + '%')
AND (#ssn IS NULL OR ssn LIKE #ssn + '%')
AND (#drlic IS NULL OR drlicense LIKE #drlic + '%')
Note that if, for example, user searched for name = foo then it will return rows that match foo% and not rows that have NULL name.
You can inline adding the wild card to the parameter value and add your null checks inline as well. There is no need for a CASE statement either. For each of the parameter/column values the result returns true if the parameter is null or if the column value is null or if the column value starts with the passed in parameter value.
Where statement:
WHERE (Name IS NULL OR #name IS NULL OR Name LIKE #name + '%')
AND (SSN IS NULL OR #ssn IS NULL OR SSN LIKE #ssn + '%')
AND (DRLICENSE IS NULL OR #drlic IS NULL OR DRLICENSE LIKE #drlic + '%')
The key here is to not do any filtering if the incoming value to use is null or if the column value is null which I assume you do not want filtered on if it is null.
You could use ISNULL() it's very useful in cases like yours.
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
ISNULL(NAME,0) LIKE ISNULL(ISNULL(#name, NAME),0)
AND ISNULL(SSN,0) LIKE ISNULL(ISNULL(#ssn, SSN),0)
AND ISNULL(DRLICENSE,0) LIKE ISNULL(ISNULL(#drlic, DRLICENSE),0)
This method will replace the NULL values with the column value if the column value is NULL then both will be set to 0 (which will be 0=0, which will always be true).
If I understand correctly, you want a NULL-safe equality. That is, you want NULL to match NULL and values to match values. So:
where (name = #name or (name is null and #name is null)) and
(ssn = #ssn or (ssn is null and #ssn is null)) and
(drlicense = #drlicense or (drlicense is null and #drlicense is null))
or, an intriguing variant:
where (select count(*)
from (select distinct *
from (values (name, 'name'), (#name, 'name'), (ssn, 'ssn'), (#ssn, 'ssn'), (drlicense, 'drlicense'), (#drlicense, 'drlicense')
v(val, which)
) x
) = 3
This is using group by semantics to combine NULL values.
Or, if you want some obfuscation:
where nullif(name, #name) is null and nullif(#name, name) is null and
nullif(ssn, #ssn) is null and nullif(#ssn, ssn) is null and
nullif(drlicense, #drlicense) is null and nullif(#drlicense, drlicense) is null

SQL OR CONDITION ON TWO DIFFERENT COLUMNS

I have two fields (#EmployeeId,#SSOId) out of which one value can come or both can come, but when i am applying OR condition it is not giving me correct output. What i am doing wrong ?
ALTER PROCEDURE [dbo].[usp_User_GetDetails] (
#UserId INT = NULL
,#ADSId NVARCHAR(32) = NULL
,#EmployeeId NVARCHAR(32) = NULL
,#SSOId NVARCHAR(32) = NULL
,#UserName NVARCHAR(100) = NULL
)
AS
*/
SET NOCOUNT ON;
BEGIN
SELECT [USER_ID] AS UserId
,[FIRST_NM] AS FirstName
,[LST_NM] AS LastName
,[FULL_NM] AS FullName
,[ADS_USER_ID] AS ADSId
,[SEG_ID] AS SegmentId
,[PHONE_NO] AS PhoneNo
,[FAX_NO] AS FaxNo
,[EMP_ID] AS EmployeeId
,[EMAIL_AD_TX] AS Email
,[SSO_ID] AS SSOId
,[SFDC_IN] AS IsSFDC
,[USER_SFDC_ID] AS UserSFDCId
,[MGR_SFDC_ID] AS ManagerSFDCId
,[ACT_IN] AS IsActive
,[SYS_USER_IN] AS IsSystemUser
,[PORFOLIO_OWN_IN] AS CanHavePortfolio
,[MGR_ID] AS ManagerId
,[LST_LOG_IN_TS] AS LastLoginDate
,[EMP_BAND_TX] AS Band
,[CREAT_TS] AS CreatedDate
,[CREAT_BY_USER_ID] AS CreatedBy
,[LST_UPDT_TS] AS UpdatedDate
,[LST_UPDT_BY_USER_ID] AS UpdatedBy
FROM [dbo].[USER] WITH (NOLOCK)
WHERE ([EMP_ID] = ISNULL(#EmployeeId, [EMP_ID])OR [SSO_ID] = ISNULL(#SSOId, [SSO_ID])
AND [ADS_USER_ID] = ISNULL(#ADSId, [ADS_USER_ID])
AND [USER_ID] = ISNULL(#UserId, [USER_ID])
AND [FULL_NM] LIKE CASE
WHEN #UserName IS NOT NULL
THEN '%' + #UserName + '%'
ELSE [FULL_NM]
END
END
I don't think the parentheses are balanced correctly. In any case, I would write this without the ISNULL():
WHERE ((#EmployeeId IS NULL OR EMP_ID = #EmployeeId) OR
(#SSOId IS NULL OR SSO_ID = #SSOId)
) AND
(#ADSId IS NULL OR ADS_USER_ID = #ADSId) AND
(#UserId IS NULL OR USER_ID = #UserId) AND
(#UserName IS NULL OR FULL_NM LIKE '%' + #UserName + '%')
I am guessing that the OR is for the first two conditions. This is where the parens don't seem to line up in the query in the question.
I prefer this construct for two reasons. First, it handles NULL values in the column values as well as the parameter values. And second -- because it is more general -- it is one of the standard two ways I use to handle optional parameters (the other is to use dynamic SQL which can make use of indexes).
Query seems to be okay .Are you passing DBNull from you C# code or empty text
WHERE (#EmployeeId IS NULL OR (EMP_ID = #EmployeeId))
AND (#SSOId IS NULL OR (SSO_ID = #SSOId))
AND [ADS_USER_ID] = ISNULL(#ADSId, [ADS_USER_ID])
AND [USER_ID] = ISNULL(#UserId, [USER_ID])
AND [FULL_NM] LIKE CASE
WHEN #UserName IS NOT NULL
THEN '%' + #UserName + '%'
ELSE [FULL_NM]
Used this script
WHERE EMP_ID = CASE WHEN ISNULL(#EmployeeId,0) > 0 THEN #EmployeeId ELSE EMP_ID END AND SSO_ID = CASE WHEN ISNULL(#SSOId,0) > 0 THEN #SSOId ELSE SSO_ID END

Filter table data using select sql statement

I want to filter table data using select statement, I have four columns, and I have also four text boxes to enable search in each column,and I can enter value in any box(es), when I enter value in text box(es) I want to return the record(s) that match the value(s) I have entered, how can I do that?
ALTER PROCEDURE dbo.test_search
(
#ID int,
#FirstName nvarchar(50),
#MiddleName nvarchar(50),
#LastName nvarchar(50)
)
AS
SELECT ID, FirstName, MiddleName, LastName
FROM StudentsInformation
WHERE (#ID IS NULL OR StudentsInformation.ID = #ID) AND
(#FirstName IS NULL OR StudentsInformation.FirstName = #FirstName )AND
(#MiddleName IS NULL OR StudentsInformation.MiddleName = #MiddleName )AND
(#LastName IS NULL OR StudentsInformation.LastName = #LastName )
RETURN
EDIT:
SELECT
id
, firstname
, middlename
, lastname
FROM studentsinformation
WHERE id = #id
OR firstname LIKE '%' + #firstname + '%'
OR middlename LIKE '%' + #middlename + '%'
OR lastname LIKE '%' + #lastname + '%'
You can swap OR for AND if you want to select records that are true for all the checkboxes.
Syntax Depends upon programming language which you use.
But generally:
string sql="select * from tableName where"
if((txt1.Text!="")&&(sql=="select * from tableName where")
sql=sql+"colName like % #txt1 %"
else
sql=sql+" and colName like % #txt1 %"
if((txt2.Text!="")&&(sql=="select * from tableName where")
sql=sql+"colName like % #txt2 %"
else
sql=sql+" and colName like % #txt2 %"
if((txt3.Text!="")&&(sql=="select * from tableName where")
sql=sql+"colName like % #txt3 %"
else
sql=sql+" and colName like % #txt3 %"
Do like this.
I hope this will work:
Select * from <table-name>
where
<Column-name1> Like 'TextBox1%'
or
<Column-name2> Like 'TextBox2%'
or
<Column-name3> Like 'TextBox2%'
or
<Column-name4> Like 'TextBox4%'
Firstly you need to find text-box in which search string is passed.
Depending on text-box the query could be written on the related the column.
select * from table_name where column like '%text-box value%'
Edit
SELECT ID,FirstName,MiddleName,LastName
FROM StudentsInformation
WHERE 1=1
ID=(case when #ID <>0 AND #ID IS NOT NULL then #ID else ID end)
and FirstName=(case when #FirstName<>'' and #FirstName IS NULL then #FirstName
else FirstName)
and MiddleName=(case when #MiddleName<>'' and #MiddleName IS NULL then #MiddleName
else MiddleName)
and LastName=(case when #LastName<>'' and #LastName IS NULL then #LastName
else LastName)

Optional Arguments in WHERE Clause [duplicate]

This question already has answers here:
Stored Procedure with optional "WHERE" parameters
(6 answers)
Closed 4 years ago.
Lets suppose there is a stored procedure that has 3 params. Out of all the possibilities, I'm looking to achieve this with a single WHERE clause without getting out of control with using () AND () OR () too much...
Example:
//Params
#CITY VARCHAR(100) = NULL,
#GENDER VARCHAR(100) = NULL,
#AGE VARCHAR(100) = NULL
I suppose you can do it using IF BEGIN ... END for each Variable if Exists, but that makes the code alot longer than desired..
This method below won't work because its way too long (there are about 10 different fields like this, but the example is only 3.) and i'm not sure if it even directly pulls up distinctive values...
SELECT NAME FROM TABLE
WHERE (
(CITY=#CITY AND GENDER=#GENDER AND AGE=#AGE)
OR (CITY=#CITY AND GENDER=#GENDER)
OR (GENDER=#GENDER AND AGE=#AGE)
OR (CITY=#CITY AND AGE=#AGE)
OR (CITY=#CITY)
OR (GENDER=#GENDER)
OR (AGE=#AGE)
)
Is there an even shorter more efficient way to do this?
If yes, it is preferable for the method to be compatible with JOIN's also.
Alternatively to the ISNULL / COALESCE options, you can test the parameters for being null:
SELECT NAME
FROM TABLE
WHERE
(#City IS NULL OR City = #City)
AND
(#Gender IS NULL OR Gender = #Gender)
AND
(#Age IS NULL OR Age = #Age)
what about this?
SELECT
NAME
FROM TABLE
WHERE CITY = COALESCE(#CITY, CITY)
AND GENDER = COALESCE(#GENDER, GENDER)
AND AGE = COALESCE(#AGE, AGE)
Try something like this:
SELECT NAME
FROM TABLE
WHERE
City = IsNull(#City, City) AND
Gender = IsNull(#Gender, Gender) AND
Age = IsNull(#Age, Age)
OR:
SELECT NAME
FROM TABLE
WHERE
(City = #City OR #City IS NULL) AND
(Gender = #Gender OR #Gender IS NULL) AND
(Age = #Age OR #Age IS NULL)
SELECT NAME
FROM TABLE
WHERE
City = case when isnull(#City ,'') = '' then City
else #City end
AND
Gender = case when isnull(#Gender ,'') = '' then Gender
else #Gender end
AND
Age = case when isnull(#Age ,0) = 0 then Age
else #Age end
Possibly this:
create procedure myProc
--Params
#CITY VARCHAR(100) = NULL,
#GENDER VARCHAR(100) = NULL,
#AGE VARCHAR(100) = NULL
as
SELECT NAME FROM [TABLE]
WHERE ISNULL(CITY,'')=ISNULL(#CITY,ISNULL(CITY,''))
AND ISNULL(GENDER,'')=ISNULL(#GENDER,ISNULL(GENDER,''))
AND ISNULL(AGE,'')=ISNULL(#AGE,ISNULL(AGE,''))
go
Assuming the columns in the WHERE clause are nullable, using ISNULL to avoid null comparison.

How do I create a stored procedure that will optionally search columns?

I'm working on an application for work that is going to query our employee database. The end users want the ability to search based on the standard name/department criteria, but they also want the flexibility to query for all people with the first name of "James" that works in the Health Department. The one thing I want to avoid is to simply have the stored procedure take a list of parameters and generate a SQL statement to execute, since that would open doors to SQL injection at an internal level.
Can this be done?
While the COALESCE trick is neat, my preferred method is:
CREATE PROCEDURE ps_Customers_SELECT_NameCityCountry
#Cus_Name varchar(30) = NULL
,#Cus_City varchar(30) = NULL
,#Cus_Country varchar(30) = NULL
,#Dept_ID int = NULL
,#Dept_ID_partial varchar(10) = NULL
AS
SELECT Cus_Name
,Cus_City
,Cus_Country
,Dept_ID
FROM Customers
WHERE (#Cus_Name IS NULL OR Cus_Name LIKE '%' + #Cus_Name + '%')
AND (#Cus_City IS NULL OR Cus_City LIKE '%' + #Cus_City + '%')
AND (#Cus_Country IS NULL OR Cus_Country LIKE '%' + #Cus_Country + '%')
AND (#Dept_ID IS NULL OR Dept_ID = #DeptID)
AND (#Dept_ID_partial IS NULL OR CONVERT(varchar, Dept_ID) LIKE '%' + #Dept_ID_partial + '%')
These kind of SPs can easily be code generated (and re-generated for table-changes).
You have a few options for handling numbers - depending if you want exact semantics or search semantics.
The most efficient way to implement this type of search is with a stored procedure. The statement shown here creates a procedure that accepts the required parameters. When a parameter value is not supplied it is set to NULL.
CREATE PROCEDURE ps_Customers_SELECT_NameCityCountry
#Cus_Name varchar(30) = NULL,
#Cus_City varchar(30) = NULL,
#Cus_Country varchar(30) =NULL
AS
SELECT Cus_Name,
Cus_City,
Cus_Country
FROM Customers
WHERE Cus_Name = COALESCE(#Cus_Name,Cus_Name) AND
Cus_City = COALESCE(#Cus_City,Cus_City) AND
Cus_Country = COALESCE(#Cus_Country,Cus_Country)
Taken from this page: http://www.sqlteam.com/article/implementing-a-dynamic-where-clause
I've done it before. It works well.
Erland Sommarskog's article Dynamic Search Conditions in T-SQL is a good reference on how to do this. Erland presents a number of strategies on how to do this without using dynamic SQL (just plain IF blocks, OR, COALESCE, etc) and even lists out the performance characteristics of each technique.
In case you have to bite the bullet and go through the Dynamic SQL path, you should also read Erland's Curse and Blessings of Dynamic SQL where he gives out some tips on how to properly write dynamic SQLs
It can be done, but usually these kitchen-sink procedures result in some poor query plans.
Having said all that, here is the tactic most commonly used for "optional" parameters. The normal approach is to treat NULL as "ommitted".
SELECT
E.EmployeeID,
E.LastName,
E.FirstName
WHERE
E.FirstName = COALESCE(#FirstName, E.FirstName) AND
E.LastName = COALESCE(#LastName, E.LastName) AND
E.DepartmentID = COALESCE(#DepartmentID, E.DepartmentID)
EDIT:
A far better approach would be parameterized queries.
Here is a blog post from one of the world's foremost authorities in this domain, Frans Bouma from LLBLGen Pro fame:
Stored Procedures vs. Dynamic Queries
Using the COALESCE method has a problem in that if your column has a NULL value, passing in a NULL search condition (meaning ignore the search condition) will not return the row in many databases.
For example, try the following code on SQL Server 2000:
CREATE TABLE dbo.Test_Coalesce (
my_id INT NOT NULL IDENTITY,
my_string VARCHAR(20) NULL )
GO
INSERT INTO dbo.Test_Coalesce (my_string) VALUES (NULL)
INSERT INTO dbo.Test_Coalesce (my_string) VALUES ('t')
INSERT INTO dbo.Test_Coalesce (my_string) VALUES ('x')
INSERT INTO dbo.Test_Coalesce (my_string) VALUES (NULL)
GO
DECLARE #my_string VARCHAR(20)
SET #my_string = NULL
SELECT * FROM dbo.Test_Coalesce WHERE my_string = COALESCE(#my_string, my_string)
GO
You will only get back two rows because in the rows where the column my_string is NULL you are effective getting:
my_string = COALESCE(#my_string, my_string) =>
my_string = COALESCE(NULL, my_string) =>
my_string = my_string =>
NULL = NULL
But of course, NULL does not equal NULL.
I try to stick with:
SELECT
my_id,
my_string
FROM
dbo.Test_Coalesce
WHERE
(#my_string IS NULL OR my_string = #my_string)
Of course, you can adjust that to use wild cards or whatever else you want to do.
Copying this from my blog post:
USE [AdventureWorks]
GO
CREATE PROCEDURE USP_GET_Contacts_DynSearch
(
-- Optional Filters for Dynamic Search
#ContactID INT = NULL,
#FirstName NVARCHAR(50) = NULL,
#LastName NVARCHAR(50) = NULL,
#EmailAddress NVARCHAR(50) = NULL,
#EmailPromotion INT = NULL,
#Phone NVARCHAR(25) = NULL
)
AS
BEGIN
SET NOCOUNT ON
DECLARE
#lContactID INT,
#lFirstName NVARCHAR(50),
#lLastName NVARCHAR(50),
#lEmailAddress NVARCHAR(50),
#lEmailPromotion INT,
#lPhone NVARCHAR(25)
SET #lContactID = #ContactID
SET #lFirstName = LTRIM(RTRIM(#FirstName))
SET #lLastName = LTRIM(RTRIM(#LastName))
SET #lEmailAddress = LTRIM(RTRIM(#EmailAddress))
SET #lEmailPromotion = #EmailPromotion
SET #lPhone = LTRIM(RTRIM(#Phone))
SELECT
ContactID,
Title,
FirstName,
MiddleName,
LastName,
Suffix,
EmailAddress,
EmailPromotion,
Phone
FROM [Person].[Contact]
WHERE
(#lContactID IS NULL OR ContactID = #lContactID)
AND (#lFirstName IS NULL OR FirstName LIKE '%' + #lFirstName + '%')
AND (#lLastName IS NULL OR LastName LIKE '%' + #lLastName + '%')
AND (#lEmailAddress IS NULL OR EmailAddress LIKE '%' + #lEmailAddress + '%')
AND (#lEmailPromotion IS NULL OR EmailPromotion = #lEmailPromotion)
AND (#lPhone IS NULL OR Phone = #lPhone)
ORDER BY ContactID
END
GO
We can use Generic #Search Parameter and pass any value to it for searching.
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: --
-- Create date:
-- Description: --
-- =============================================
CREATE PROCEDURE [dbo].[usp_StudentList]
#PageNumber INT = 1, -- Paging parameter
#PageSize INT = 10,-- Paging parameter
#Search VARCHAR(MAX) = NULL, --Generic Search Parameter
#OrderBy VARCHAR(MAX) = 'FirstName', --Default Column Name 'FirstName' for records ordering
#SortDir VARCHAR(MAX) = 'asc' --Default ordering 'asc' for records ordering
AS
BEGIN
SET NOCOUNT ON;
--Query required for paging, this query used to show total records
SELECT COUNT(StudentId) AS RecordsTotal FROM Student
SELECT Student.*,
--Query required for paging, this query used to show total records filtered
COUNT(StudentId) OVER (PARTITION BY 1) AS RecordsFiltered
FROM Student
WHERE
--Generic Search
-- Below is the column list to add in Generic Serach
(#Search IS NULL OR Student.FirstName LIKE '%'+ #Search +'%')
OR (#Search IS NULL OR Student.LastName LIKE '%'+ #Search +'%')
--Order BY
-- Below is the column list to allow sorting
ORDER BY
CASE WHEN #SortDir = 'asc' AND #OrderBy = 'FirstName' THEN Student.FirstName END,
CASE WHEN #SortDir = 'desc' AND #OrderBy = 'FirstName' THEN Student.FirstName END DESC,
CASE WHEN #SortDir = 'asc' AND #OrderBy = 'LastName' THEN Student.LastName END,
CASE WHEN #SortDir = 'desc' AND #OrderBy = 'LastName' THEN Student.LastName END DESC,
OFFSET #PageSize * (#PageNumber - 1) ROWS FETCH NEXT #PageSize ROWS ONLY;
END
My first thought was to write a query something like this...
SELECT EmpId, NameLast, NameMiddle, NameFirst, DepartmentName
FROM dbo.Employee
INNER JOIN dbo.Department ON dbo.Employee.DeptId = dbo.Department.Id
WHERE IdCrq IS NOT NULL
AND
(
#bitSearchFirstName = 0
OR
Employee.NameFirst = #vchFirstName
)
AND
(
#bitSearchMiddleName = 0
OR
Employee.NameMiddle = #vchMiddleName
)
AND
(
#bitSearchFirstName = 0
OR
Employee.NameLast = #vchLastName
)
AND
(
#bitSearchDepartment = 0
OR
Department.Id = #intDeptID
)
...which would then have the caller provide a bit flag if they want to search a particular field and then supply the value if they are to search for it, but I don't know if this is creating a sloppy WHERE clause or if I can get away with a CASE statement in the WHERE clause.
As you can see this particular code is in T-SQL, but I'll gladly look at some PL-SQL / MySQL code as well and adapt accordingly.
I would stick with the NULL/COALESCE method over AdHoc Queries, and then test to make sure you don't have performance problems.
If it turns out that you have slow running queries because it's doing a table scan when you're searching on columns that are indexed, you could always supplement the generic search stored procedure with additional specific ones that allow searching on these indexed fields. For instance, you could have a special SP that does searches by CustomerID, or Last/First Name.
Write a procedure to insert all employee data whose name start with A in table??