Sql where clause - sql

I have a stored procedure where I am passing a value to be used in the select statement in the where clause.
If the value that I am passing is NULL, I do not want it to be part of that portion of the where clause where it is used. In the example below, variable2 is the variable I am passing to the stored procedure and using in the sql statement but if #variable2 is NULL, I do not want to use variable2= #val1 in the where clause. Example:
select Field1, Field2 from tbl1
where variable2= #val1
and ID = 'test'

Try:
where (#val1 is null or variable2 = #val1)
and ID = 'test'

select Field1, Field2 from tbl1
where (variable2= #val1 or #val1 is null)
and ID = 'test'

How about:
select Field1, Field2 from tbl1
where (#val1 IS NULL or variable2 = #val1)
and ID = 'test'

Your WHERE clause should have the column on the left side, and that could possibly be the case but you are calling it variable2. This would work, given specific parameters:
select Field1, Field2
from tbl1
where yourColumn =
case
when #param1 is null
then #param2
end
I have used a generic field name and parameter names, but you should get the idea.

Related

SQL: CASE expression with declared variable

I have following example that doesn't work in SQL server.
table1.field1 is also a char(3)
DECLARE #CALCULATED_FIELD char(3);
SELECT table1.field1
,table1.field2
,CASE
WHEN table1.field2 = '1' THEN #CALCULATED_FIELD = table1.field1
ELSE #CALCULATED_FIELD = 'ALL'
END
FROM table1
Anyone knows the problem with the case statement?
A SQL Server SELECT statement can either assign variable values or return rows, but not both. You might intend:
SELECT #CALCULATED_FIELD = COALESCE(table1.field1, 'ALL')
FROM table1;
This would assign the maximum value to the variable -- and the only value if the table has only one row. If the table has no rows, the variable would be assigned 'ALL'.
The result of the CASE expression must be assigned to the variable, but it is not allowed in the same statement to return any columns from the table.
So this:
SELECT
#CALCULATED_FIELD = CASE
WHEN field2 = '1' THEN field1
ELSE 'ALL'
END
FROM table1
is syntactically valid, although it will assign to the variable finally, the result of the CASE expression of the last row fetched.
By the name of the variable, I suspect that you want a 3d column which will be calculated by CASE:
SELECT field1, field2,
CASE
WHEN field2 = '1' THEN field1
ELSE 'ALL'
END calculated_field
FROM table1
See a simplified demo.
I would use a scaler funtion in this case
CREATE FUNCTION calcfield
(
#field2 VARCHAR(4),
#field1 VARCHAR(4)
)
RETURNS VARCHAR(3)
AS
BEGIN
DECLARE #CalcField CHAR(3)
SELECT #CalcField = CASE
WHEN #field2 = '1' THEN #field1
ELSE 'ALL'
END
RETURN #CalcField
END
GO
and then change your query to
SELECT table1.field1
,table1.field2
,dbo.calcfield(table1.field2,table1.field1)
FROM table1
Expressions like A=B is not a scalar value. So when you run the following query, it fails and you will get an error Incorrect syntax near '='.
SELECT ('aaa' = 'aaa')
In your case
CASE WHEN table1.field2 = '1'
THEN #CALCULATED_FIELD = table1.field1
ELSE #CALCULATED_FIELD = 'ALL'
END
is not a valid expression, and you might mean something like
CASE WHEN table1.field2 = '1'
THEN (CASE WHEN #CALCULATED_FIELD = table1.field1 THEN 1 ELSE 0)
ELSE (CASE WHEN #CALCULATED_FIELD = 'ALL' THEN 1 ELSE 0)
END
Please note that you can run a query like
SELECT columnName = 'aaa'
and it works as
SELECT 'aaa' AS columnName
Thx a lot.
For the create function, I have no rights and we can't do it on the production environment. But would work. Nice.
The example from forpas used and it works perfect for me.

SQL partial update of columns based on case statement?

Recently I have had to do a few variable updates to a table, and although I am aware of the MERGE statement (although need to catch up on all of that!), I also performed the following statement to optional update a table and wish to check if this is "a good idea" or has some hidden consequences that I not aware of.
So in my case, I pass a primary key to a table, however depending on if parameters passed are null or not, I update the column.. obviously if you had to ensure a forceful update (of a status etc.) then you would just update the column.. this is to save having multiple "IF / THEN" type structures..
create procedure sp_myprocedure
as
#id bigint,
#field1 int = null,
#field2 varchar(255) = null,
#field3 char(1) = null
begin
update my_table
set
field1 = case when #field1 is not null then #field1 else field1 end,
field2 = case when #field2 is not null then #field2 else field2 end,
field3 = case when #field3 is not null then #field3 else field3 end,
where
id = #id
end
Just after some thoughts of the above or is it best to pursue the MERGE statement for scenarios like the above?
Many thanks in advance,
This is fine although it can be written in a cleaner way.
update my_table
set
field1 = coalesce (#field1,field1)
,field2 = coalesce (#field2,field2)
,field3 = coalesce (#field3,field3)
where
id = #id and coalesce(#field1,#field2,#field3) is not null
You can also move the coalesce(#field1,#field2,#field3) is not null to a wrapper block
if coalesce(#field1,#field2,#field3) is not null
begin
update my_table
set
field1 = coalesce (#field1,field1)
,field2 = coalesce (#field2,field2)
,field3 = coalesce (#field3,field3)
where
id = #id
end
MERGE statement is not relevant here.
With MERGE the decision is if to INSERT, UPDATE or DELETE a record base on the non-existent/existent of a record with the same merge keys in the source/target table.
In your case it is always UPDATE.
create procedure sp_myprocedure
#id bigint,
#field1 int = null,
#field2 varchar(255) = null,
#field3 char(1) = null
as
begin
IF coalesce(#field1,#field2,#field3) is not null
update dbo.my_table
set
field1 = coalesce (#field1,field1),
field2 = coalesce (#field2,field2),
field3 = coalesce (#field3,field3)
where id = #id
END
Responding to the answer by #Dudu Markovitz:
MERGE statement is not relevant here.
I disagree , I think MERGE is entirely relevant here.
The idea is to create a source table expression using the parameter values with which to update the target table:
MERGE my_table T
USING ( VALUES ( #id, #field1, #field2, #field3 ) )
AS S ( id, field1, field2, field3 )
ON T.id = S.id
WHEN MATCHED THEN
UPDATE
SET field1 = COALESCE( S.field1, T.field1 ),
field2 = COALESCE( S.field2, T.field2 ),
field3 = COALESCE( S.field3, T.field3 );
Of course, if there was a single table-valued parameter (as arguable there should be) then the relevance of MERGE is even more obvious.

Statement blocks in SQL SELECT using IF ELSE

I'm trying to return different data depending on a variable in a SELECT. Something like this:
SELECT
IF #variable = 'YES'
column1, column2
ELSE
column3
FROM TABLE
What is this the proper way to use the IF condition in SQL? Or is there a better alternative to what I'm trying to accomplish?
If you want to return a different number of columns, you'll need to use an IF:
IF #variable = 'YES'
BEGIN
SELECT column1, column2
FROM YourTable
END
ELSE
BEGIN
SELECT column3
FROM YourTable
END
If you want different data on the same column (assuming the same datatype), you could use a CASE:
SELECT CASE WHEN #variable = 'YES' THEN column1 ELSE Column2 AS Data
FROM YourTable
You can use an IF statement, but you'll need to set up multiple queries. You can use a CASE for selecting one column or another, but not to select one or multiple like in your question.
DECLARE #var INT = 1;
DECLARE #test TABLE (
Col1 int,
Col2 int,
Col3 int
)
INSERT INTO #test VALUES (1,2,3)
IF #var = 1
BEGIN
SELECT Col1, Col2
FROM #test
END
ELSE
BEGIN
SELECT Col3
FROM #test
END

Conditional filter in WHERE clause

How can I set a conditional filter in a SQL WHERE clause? For example, I have a parameter #ID with the following procedure
SELECT * FROM myTable WHERE Column1 = 'test' AND Column2 = #ID
However, If #ID = -1 I don't want the last part of the SQL (AND Column2 = #ID) included
I realize I can make an if statement with 2 separate queries, however this is a large script and has this same issue multiple times, so I was hoping there was a better way than nearly duplicating several queries
This is ok for T-SQL:
SELECT * FROM myTable WHERE Column1 = 'test' AND (#ID = -1 OR Column2 = #ID)
Just include the condition in your SQL as an OR, note the brackets
SELECT * FROM myTable WHERE Column1 = 'test' AND (#ID = -1 OR Column2 = #ID)
One alternative:
SELECT * FROM myTable WHERE Column1 = 'test' AND #ID in (-1,Column2)

Using Case Statement in SQL with parameter/variable to check for Null values

I am trying to write a SQL Select statement to return records based on a user input through a front end.
I want to write the Select statement like this:
SELECT somefields
FROM sometable
WHERE CASE variable
WHEN 'blank' THEN field IS NULL
ELSE field = field
END
Basically I either want to filter a column to find NULL values or ignore the filter and return all values depending on the value of the variable. I know that the results of the CASE statement is not executable but how can I do this?
When variable is 'blank', the following query will give you rows where field is NULL. When variable is anything else, it will give you all rows:
SELECT somefields
FROM sometable
WHERE
(variable = 'blank' AND field IS NULL)
OR (variable <> 'blank')
You can use NULLIF() (link is for SQL Server, but NULLIF() should be standard):
SELECT somefields
FROM sometable
WHERE field = NULLIF(variable, 'blank')
The following snippet should behave as follows:
when #variable is null, return all rows
when #variable = 'blank', return all rows where field is null or field = 'blank'
otherwise, return rows where #variable equals field
Code snippet:
WHERE 1 = CASE
WHEN #variable is null then 1
WHEN #variable = 'blank' and field is null then 1
WHEN #variable = field then 1
END
SELECT somefields
FROM sometable
WHERE ((variable IS NULL OR variable = 0) OR (variable = field))
WHERE Criteria is apply when variable have value
For Example:
DECLARE #CityName VARCHAR(50)
SET #CityName = NULL
SELECT CityName
FROM City
WHERE ((#CityName IS NULL ) OR (#CityName = CityName ))
When City is null then tables return all rows
I think I get what you're after. Something like this maybe?
SELECT field1,
field2,
CASE variable
WHEN 'blank' THEN NULL
ELSE field3
END as field3
FROM sometable
Think I understand what you mean....for example....
SELECT
House, Postcode
from
SomeTable
where
(House=isnull(#House,House) or (House is null and #House is null))
and
(Postcode=isnull(#Postcode,Postcode) or (Postcode is null and #Postcode is null))
First bit of the conditional where is to use the variable, when present (the isnull bit is to ignore the variable if it's null)
Second bit of the conditional where is in case your evaluative field is null also as effectively fields don't = null they are 'is null'.
Confused? Good. Works on what I'm doing though!
Here is my solution based on #Andomar answer above aimed at anyone testing an input varchar value, you need to test the parameter in the right order as per the example below:
FIELD1 = CASE
WHEN #inputParameter = '' THEN FIELD1
WHEN #inputParameter <> FIELD1 THEN NULL -- if input is some text but does not match
WHEN #inputParameter IS NULL THEN FIELD1
WHEN #inputParameter != '' AND FIELD1 = #inputParameter THEN FIELD1
END
Hope this helps someone.