SELECT statement having where clause with dynamic condition - sql

I have a small select query which picks data from a table as per the parameter passed to a procedure.
DECLARE #flgParam bit
.
.
SELECT *
FROM tablename
WHERE flgRequired like <If #flgparam is 0 then 1 or zero , Else 1>
what is the best way to construct the where clause

I'm thinking something like this:
SELECT *
from tablename
where #flgparam is null or #flgcolumnval = #flgparam;
#flgparam is declared as a bit, so it can only take on the values of NULL, 0, and 1.
EDIT:
I'm trying to understand the logic. Adapted for the right names:
SELECT *
from sample
where (#flgparam = 0 and flgRequired is not null) or
(coalesce(#flgparam, 1) = 1 and flgRequired = 1)
The like is unnecessary; you can do strict equality.

A bit rough, but it should work, based on requirements:
select
S.itemname
,S.flgrequired
from
sample S
where
(S.flgRequired >= #flgParam)
Tested on sqlfiddle.

You cant use variables to substitute columns in the querys, to achieve that you should create your query as a string #QUERY and execute it using exec #QUERY

Related

Anything like template literals while writing a search query in SQL?

I am writing a stored procedure to get a particular value.
declare #num int
set #num = (SELECT Id
FROM [sometable]
WHERE Name like '%today%')
-- returns #num = 1
Select Value
FROM [anothertable]
where name like 'days1'
In the last line of the query I want to add "1" or any other number after 'days', depending on the variable #num.
How can I do it, sort of like how we use template literals in Javascript, using the ${} syntax but in SQL?
You can just use the first query as a sub-query of the second:
select [Value]
from anothertable
where [name] = Concat('days', (select Id from sometable where [Name] like '%today%'));

how to check a dynamic column name is null

I have a table like below which has several columns along with series of numbers as well like the below:
Name: JLEDG
name
user_val_1
user_val_2
user_val_3
user_val_4
One
Two
Three
Three
Three
DECLARE #myvar int = 3;
So I would like to do the following which is not working:
SELECT * FROM JLEDG WHERE ('user_val_' + #myvar) IS NULL;
Expect the sql should be
SELECT * FROM JLEDG WHERE user_val_3 IS NULL;
You can only do that in dynamic SQL. You seem to have a problem with your data model. You shouldn't be storing values splayed across columns like that. You should have another table with one row per value.
One thing you can do is unpivot (using apply) and then filter:
select j.*
from jledg j cross apply
(values (1, user_val_1), (2, user_val_2), . . .
) v(which, user_val)
where which = #myvar;
The alternative is to use dynamic SQL (sp_executesql), but that seems quite cumbersome when you could just fix the data model.
SQL Server is declarative by design, and does not support macro substitution. As Gordon mentioned in his solution (+1), Dynamic SQL is just another option
Example
Declare #myvar int = 3
Declare #SQL varchar(max) = concat('SELECT * FROM JLEDG WHERE user_val_',#myvar,' IS NULL;')
Exec(#SQL)

Find whole value without using LIKE operator

I have a large number to find in a table. But only a little part of it is given to me to find the whole number. I am looking for some new way to find these out without using the like operator. I know it is a simple thing, but I need a new approach.
Value given is: 4213076600
Value to find is: 89013106904213076600
I want to find it in the following query:
SELECT *
FROM table_name
WHERE column_name in (value,value,value)
i have searched the websites for this and came to know about the left() and right() functions but don't know how to arrange them to get the result
You can use CONTAINS more info:
SELECT *
FROM table_name
WHERE CONTAINS(column_name , '"*value*"')
For CONTAINS you need to create a FULL TEXT INDEX on the table.
DECLARE #table table (n varchar(20))
DECLARE #param1 varchar(20)
SET #param1 = '4213076600'
INSERT INTO #table (n)
SELECT '89013106904213076600'
SELECT n
FROM #table
WHERE RIGHT(n, len(#param1)) = #param1
Edit
select *
from table_name
where right(column_name, len(value)) = value
SELECT
*
FROM
table_name
WHERE
CHARINDEX(value1,column_name)>0
OR CHARINDEX(value2,column_name)>0
OR CHARINDEX(value3,column_name)>0
SELECT left(column_name,length_of_value)
FROM table_name
WHERE RIGHT(column_name,length_of_value_given) IN (value,value,value)
That's way it works for IN clause

SQL Statement Match Anything

I use a regex in my SQL statements for an app that look like this
SELECT * FROM table WHERE id = {{REPLACEME}}
However, sometimes I'm not giving a parameter to replace that string with. Is there a way to replace it with something that matches anything. I tried *, but that does not work.
SELECT * FROM table WHERE id = id will match all rows that have non-null id
SELECT * FROM table WHERE id = id OR id IS NULL will match all rows.
id is probably a primary key, so you can probably use the former.
Replace {{REPLACEME}} with
[someValidValueForYouIdType] OR 1=1
I can only describe my solution with an example. The #AllRec is a parameter:
Declare #AllRec bit
set #AllRec = {0|1} --as appropriate
SELECT *
FROM table
WHERE
(
id = {{REPLACEME}}
and #AllRec = 0
) OR (
#AllRec = 1
)
In this solution, if #AllRec is 1 then everything is returned, ignoring the id filter. If #AllRec is zero, then the id filter is applied and you get one row. You should be able to quickly adapt this to your current regex solution.
Using the Regex-Replace option opens you up to SQL Injection attacks.
Assuming your language has support for parameterized queries, try this modified version of Jacob's answer:
SELECT * FROM table WHERE (id = #id OR #id IS NULL)
The catch is that you'll always have to provide the #id value.
SELECT field1, field2
FROM dbo.yourTable
WHERE id = isnull(#var, id)
Not sure what language your using, and this code kind of scares me but...
var statement = "SELECT * FROM table";
If REPLACEME is not empty Then
statement += " WHERE id = {{REPLACEME}}"
End If

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.