Dynamic WHERE clause in SQL Server 2008 R2 - sql

I have a table which I'm querying using a dynamic conditional WHERE clause. I'm looking a best approach to get simple WHERE condition when all columns are null or when some columns has some value.
I tried something like this:
SET #CONDITIONS = CASE
WHEN #VEHICLE_TYPE_NAME IS NULL
THEN ' ISNULL(A.VEHICLE_TYPE_NAME,'''') = ISNULL(A.VEHICLE_TYPE_NAME,'''') '
ELSE ' A.VEHICLE_TYPE_NAME = ''' + #VEHICLE_TYPE_NAME + ''''
END + ' ' + CASE
WHEN CAST(#PRODUCT_ID AS VARCHAR(MAX)) IS NULL
THEN ' AND ISNULL(A.PRODUCT_ID, ''-1'') = ISNULL(A.PRODUCT_ID, ''-1'') '
ELSE ' AND A.PRODUCT_ID = ''' + CAST(#PRODUCT_ID AS VARCHAR(MAX)) + ''''
END + ' ' + CASE
WHEN CAST(#CAPABILITY_ID AS VARCHAR(MAX)) IS NULL
THEN ' AND ISNULL(A.CAPABILITY_ID,''-1'') = ISNULL(A.CAPABILITY_ID,''-1'') '
ELSE ' AND A.CAPABILITY_ID = ''' + CAST(#CAPABILITY_ID AS VARCHAR(MAX)) + ''''
END + ' ' + CASE
WHEN #SPONSOR_FIRM_ID IS NULL
THEN ' AND ISNULL(A.SPONSOR_FIRM_ID,'''') = ISNULL(A.SPONSOR_FIRM_ID,'''') '
ELSE ' AND A.SPONSOR_FIRM_ID = ''' + #SPONSOR_FIRM_ID + ''''
END + ' ' + CASE
WHEN #CLIENT_FIRM_ID IS NULL
THEN ' AND ISNULL(A.CLIENT_FIRM_ID,'''') = ISNULL(A.CLIENT_FIRM_ID,'''') '
ELSE ' AND A.CLIENT_FIRM_ID = ''' + #CLIENT_FIRM_ID + ''''
END + ' ' + CASE
WHEN CAST(#DIST_PLATFORM_ID AS VARCHAR(MAX)) IS NULL
THEN ' AND ISNULL(A.DIST_PLATFORM_ID,''-1'') = ISNULL(A.DIST_PLATFORM_ID,''-1'') '
ELSE ' AND A.DIST_PLATFORM_ID = ''' + CAST(#DIST_PLATFORM_ID AS VARCHAR(MAX)) + ''''
END + ' ' + CASE
WHEN #RR_INTERNAL_NUMBER IS NULL
THEN 'AND ISNULL(A.RR_INTERNAL_NUMBER,'''') = ISNULL(A.RR_INTERNAL_NUMBER,'''') '
ELSE ' AND A.RR_INTERNAL_NUMBER = ''' + #RR_INTERNAL_NUMBER + ''''
END

You don't need the part where your parameter is null. You can simply build up a dynamic SQL for each part
IF #PRODUCT_ID IS NOT NULL
#CONDITIONS = #CONDITIONS + ' AND A.PRODUCT_ID = ''' + CAST(#PRODUCT_ID AS VARCHAR(MAX)) + ''''

Why do you need dynamic SQL?
WHERE (#VEHICLE_TYPE_NAME IS NULL OR A.VEHICLE_TYPE_NAME = #VEHICLE_TYPE_NAME)
AND (#PRODUCT_ID IS NULL OR A.PRODUCT_ID = #PRODUCT_ID)
...

Related

when using "SELECT varname = something + something etc. I cannot then do "WHERE varname = ..."

I have:
SELECT KEYWORDS = CAST(USRN AS VARCHAR(15)) + ' ' +
RTRIM(SD) + ' ' + RTRIM(NL.LOCALITY_NAME) + ' ' +
RTRIM(NT.TOWN_NAME) + ' ' + RTRIM(NA.AUTHORITY_NAME)
That gives me what looks like a column, but is not:
I want to have it so my code only selects the rows from KEYWORDS that match whatever the user is typing. Normally, if KEYWORDS was a column, I would write:
SELECT .... WHERE KEYWORDS = '%whateverTheUserIsTyping%'
but I cannot because keywords is not a real column and it is telling me that it does not exist.
How do I get around this? thanks
The column alias KEYWORDS isn't visible to the SQL Engine at the time that the WHERE clause is evaluated. You can just repeat your CAST statment, though.
SELECT
KEYWORDS = CAST(USRN AS VARCHAR(15)) + ' ' +
RTRIM(STREET_DESCRIPTOR) + ' ' + RTRIM(NSG_LOCALITY.LOCALITY_NAME) + ' ' +
RTRIM(NSG_TOWN.TOWN_NAME) + ' ' + RTRIM(NSG_AUTHORITY.AUTHORITY_NAME)
FROM yourTable
WHERE
CAST(USRN AS VARCHAR(15)) + ' ' +
RTRIM(STREET_DESCRIPTOR) + ' ' + RTRIM(NSG_LOCALITY.LOCALITY_NAME) + ' ' +
RTRIM(NSG_TOWN.TOWN_NAME) + ' ' + RTRIM(NSG_AUTHORITY.AUTHORITY_NAME)
LIKE '%whateverTheUserIsTyping%'
You can use derived table with an alias (here Q) and get the result from that by filtering in WHERE clause:
SELECT Q.KEYWORDS FROM (
SELECT KEYWORDS = CAST(USRN AS VARCHAR(15)) + ' ' +
RTRIM(STREET_DESCRIPTOR) + ' ' + RTRIM(NSG_LOCALITY.LOCALITY_NAME) + ' ' +
RTRIM(NSG_TOWN.TOWN_NAME) + ' ' + RTRIM(NSG_AUTHORITY.AUTHORITY_NAME)
) AS Q
WHERE Q.KEYWORDS LIKE '%whateverTheUserIsTyping%'
Because you can't use the column alias in the WHERE clause as you mentioned. Also instead of the KEYWORDS = '%whateverTheUserIsTyping%', you can use LIKE operator.

using CASE in SQL with update statement

I am trying to write a case statement something like this. Can someone help with the syntax
UPDATE A
CASE WHEN ATTDESC = 'ABC' THEN SET A.DESC = PG.VAL + ' - ' + LD.DESC + ' - ' + GH.PL3NAME
WHEN ATTDESC = 'DEF' THEN SET A.DESC = PG.VAL + ' - ' + LD.DESC + ' - ' + GH.PL3NAME
END
FROM ATTR A, PRODUCT PG, Global GH, Look LD
A CASE expression doesn't control flow; it returns a single value. So something like this:
...
SET [DESC]=CASE [ATTDESC]
WHEN 'ABC' THEN PG.VAL + ' - ' + LD.DESC + ' - ' + GH.PL3NAME
WHEN 'DEF' THEN PG.VAL + ' - ' + LD.DESC + ' - ' + GH.PL3NAME
ELSE [DESC]
END
FROM
...

using sql - Is not null in a select statement

I can't seem to figure out how to use the opposite of isnull or ifnull statements in sql. I need to say if a.Error1 is not null -- then print the ' - ' and the + CHAR(13)+CHAR(10). Basically There should be no dash or no new line break if the a.Error1 comes back null. So print the information if the field isn't null.
select a. ....
' - ' + a.Error1 + CHAR(13)+CHAR(10) +
' - ' + a.Error2 + CHAR(13)+CHAR(10) +
' - ' + a.Error3 + CHAR(13)+CHAR(10) +
' - ' + a.Error4 + CHAR(13)+CHAR(10) +
' - ' + a.Error5 + CHAR(13)+CHAR(10) +
' - ' + a.Error6 as 'error_message'
...
from table1 a
For example if for a given record error1, 2 and 5 returned output I would like the output to be as follows:
- Error1: There was a ...
- Error2: ....
- Error5: The data was ...
If no errors existed for that row it should simply be an empty/null field.
You can use CASE:
SELECT a. ....
(CASE WHEN a.Error1 IS NOT NULL
THEN ' - ' + a.Error1 + CHAR(13)+CHAR(10)
ELSE ''
END) +
(CASE WHEN a.Error2 IS NOT NULL
THEN ' - ' + a.Error2 + CHAR(13)+CHAR(10)
ELSE ''
END) +
(CASE WHEN a.Error3 IS NOT NULL
THEN ' - ' + a.Error3 + CHAR(13)+CHAR(10)
ELSE ''
END) +
...etc
Yes! i know i'm like 5 years too late but i too enountered this problem.
It's weird how it doesn't exist some kind of !ISNULL() but whatever.
Try this for a cleaner code:
select a. ....
IIF(a.Error1 IS NOT NULL, ' - ' + a.Error1 + CHAR(13)+CHAR(10) , '') as Error1,
IIF(a.Error1 IS NOT NULL, ' - ' + a.Error1 + CHAR(13)+CHAR(10) , '') as Error2
from table1 a
Learn more about IIF() function : SQL Server IIF Function
The COALESCE function does what you want here. The result of COALESCE is the first NOT NULL value it is passed. Below we use '', which is distinct from NULL so that the outer + is always applied to NOT NULL strings.
e.g.
select a. ....
COALESCE( ' - ' + a.Error1 + CHAR(13)+CHAR(10), '' ) +
COALESCE( ' - ' + a.Error2 + CHAR(13)+CHAR(10), '' ) +
COALESCE( ' - ' + a.Error3 + CHAR(13)+CHAR(10), '' ) +
COALESCE( ' - ' + a.Error4 + CHAR(13)+CHAR(10), '' ) +
COALESCE( ' - ' + a.Error5 + CHAR(13)+CHAR(10), '' ) +
COALESCE( ' - ' + a.Error6 , '' ) as 'error_message'
...
from table1 a
SELECT (CASE WHEN a.Error1 IS NOT NULL
THEN ' - ' + a.Error1 + CHAR(13)+CHAR(10) +
ELSE a.Error1
END) +
(CASE WHEN a.Error2 IS NOT NULL
THEN ' - ' + a.Error2 + CHAR(13)+CHAR(10) +
ELSE a.Error2
END) +
.....etc

Building dynamic self join statements in SQL

Declare #alias as varchar(10)
set #alias = 'fk2'
insert into #Queries(Query, ExecuteOrder)
select top 1 'delete ' + fk1.TableFrom + ' from ' + fk1.TableFrom
+ ' join ' + #alias.TableFrom + ' on ' + fk1.TableFrom+'.'+fk1.FK_Column + ' = ' + fk2.TableFrom + '.ID'
+ ' join ' + fk3.TableFrom + ' on ' + fk2.TableFrom+'.'+fk2.FK_Column + ' = ' + fk3.TableFrom + '.ID'
+ ' join ' + fk4.TableFrom + ' on ' + fk3.TableFrom+'.'+fk3.FK_Column + ' = ' + fk4.TableFrom + '.ID'
+ ' Where ' + fk4.TableFrom + '.' + fk4.FK_Column + ' = ' + #value
,#i
from #FK fk1
join #fk As #alias on #alias.TableFrom = fk1.TableTo
join #fk fk3 on fk3.TableFrom = fk2.TableTo
join #fk fk4 on fk4.TableFrom = fk3.TableTo
I am joining a table to itself to build a resulting query to then be executed from the temp table being inserted into. I am currently specifying the amount of joins but would like to build them dynamically based on another integer value being passed in. The amount of joins will correlate with this integer value. The only problem is I need a unique Alias for each join to then be used above to build the resulting query. Is it possible to use a dynamic Alias as to eliminate the need to hardcode the Alias for each join?

space in a select statement in dynamic query

I have a dynamic query like this :
SET #str_Query = 'SELECT SIM.Item_ID,
SIM.Item_Description,
SU.Short_Description AS Unit,
SIM.Std_Lead_Time,'+
'' ''+' AS Last_Purchase_Rate
FROM FKMS_Item_Master AS SIM
INNER JOIN FKMS_STP_Units SU
ON SIM.Item_Purchase_Unit=SU.Unit_Id' +
' WHERE ' + #str_Condition +
' AND SIM.Location_Id =' + CAST(#aint_Location_Id AS VARCHAR(10)) +
' AND SIM.Item_Deleted =0
AND SIM.Approved_On IS NOT NULL'
+' ORDER BY SIM.Item_Description'
I want to retrieve space as Last_Purchase_Rate
It is showing syntax error in the portion of '' ''+' AS Last_Purchase_Rate
when I execute this query.
If I print this dynamic query, query seems correct. It shows as AS Last_Purchase_Rate with space before AS. Please help.
I would write
...SIM.Std_Lead_Time, '' '' AS Last_Purchase_Rate...
instead of
...SIM.Std_Lead_Time,'+'' ''+' AS Last_Purchase_Rate...
Why not use NULL instead of space and then handle the result in your app?
I.e.,
SET #str_Query = 'SELECT SIM.Item_ID,
SIM.Item_Description,
SU.Short_Description AS Unit,
SIM.Std_Lead_Time,
NULL AS Last_Purchase_Rate, -- and so on.
You could also use CHAR(32):
SET #str_Query = 'SELECT SIM.Item_ID,
SIM.Item_Description,
SU.Short_Description AS Unit,
SIM.Std_Lead_Time,
CHAR(32) AS Last_Purchase_Rate, -- and so on.
You did not escape all quotes.
A working version of your statement would be
SET #str_Query = 'SELECT SIM.Item_ID,
SIM.Item_Description,
SU.Short_Description AS Unit,
SIM.Std_Lead_Time,'
+ ''' '''
+ ' AS Last_Purchase_Rate
FROM FKMS_Item_Master AS SIM
INNER JOIN FKMS_STP_Units SU
ON SIM.Item_Purchase_Unit=SU.Unit_Id' +
' WHERE ' + #str_Condition +
' AND SIM.Location_Id =' + CAST(#aint_Location_Id AS VARCHAR(10)) +
' AND SIM.Item_Deleted =0
AND SIM.Approved_On IS NOT NULL'
+' ORDER BY SIM.Item_Description'
but I find that with a little reformatting, the error is easier to spot
SET #str_Query =
'SELECT SIM.Item_ID '
+ ', SIM.Item_Description '
+ ', SU.Short_Description AS Unit '
+ ', SIM.Std_Lead_Time '
+ ', '' ''' + ' AS Last_Purchase_Rate '
+ 'FROM FKMS_Item_Master AS SIM '
+ ' INNER JOIN FKMS_STP_Units SU '
+ ' ON SIM.Item_Purchase_Unit=SU.Unit_Id '
+ ' WHERE ' + #str_Condition
+ ' AND SIM.Location_Id = ' + CAST(#aint_Location_Id AS VARCHAR(10))
+ ' AND SIM.Item_Deleted =0 '
+ ' AND SIM.Approved_On IS NOT NULL '
+ ' ORDER BY SIM.Item_Description '
Try using tsql function SPACE(1)