Stored procedure to search Table based on multiple values from dropdown - sql

I have three down with different values such as
Category One dropdown
Category Two dropdown
Year dropdown
I Have to search Product table based on dropdown values it should filter search based on any one of the dropdown or all of the dropdown selected values.
Let us say i have following fields in Product Table
ProductID
ProductName
ProductCatOne
ProductCatTwo
Description
Image
....
....
How is the most efficient way to write a store procedure so that i cant handle any of the three value selected. I want to avoid two many if statements in store procedure
ALTER PROCEDURE [dbo].[sp_SearchProduct]
#ProductID int,
#ProductCatOne int,
#ProductCatTwo int
AS
BEGIN
SET NOCOUNT ON;
If #ProductID > 0 THEN
END IF
END
STORED PROCEDURE FOR MS SQL SERVER
I am not sure how to create dynamic query inside SP fr this search

It is called Dynamic Search Conditions. I recommend you to read this excellent article by Erland Sommarskog. He explains several ways to do it and why OPTION(RECOMPILE) is needed if you don't use dynamic SQL as in the example below.
Few notes.
It is bad practice to name your stored procedures with the prefix sp_.
I prefer to pass NULL value instead of 0 to indicate that this parameter should be ignored. 0 value can be a valid value for search.
ALTER PROCEDURE [dbo].[SearchProduct]
#ProductID int,
#ProductCatOne int,
#ProductCatTwo int
AS
BEGIN
SET NOCOUNT ON;
SELECT
...
FROM Products
WHERE
(ID = #ProductID OR #ProductID IS NULL)
AND (ProductCatOne = #ProductCatOne OR #ProductCatOne IS NULL)
AND (ProductCatTwo = #ProductCatTwo OR #ProductCatTwo IS NULL)
OPTION(RECOMPILE);
END
This code assumes that columns ID, ProductCatOne, ProductCatTwo can't have NULLs.

ALTER PROCEDURE [dbo].[sp_SearchProduct]
#ProductID int,
#ProductCatOne int,
#ProductCatTwo int
AS
BEGIN
SET NOCOUNT ON;
IF #ProductID =''
SET #ProductID=NULL
IF #ProductCatOne =''
SET #ProductCatOne=NULL
IF #ProductCatTwo =''
SET #ProductCatTwo=NULL
SELECT *
FROM Product
WHERE ID = COALESCE (#ProductID,ID)
AND ProductCatOne =COALESCE (#ProductID,ProductCatOne )
AND ProductCatTwo=COALESCE (#ProductID,ProductCatTwo)
END

ALTER PROCEDURE [dbo].[SearchProduct]
#ProductID int,
#ProductName int,
#ProductCatOne int
AS
BEGIN
SET NOCOUNT ON;
SELECT
...
FROM Products
WHERE
(Case When #ProductID <> 'ALL' Then ProductID Else #ProductID End ) in(#ProductID) And
(Case When #ProductName <> 'ALL' Then ProductName Else #ProductName End ) in(#ProductName) And
(Case When #ProductCatOne <> 'ALL' Then ProductCatOne Else #ProductCatOne End ) in(#ProductCatOne)
END

Related

What's better to optimize a database: use a bunch of stored procedures with different filters or use a single one with if conditions?

I'm trying to optimize my database so, I decided to change a stored procedure which has a lot of "IF CONDITIONS" to filter with different parameters.
So, I was thinking on change it and make a bunch of stored procedures with different filters and stop using the one with a lot of "IF CONDITIONS"
And just validate on my backend which stored procedure use, instead of do it in SQL Server.
This is the best way to do it or there are better ways to do this?
Example of my actual stored procedure:
CREATE PROCEDURE [dbo].[sp_GetFilters]
#Id INT,
#Name VARCHAR(50),
#LastName VARCHAR(50),
#Age INT,
#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
IF #ID IS NOT NULL AND
#NAME IS NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE
WHERE ID = #ID
END
ELSE IF #ID IS NULL AND
#NAME IS NOT NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE WHERE
NAME = #NAME
END
...
and so on..
I want to change that one to a bunch of different stored procedures, each one of them with a unique filter
It is a good idea? There are better ways to optimize this stored procedure?
Thanks, for the help!
You could try one query, with parameter evaluation in the WHERE clause. I've used this approach widely with great success.
CREATE PROCEDURE dbo.sp_GetFilters
#Id INT = NULL
,#Name VARCHAR(50) = NULL
,#LastName VARCHAR(50) = NULL
,#Age INT = NULL
,#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM EXAMPLE_TABLE
WHERE 1 = 1
AND CASE WHEN #Id IS NULL THEN 1 ELSE ID END = CASE WHEN #Id IS NULL THEN 1 ELSE #Id END
AND CASE WHEN #Name IS NULL THEN '1' ELSE NAME END = CASE WHEN #Name IS NULL THEN '1' ELSE #Name END
AND CASE WHEN #Age IS NULL THEN 1 ELSE AGE END = CASE WHEN #Age IS NULL THEN 1 ELSE #Age END;
/* and so on....*/
END;

How can I return tables with different number of parameters with procedure?

I'm going to create different temp tables depending on the #selection parameter I get, and then I want to return the table I created.
I actually wanted to do it with the function, but I got an error for variable parameter tables. The sql procedur I wrote is as follows:
ALTER PROCEDURE [dbo].[Report]
(#Id BIGINT = 55,
#selection INT)
AS
BEGIN
IF #selection=1
BEGIN
Declare #tep_table table (Id int
,Name varchar(250)
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table
Select * from User
END
IF #selection=1
BEGIN
Declare #tep_table2 table (Id int
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table2
Select * from Client
END
IF #selection=1
BEGIN
RETURN #tep_table
END
ELSE
BEGIN
RETURN #tep_table2
END
END
I am getting this error:
Must declare the scalar variable "#tep_table"
Personally I would turn this into three procedures to avoid the performance problems faced with multiple execution paths.
Something like this.
ALTER Procedure [dbo].[Report]
(
#Id bigint = 55 --not sure what the point of this parameter is as it wasn't used anywhere in the sample code
, #selection int
) AS
set nocount on;
IF #selection = 1
exec GetUserData;
IF #selection = 2
exec GetClientData;
GO
create procedure GetUserData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from [User];
GO
create procedure GetClientData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from Client;
GO

Dynamic Where Condition Based on Parameter

I have a parameter based on which I need to include or exclude one condition in a where clause.
If the CustomerType parameter is blank, then I need to include a condition CustomerType is null, otherwise I need to exclude that CustomerType is null condition.
The SQL query is:
IF(#CustomerType = Blank)
BEGIN
Select * From Customer
Where
(CustomerType IN(#Type) Or CustomerType is null)
END
Else
Begin
Select * From Customer
Where
CustomerType IN(#Type)
End
Is there a better way to include or exclude this condition without using an IF ELSE condition like above?
Try
Select * From Customer
Where
(CustomerType is null AND #customertype ='')
OR
CustomerType IN (#Type)
You need change your "IN" part , however.
Edit:
Select * From Customer
Where (#customertype ='') OR CustomerType IN (...)
To handle all those input in one stored procedure:
CREATE PROCEDURE FIND_CUSTOMER_BY_TYPE #TYPE VARCHAR(50)
AS
BEGIN
-- a lazy check on your parameters
IF #TYPE LIKE '%[^0-9, ]%' BEGIN
RAISERROR('Invalid parameter',16,1);
return;
End;
SET NOCOUNT ON;
DECLARE #SQL VARCHAR(500);
SET #SQL='SELECT * FROM CUSTOMERS';
IF #TYPE>''
SET #SQL = #SQL + ' WHERE CUSTOMER_TYPE IN ('+#TYPE+')';
EXEC(#SQL);
SET NOCOUNT OFF;
END;
Your program can all this procedure with the parameter.

Stored procedure unsure syntax

I am trying to create a stored procedure that will determine if my customerid exists if it exists then my other parameter foundcustomer will be assigned to found otherwise not found. I am unsure how to assign found please help
here is what i tried
CREATE PROCEDURE procedure4
-- Add the parameters for the stored procedure here
#FoundCustomer varchar(10) = null,
#Customerid varchar (5) = null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
if Not(#Customerid is null)
SELECT customerid
from customers
where customerid = #Customerid
END
GO
Gordon is right, it sounds like you may want a function but if it has to be a stored procedure you can follow this example.
CREATE PROCEDURE procedure4
#Customerid varchar(5) = null
AS
BEGIN
SET NOCOUNT ON;
DECLARE #FoundCustomer varchar(10) = ''
IF #FoundCustomer is not null
BEGIN
IF (SELECT COUNT(1) FROM customers WHERE customerid = #customerid) > 0
SET #FoundCustomer = 'Found'
ELSE
SET #FoundCustomer = 'Not Found'
END
SELECT #FoundCustomer
END

Sql Stored Procedure to insert and update

I am new to Stored Procedures and SQL. Looking in to various articles, I found how to insert an record using stored procedure and it works.
CREATE PROCEDURE [dbo].[stprOrder]
#OrderDate date,
#OrderID nchar(50),
#ShipToID nchar(50),
#TotalAmt decimal(18,2),
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO ORDER(OrderDate,OrderID,ShipToID,TotalAmt)
Values(#OrderDate,#OrderID,#ShipToID,#TotalAmt)
END
I am not sure how to update an record using the same stprOrder stored procedure. Like the stored procedure should do inserting and updating depending on the OrderID.
Most likely you're looking for something like this
CREATE PROCEDURE [dbo].[stprOrder]
#OrderDate date,
#OrderID nchar(50),
#ShipToID nchar(50),
#TotalAmt decimal(18,2),
AS
BEGIN
SET NOCOUNT ON;
IF (SELECT TOP (1) 1 FROM ORDER WHERE OrderID = #OrderID) IS NULL
INSERT INTO ORDER(OrderDate,OrderID,ShipToID,TotalAmt)
Values(#OrderDate,#OrderID,#ShipToID,#TotalAmt)
ELSE
UPDATE ORDER SET OrderDate = #OrderDate, ShipToID = #ShipToID, TotalAmt = #TotalAmt
WHERE OrderID = #OrderID
END
First it checks if order with given ID already exists - if it doesn't - a new entry is created, otherwise existing record is updated
CREATE PROCEDURE [dbo].[stprOrder]
#OrderDate date,
#OrderID nchar(50),
#ShipToID nchar(50),
#TotalAmt decimal(18,2),
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT null FROM ORDER WHERE id = #orderID)
BEGIN
UPDATE ORDER SET ..... WHERE id = #orderID
END
ELSE
BEGIN
INSERT INTO ORDER(OrderDate,OrderID,ShipToID,TotalAmt)
VALUES(#OrderDate,#OrderID,#ShipToID,#TotalAmt)
END