How to use variable in t-sql query - tsql

Today I get my database name like that :
set #databaseNameTXT = 'NewStat1DB';
And then I insert the data to the right table like that:
IF #databaseNameTXT = 'NewStat1DB'
BEGIN
INSERT INTO [NewStat1DB] (wStat_id) values(#wStat_id)
END
IF #databaseNameTXT = 'NewStat2DB'
BEGIN
INSERT INTO [NewStat2DB] (wStat_id) values(#wStat_id)
END
How can I use the variable inside the t-sql and run it, something like:
INSERT INTO [#databaseNameTXT] (wStat_id) values(#wStat_id)
Thanks

You need to use dynamic SQL for this, though you need to be careful of SQL Injection.
Database, schema, table and column names cannot be variables - the only way to do this is use dynamic SQL.
For example (this is vulnerable to SQL Injection):
sp_executesql 'INSERT INTO [' + #databaseNameTXT +
'] (wStat_id) values(' + #wStat_id + ');';
I suggest reading the linked article - it is a comprehensive treatment of the subject of dynamic SQL.

You can use Dynamic SQL for this:
declare #query nvarchar(max)
set #query = 'INSERT INTO ' + QUOTENAME(#databaseNameTXT) + '(wStat_id)
values('+#wStat_id+')'
exec(#query)

Related

How do convert below code from T-SQL into DB2 LUW?

How do I convert this code from T-SQL into DB2 LUW, it seems so easy with T-SQL but in DB2 can't find any solution. See code below:
DECLARE #sqlCommand varchar(1000)
DECLARE #columnList varchar(75)
DECLARE #city varchar(75)
SET #columnList = 'AddressID, AddressLine1, City'
SET #city = '''London'''
SET #sqlCommand = 'SELECT ' + #columnList + ' FROM Person.Address WHERE City = ' + #city
EXEC (#sqlCommand)
The problem is that you can’t ‘select to nowhere’ in a compound statement in DB2. Db2 CLP can return you the result set of a single sql statement, but it doesn’t try to do the same for select statements in a compound statement. If you want to print the result set from a select statement in a compound statement, you can, for example, declare a cursor, fetch it in a loop, and use dbms_output.put_line calls to print the values of variables.
Not Pretty but you can find an example of the bottom of this page:
Stored Procedures and Dynamic SQL Returning a Result set
Essentially you most:
1) create a dynamic SQL string
2) prepare the string into a statement
3) Link the statement to a cursor you're going to declare as WITH RETURN
Opening the cursor will be the last line in your procedure.

Is this vulnerable to SQL injection?

We are using a third party product which references a stored procedure in MSSQL. This stored proc looks something like this:
CREATE PROCEDURE [dbo].[example]
#a nvarchar(255)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #strSQL nvarchar(3000)
SET #strSQL = 'SELECT * FROM test WHERE x = ''1'''
IF IsNull(#a, '') <> ''
SET #strSQL = #strSQL + ' AND a = ''' + #a + ''''
EXEC(#strSQL)
END
This stored proc doesn't actually output its results to the website but I'm still sure that it is vulnerable to SQL injection. I can input t' + 'est and get the same result as I would from inputing test.
We obviously need to get them to change this but I need to demonstrate that it is an issue first. How can I do something like insert a row in to a table by passing SQL in as #a? If I do
'; INSERT INTO blah VALUES('test')
Then I get:
Incorrect syntax near ';'.
yes, it's vulnerable, but by chance you've injected the wrong text, producing a syntax error:
SELECT * FROM test WHERE x = "1" AND a =; INSERT INTO blah VALUES('test')
^--your syntax error
If your injection text had been:
a; INSERT blah blah blah
^---
then you'd have ended up with two valid queries and test in your blah table.
Yes, you can set your # to have an secape character and thus create mutiple Execs ulimately leading to execcmd format C: or other - google SQL injection attacks
However:
Create proc db.eg #a nvarchar(255)
AS
BEGIN
Update Mytable SET Mycol = #a WHERE Condition etc..
END
IS not open to SQL injection as the string goes directly to the table column, it is nt exec'd

T-SQL: issue with string concat

I have a set of audio files with names GreenLine1.mp3, GreenLine2.mp3 e.t.c. I'm going to write them into a table as BLOB (I use MS SQL Server'08), here's my sql request:
DECLARE #aud AS VARBINARY(MAX)
DECLARE #num AS INT
-- Load the audio data
SET #num=1
WHILE (#num<38)
BEGIN;
SELECT #aud = CAST(bulkcolumn AS VARBINARY(MAX))
FROM OPENROWSET(
BULK
'C:\Users\Ilya\folder\GreenLine' + CAST(#num AS VARCHAR) + '.mp3',
SINGLE_BLOB ) AS x
-- Insert the data to the table
INSERT INTO Mb2.dbo.Audios (Id, [Content])
SELECT NEWID(), #aud
SET #num = #num + 1
END;
I have an error: Incorrect syntax near '+', expecting ',' or ')'.
If I try to write
'C:\Users\Ilya\folder\GreenLine' +
CAST(#num AS VARCHAR) + '.mp3'
into a variable and put it after BULK, I get Incorrect syntax near #variable, expected STRING, or TEXT_LEX
You can't parametrise or concatenate the parameters of OPENROWSET. It is constant values only.
You'll have to use dynamic SQL and a temp table, or consider using SSIS for example
This article pointed me in the right direction when I had the same issue with OPENQUERY:
https://web.archive.org/web/20120724073530/http://consultingblogs.emc.com/jamespipe/archive/2007/06/28/SQL-Server-2005_3A00_-Passing-variables-into-an-OPENQUERY-argument.aspx
Basically, you can wrap the entire statement in a variable (nvarchar), including the openrowset, and run exec sp_executesql #sql. It gets a little ugly to read around the 's though, because you'll have to escape them with ''.

TSQL varchar string manipulation

I have a variable which contains the following string: AL,CA,TN,VA,NY
I have no control over what I get in that variable (comes from reporting services)
I need to make it look like this: 'AL','CA','TN','VA','NY'
How do I do this?
declare #x varchar(50) = 'AL,CA,TN,VA,NY'
select '''' + REPLACE(#x, ',', ''',''') + ''''
I ended up doing something very similar that I thought I'd post. (I'll give credit to Mitch however)
This takes care of the middle:
SET #StateList = REPLACE(#StateList, ',', ''',''')
Then quote the edges:
SET #WhereClause1 = #WhereClause1 + 'AND customerState IN (''' + #StateList + ''') '
For a more generic answer, when you don't know what your output will look like exactly, use regular expressions.
This would let you you match on something like [A-Z]{2} and replace it with '$&'.
A commenter suggested this is overkill for this task - agreed, if you can guarantee you will always get a string like that. However, other people find these question pages later with similar, but not exact, problems, so other options are helpful to have.
Don't bother with dynamic sql.
You need to convert the string to a table
so
A,B,C,D
becomes
Value
A
B
C
D
using a function like
http://www.sqlusa.com/bestpractices/training/scripts/splitcommadelimited/
then you can use CROSS APPLY (which is like joining to a table, but a table created by a function) or you can just put it in a table variable and join to that
I want to know y does the following script run in SQL and not in T-SQL
DECLARE #tblName varchar(30)
SET #tblName = CONVERT(VARCHAR(20),GETDATE(),112) + 'Table'
DECLARE #sql nvarchar(4000)
SELECT #sql =
'CREATE TABLE "' + #tblName + '"
(
ID VARCHAR(15),
Name VARCHAR(15)
)'
EXEC(#sql)
go
it gives you the error
Msg 170, Sev 15: Line 1: Incorrect syntax near '20090714Table'. [SQLSTATE 42000]

SQL server name of columns as variables

I have the following statement in a stored procedure. I am passing the name of the column as parameter and also the value to be checked in another variable. Is it possible to accomplish this in SQL server. Please let me know.
SELECT CaseId FROM app_Case
where #SearchCat=#keywords
ORDER BY CreatedDate DESC
I think the only way to do this would be to generate a dynamic SQL statement. The other option would be to take all column values as parameters, default them to null, and check for that.
ie
WHERE (cola = #cola OR #cola IS NULL) AND (colb = #colb OR #colb IS NULL) etc.
You need to create a string of SQL inside the SP and execute it.
Declare #SQL As VARCHAR(8000)
SET #SQL = 'SELECT CaseId FROM app_Case where ' +
#SearchCat + ' = '' + #keywords +
'' ORDER BY CreatedDate DESC'
EXEC(#SQL)
You can build a dynamic query Essentially you build a string and then execute it. (Watch out for SQL injection attacks).
Another approach would be to use a case statement which if you don't have a lot of options might be worth trying:
select CaseId from app_Case
where case when #searchCat='field1'
then field1
else #searchVal
end = #searchVal and
case when #searchCat='field2'
then field2
else #searchVal
end = #searchVal
Another approach is do the same thing using or clauses:
select CaseId from app_Case
where (#searchCat='Field1' and Field1=#searchVal) OR
(#serachCat='Field2' and Field2=#searchVal)