T-SQL: WHERE Clause - How to adjust based on input variable - sql

Using SQL Server 2008. I have an input param in my stored proc called '#State'. The param can basically be '--All--' or can contain the state to filter.
So, if it is '--All--' I don't want to incorporate the #State into the where clause. Otherwise I'd like it to filter based on the provided #State. So basically it could result in this....
SELECT * FROM MyTable
WHERE Type='AAA' AND Status=#Status
or, if they pass '--All--'
SELECT * FROM MyTable
WHERE Type='AAA'
How can I do this in a stored proc?

SELECT
*
FROM
MyTable
WHERE
Type='AAA'
AND Status = CASE #Status WHEN '--All--' THEN Status ELSE #Status END

I thought you made a typo. It should be #State, not #Status. This simple query might not be what you are looking for since you want to two sql statements in your requirement.
SELECT * FROM MyTable
WHERE Type='AAA' AND (#State='--All--' or State=#State)

Or...
you could make it even simpler than that:
SELECT * FROM MyTable
WHERE Type='AAA' AND #State in ('--All--', State)
No need to do it in a stored procedure, unless absolutely necessary (or if business/coding practice requires you to do so).

Related

Adding to WHERE clause conditions using CASE

I have a stored procedure that accepts an optional #ID param. When the param is passed in, I want the WHERE statement to include something like id = #ID, otherwise, when #ID is null, I don't want it to be filtered.
For example:
#ID BIGINT = NULL
SELECT * from myTable
WHERE
CASE
WHEN #ID IS NOT NULL THEN mytable.id = #ID
END
I am running this in SQL server 2016 and it says bad syntax near mytable.id = #ID. Can CASE be used in this way or should I try a different SQL method for this?
The only other option I considered to accomplish this was by using IF conditions in my stored procedure, but that didn't seem possible either based on my searches.
CASE is an expression, not a statement. It is not used to control flow like this and it will not work.
Your logic would need to be something like this.
Where mytable.id = ISNULL(#ID, mytable.id)
I should caution you that this pattern can lead to some poor performance. For a more detailed explanation and some other options you should check out this article. http://www.sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/
A bad-performance approach would be:
WHERE ISNULL(#ID,mytable.id) = mytable.id
A better-performance approach would be:
if(#ID IS NULL)
select * from ... without the WHERE condition
else
do your query with the condition mytable.id = #ID
Or build the query dynamically in the stored proc and execute it through sp_executesql passing parameters
Note: If the table is small enough, stick to simplicity and use the first option.

Parameterized WHERE clause in SQL Server Stored Procedure

I have a Stored Procedure to get the details of Invoices
Some occasions I get the list of invoices by sending only the InvoiceID
But in some other occasions I need to get the list of invoices as per the search fields supplied by the user. To do this I send all the fields to the Stored Procedure and use those parameters as below. I included only 2 columns but there are more.
SELECT * FROM INVOICES I
WHERE
(#InvoiceNumber is null or I.InvoiceNumber = #InvoiceNumber)
and
(#PONo is null or I.PONo = #PONo)
Is there a way to send the condition for the WHERE clause as one parameter?
Yes, it is possible with Dynamic SQL, but I highly discourage to do that.
SELECT * FROM tbl WHERE #condition:
If you are considering to write the procedure
CREATE PROCEDURE search_sp #condition varchar(8000) AS
SELECT * FROM tbl WHERE #condition
Just forget it. If you are doing this, you have not completed the transition to use stored procedure and you are still assembling your
SQL code in the client.
It will also open your application to SQL Injection attacks.
You can use custom type to pass table as parameter https://msdn.microsoft.com/pl-pl/library/bb510489(v=sql.110).aspx or you can use default parameters
If you're using SQL Server 2016 or similar (check by calling select compatibility_level, name from sys.databases and seeing that your DB is 130 or higher) then you can use the string_split builtin function.
I found it works best like this (spread out for clarity)
CREATE PROCEDURE [dbo].[GetInvoices]
#InvoiceNumber int = NULL
#PONo nvarchar(1024) = NULL
AS
SELECT * from [Invoices] AS [i]
WHERE
i.InvoiceNumber = ISNULL(#InvoiceNunber, i.InvoiceNunber)
AND CASE
WHEN #PONo is null
THEN 1
ELSE (CASE
WHEN i.PONo IN (select value from string_split(#PONo, ','))
THEN 1
ELSE 0
END)
END
= 1
So if you pass in a null to either parameter it gets translated as where x = x which is always true, and if you pass in a CSV value, it selects it from a split table of values that, if present, results in the where clause being where 1=1, which is true or 0=1 if the value is not present in the input list.
So here you can pass in an invoice number, or PO number, or both, or neither and it should return what you expect.

Execute a stored procedure within a case statement

I have an Insert Into Select statement with a Case When clause. I want to execute a stored procedure within the When statement.
Insert into Orders(id, custId, custIntake)
Select id, custId custIntake =
Case
When ( Exec mySProc(custId) = 1 ) = 'InStore'
When ( Exec mySProc(custId) = 0 ) = 'OutsideStore'
Else null
End
From OrdersImport
How can I run Exec mySProc(custId) within the Case When?
I would suggest you convert your 'mySProc' procedure into a Scalar User Defined Function if you want to run it like this. Stored Procedures are not able to do what you want.
If I understand correctly then what you need is code to run when the WHEN statement is true.
Just use CASE > WHEN > THEN as described here: http://msdn.microsoft.com/en-us/library/ms181765.aspx
Hope this helps.
Do like this.
If you set auto increment for id column, not need to mention in the query. If you need, you can add it.
Insert into orders(custId, custIntake)
Select custId, (CASE WHEN custId = '1' THEN 'InsideStore' ELSE 'OutsideStore' END) from ordersimport;
Hope, it will help you.

SQL Server Stored Procedure WHERE Clause IF CASE No Value

I have a stored procedure with default values, which I set to NULL. In the WHERE clause, for each value specified, rather than NULL or not given (where it would also be NULL), I would like the column to equal this value, otherwise, I would like to search without this column being in the WHERE clause. The basic structure looks something like this:
// Set up the stored procedure
USE Table;
GO
CREATE PROCEDURE dbo.SearchTable
// Specify value(s)
#Name varchar(50) = NULL
AS
// Set up the query
IF(#Name IS NOT NULL
SELECT * FROM Table WHERE Name=#Name;
ELSE
SELECT * FROM Table
BEGIN
END
I have more than 1 parameter, and so, with this logic, I would need 2 IF's for every parameter. As you can imagine, this gets boring, time-consuming, and error-prone fast.
I would like to move this logic into the query, preferably into the WHERE clause, but any way I have found will cause errors (besides exceptions, which would require just as many IF's). SQL Server doesn't like IF's in the WHERE clause as far as I know, and with CASE I would have to specify the column, which I do not want to do.
What should I do?
Edit:
I have SQL Server version 2012, so please concentrate on this or any recent versions in your answer.
If you don't care about performance, you can do:
SELECT *
FROM Table
WHERE #Name is null or Name = #Name;
Often, having an or condition gets in the way of efficient use of indexes. Perhaps this isn't a problem in your case, though.
You could do something like this. The downside to this is that indexes may not be used properly and thus the performance may not be great.
SELECT * FROM Table
WHERE (#Name Is Null Or Name = #Name)
And (#Col2 Is Null Or Col2 = #Col2)
And (#Col3 Is Null Or Col3 = #Col3)
Each column condition is "anded". Or is used to apply that column condition only if #var is not null. So for example, if this is called with just #Name populated, it is equivalent to Where Name = #Name. If both #Name and #Col2 are populated, it is equivalent to Where Name = #Name And Col2 = #Col2.

SQL Server 2005: Call a stored procedure from a WHERE clause

I need to make a SELECT with a call of a stored procedure in the WHERE clause.
It should be something like that....
SELECT distinct top 10 i.x, d.droit
FROM v_droit d, v_info i
WHERE d.nomdroit='yy'
AND i.id<>2
AND (select val from (exec up_droits(i.x, d.droit)) <>3
But it does not work...
Any idea?
Don't say to replace the stored procedure with a function because is not possible to use the existing code in a function. So the function is not a valid option. I really need to be able to use a stored procedure
This is achieved by first executing the stored procedure, capturing the output into a #temp table or a #tabel variable, then running your query against the table. Something like this:
declare #droits_table (val ,... );
insert into #droits_table
exec up_droits(param, param);
SELECT distinct top 10 i.x, d.droit FROM v_droit d, v_info i WHERE d.nomdroit='yy' AND i.id<>2 AND (select val from #droits) <>3
Of course this will not work for you because the up_droits needs the i.x and d.droit parameters from the query. This indicates that your stored procedure should probably be a a view or table valued function.
Sorry but, make it a table valued function rather than stored procedure.
Eg:
Scalar - SELECT id, name FROM test WHERE id < (SELECT dbo.mytestfunction())
Table - SELECT id, name FROM test WHERE id = (SELECT col1 from dbo.mytestfunction())
You can't. The content of the WHERE clause must be a search expression.
Is the reason that the code doesn't work as a function because it modifies some data? If so, then you're out of luck, functions used in where clauses must be immutable.
If the stored procedure doesn't modify any data, you may be able to wrap it inside of a function.
If you are on SQL Server I don't think you can do what you propose.
But one thing you can do is build dynamic queries, but be careful doing it because they open up many interesting problemareas.
The syntax is :
EXEC #<query>
But anotherthing you can do, which is probably much better for you, is to make the up_droits function deliver it's results in a temp table, if you select into a #table it is temporary for the duration of your function/procedure scope
declare procedure up_droits() as
select val .. into #temp
So what you do is create a procedure
create procedure Top10FromDroit
begin
exec up_droits
SELECT distinct top 10 i.x, d.droit FROM v_droit d, v_info i WHERE d.nomdroit='yy' AND i.id2 AND (select val from (#temp) 3
Hopefully that will give you the results you want to achieve.
If at first you don't succeed, code around it^^
Could anyone of you explain reasons for executing dynamic SQl inside stored procedure. I know very few situations when you need them - but really very few. 99.9% (or 999 of a 1000) of execute strings could be rewritten as normal sql statements with parameters.
The very same is with Selects that have functions inside select or where clauses.
Try to think about your sets of data, not about procedural ways how to solve it.