T-SQL creating a dynamic where statement? - sql

I know this is not possible, but is there something that would work? Basically I want the where statement to be dynamic, allowing me to pass it any string, which it will be able to search upon.
Declare #search varchar(80)
set #search = 'RegionID'
Select * from TBL_TripDetails
Where #search = '1'
Thanks for your answers. After reading a few documents, I have decided to use multiple select statements instead of using dynamic sql. thanks!

declare #sql nvarchar(max);
set #sql = N'select * from table where ' + quotename(#search) + N'=''1''';
exec sp_executesql #sql;
See The Curse and Blessings of Dynamic SQL

It is indeed possible, altough is often frowned upon.
Have a look at sp_executesql

Declare #search varchar(80)
set #search = 'RegionID'
declare #query varchar(max)
set #query = "Select * from TBL_TripDetails Where " + #search + " = '1'"
exec #query

DECLARE #search VARCHAR(80)
DECLARE #SQL VARCHAR(8000)
SET #search = 'RegionID'
SET #SQL = 'SELECT * FROM TBL_TripDetails WHERE ' + #search + ' = 1'
EXEC #SQL
Be careful though. Concatenating SQL can allow SQL injection attacks.

I'm a bit confused with your question "pass it any string, which it will be able to search upon". In your example your passing in a field which is being compared against a hard coded value of 1, this doesn't really match your description.
If this is truly what you wanted, then you'll need to use Dynamic SQL. If you just want to be able to support optional search criteria/parameters (e.g. If RegionID has a value set then apply criteria, else ignore criteria), then use the example below.
DECLARE #RegionID AS VARCHAR(1);
SELECT *
FROM TABLE
WHERE (#RegionID Is Null OR #RegionID = '' OR RegionID = #RegionID);
Now, if #RegionID is blank or NULL it won't be used in the criteria.

Related

Setting SQL Variable via Dynamic SQL

I know I am overthinking this, but I've been banging against this for too long so I'm reaching out for help.
This is the statement I'm trying to run: SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]
BUT, the table name is a variable #reportTable
This doesn't work:
SET #sql = 'SELECT #cntMax = MAX(id) FROM #reportTable'
EXEC sp_executesql #sql
I even tried having the actual table name in the SET #sql and that doesn't work either.
I didn't think it would be this difficult, please tell me I'm missing something easy/obvious.
Here's the full bit of code for those who want it:
DECLARE
#inTable nvarchar(255) = 'Raw_Item',
#reportTable nvarchar(255),
#fieldName nvarchar(255),
#cnt int,
#cntMax int,
#sql nvarchar(max)
SET #reportTable = #inTable + '-FieldReport'
SET #cnt = 1
SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]
PRINT #cntMax
SET #cntMax = 0
SET #sql = 'SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]'
EXEC sp_executesql #sql
PRINT #cntMax
SQL Server 12.0.2008.8 (on Azure)
You need to use an output parameter, otherwise SQL Server has no idea how to connect #cntMax in the dynamic SQL to #cntMax not in the dynamic SQL, since they are different scopes. And to protect yourself from SQL injection (some tips here and here), always check that your object exists, and use QUOTENAME() as opposed to manually adding square brackets (and you should always use QUOTENAME() when building object names from user input or variables, even when they don't have bad characters like dashes):
DECLARE #sql nvarchar(max),
#inTable nvarchar(255) = N'Raw_Item',
#reportTable nvarchar(255);
SET #reportTable = N'dbo.' + QUOTENAME(#inTable + '-FieldReport');
IF OBJECT_ID(#reportTable) IS NOT NULL
BEGIN
SET #sql = N'SELECT #cntMax = MAX(id) FROM ' + #reportTable + N';';
EXEC sys.sp_executesql #sql,
N'#cntMax int output',
#cntMax = #cntMax OUTPUT;
PRINT #cntMax;
END
ELSE
BEGIN
PRINT 'Nice try, h#xx0rs!';
END
Always use schema reference (dbo), always use statement terminators, and please try to avoid naming things with invalid identifier characters like dash (-). And one additional tip: always use N prefix on N'nvarchar string literals'.

Is it possible to set a part of a select statement in a variable

I have a query of which the select-part is really long. I'd like to split this in several pieces, especially because some parts are in there twice or even more often.
What I'd like is something like the following:
Declare #SQLPart as varchar(1000)
Set #SQLPart = 'Field1,
case ... as Field2,'
Select ..., #SQLPart, ... From .....
Unfortunately this results error messages. I tried something like EXEC(#SQLPart) as well but of course this also didn't work. How would I solve this?
Yes, dynamic sql and sp_executesql:
CREATE TABLE ##Temp (Field1 int, Field2 int)
Declare #SQLPart nvarchar(1000)
Set #SQLPart = N'Field1, Field2 '
DECLARE #SQL nvarchar(1000) = N'SELECT ' + #SQLPart + 'FROM ##Temp'
PRINT #SQL
EXEC sp_executesql #SQL
DROP TABLE ##Temp
Your SQL code must be nvarchar type.
Alse sp_executesql is better than EXECUTE function, when you have many similar queries, sp_executesql caches executaion plans, and it can be better in perfomance.
You can use dynamic sql here,and use a EXECUTE keyword to execute this dynamic query
Declare #SQLPart as varchar(1000)
Set #SQLPart = 'Field1,
case ... as Field2,'
EXECUTE ('SELECT ....,'+#SQLPart+',... FROM ...')
SQL Server does not support Macro-Substitution, so you would have to use Dynamic SQL.
Declare #SQL varchar(max) ='Select ... ' + #SQLPart + '... from ...'
Exec(#SQL)

SQL Store a value from an EXECUTE Command into a variable

I'm attempting to store a value into a variable from a EXECUTE command. I know I'm suppose to use sp_executesql command, but all examples online are only making more confused. So here is what I'm trying to do.
I have a stored procedure that accepts two parameters (a table name, a room #). To have a dynamic table name, I use dynamic SQL style while using strings. I'm attempting to store a phone number that is either from multiple tables. I got this working so far.
DECLARE #Location varchar(MAX);
DECLARE #Room varchar(10);
DECLARE #Number char(8);
DECLARE #SQLString varchar(MAX);
SET #Location = N'CMPhone.dbo.GardenCottage';
SET #Room = N'202';
SET #SQLString ='SET #Number = (SELECT PhoneNumber FROM ' + #Location + ' WHERE Room = ''' + #Room + ''');';
PRINT(#SQLString);
OUTPUT
SET #Number = (SELECT PhoneNumber FROM CMPhone.dbo.GardenCottage WHERE Room = '202');
SET #Number = (SELECT PhoneNumber FROM CMPhone.dbo.GardenCottage WHERE Room = '202');
PRINT(#Number);
OUTPUT
123-4567
Which is the correct number. Now, here is where the problem comes in. I need to do another query using dynamic SQL so I can use multiple tables again. So in my stored procedure, I need to store my EXEC(#SQLString) into a variable (#Number) so I can use that value, and that's where I'm having problems. I can't get sp_executesql to store the value into #Number. The other query will look something like this
SET #SQLString = ' UPDATE PhoneNumbers SET Active = ''1'' WHERE
PhoneNumber = ''' + #Number + ''';';
EXEC(#SQLString);
If this is confusing in anyway, or you have questions, please ask. Any help is very much appreciated. Thanks
Update #1:
I have this new string now
#SQLString = 'SELECT PhoneNumber FROM ' + #Location ' + ' WHERE Room = ''' + #Room + ''';';
EXECUTE SP_EXECUTESQL #SQLString
gets the correct number, but I don't know how to set up a OUTPUT parameter.
I'm attempting to follow this example from Microsoft
DECLARE #SQLString NVARCHAR(500)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #IntVariable INT
DECLARE #Lastlname varchar(30)
SET #SQLString = N'SELECT #LastlnameOUT = max(lname)
FROM pubs.dbo.employee WHERE job_lvl = #level'
SET #ParmDefinition = N'#level tinyint,
#LastlnameOUT varchar(30) OUTPUT'
SET #IntVariable = 35
EXECUTE sp_executesql
#SQLString,
#ParmDefinition,
#level = #IntVariable,
#LastlnameOUT=#Lastlname OUTPUT
SELECT #Lastlname
But I don't see how their declaring the lastlNameOUT variables.
use output variable in your EXECUTE sp_executesql like this:
EXECUTE sp_executesql #SQLString, N'#Number char(8) out',#Number out then you will get #Number value from inside dynamc sql, then you can use that value in other part of the query. hope this helps

Get error in string query

I'm a beginner to SQL Server
I wrote this query:
DECLARE #sql nvarchar(1000) = 'UPDATE Work
SET [Name] = Programmer, [ImageAddress] = pic.jpg
WHERE Id = 2'
SELECT #sql
EXEC Sp_executesql #sql
but I get this error
Invalid column name 'Programmer'.
Why do I get this error?
Thank you for your help
You are dealing with SQL in strings. Quoting the strings becomes a challenge. You need for Programmer to be in single quotes when the query is executed. To get this, you need double single quotes in the string:
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = ''Programmer'', [ImageAddress] = ''pic.jpg'' WHERE Id=2'
select #sql
EXEC Sp_executesql #sql;
Because you are wise enough to use sp_executesql, you should learn about parameters. You can write the query as:
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = #Programmer, [ImageAddress] = #imageaddress WHERE Id=2'
select #sql
EXEC Sp_executesql #sql, N'#programmer nvarchar(255), #imageaddress nvarchar(255)',
#programmer = N'Programmer', #imageaddress = N'pic.jpg';
This has several advantages besides the quoting. It is safer in terms of SQL injection and it allows SQL Server to cache the execution plans if the query is called more than once.
try this:
You need to use '' (Double Quotes for string) Inside Dynamic SQL
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = ''Programmer'',[ImageAddress] =''pic.jpg'' WHERE Id=2'
select #sql
EXEC Sp_executesql #sql

Specifying Column Name As A Parameter in SELECT statement?

I need to do something like this, but it always fails with 'Error converting data type varchar to int':
DECLARE #intParam INT
DECLARE #ColName VARCHAR(64)
SET #ColName='intcolumn'
SET #intParam = SELECT #ColName FROM myTable
How do I accomplish something like this? I can see the problem is that the SELECT statement simply returns the column name as a string, but I am not sure how to fix that. I am using SQL Server 2008R2.
You need to use dynamic sql:
build your dynamic SQL query (take a look at #SQL variable in sample below)
use output parameter to get value back from dynamic sql (take a look at #intParam and #intParam_out in sample below)
execute dynamic sql using sp_executesql
DECLARE #intParam INT
DECLARE #ColName VARCHAR(64)
SET #ColName='intcolumn'
DECLARE #SQL NVARCHAR(1000)
SET #SQL = 'SELECT #intParam_out = ' + #ColName + ' FROM myTable'
exec sp_executesql #SQL, N'#intParam_out int OUTPUT', #intParam_out = #intParam OUTPUT
Use Cast:
SET #intParam = SELECT cast(#ColName as int) FROM myTable