Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to concatenate variables into SQL strings

I need to concatenate a variable table name into my SQL query such as the following...

ALTER FUNCTION fn_myfunction(@KeyValue text)
BEGIN
     INSERT INTO @tmpTbl1
     SELECT @KeyValue AS fld1
     FROM tbl + @KeyValue + KeyValue.fld1

I also attempted the following but it told me I had to declare the table variable?

ALTER FUNCTION fn_myfunction(@KeyValue text, @KeyTable text)
     FROM @KeyTable.fld1
like image 534
codingManiac Avatar asked Jul 19 '13 19:07

codingManiac


People also ask

How do you concatenate a variable in a string in SQL?

Concatenates two strings and sets the string to the result of the operation. For example, if a variable @x equals 'Adventure', then @x += 'Works' takes the original value of @x, adds 'Works' to the string, and sets @x to that new value 'AdventureWorks'.

How do you concatenate strings and variables?

Concatenation is the process of appending one string to the end of another string. You concatenate strings by using the + operator. For string literals and string constants, concatenation occurs at compile time; no run-time concatenation occurs. For string variables, concatenation occurs only at run time.

How do I concatenate data types in SQL?

Solution. TSQL provides 2 ways to concatenate data, the + sign and the new CONCAT() function. This tip will cover the differences in the two, so you can achieve the expected behavior in your code. The way most us are used to concatenating data together is using the + sign.

How do I concatenate two column values in SQL?

MySQL CONCAT() Function The CONCAT() function adds two or more expressions together. Note: Also look at the CONCAT_WS() function.


1 Answers

You can accomplish this (if I understand what you are trying to do) using dynamic SQL.

The trick is that you need to create a string containing the SQL statement. That's because the tablename has to specified in the actual SQL text, when you execute the statement. The table references and column references can't be supplied as parameters, those have to appear in the SQL text.

So you can use something like this approach:

SET @stmt = 'INSERT INTO @tmpTbl1 SELECT ' + @KeyValue 
    + ' AS fld1 FROM tbl' + @KeyValue

EXEC (@stmt)

First, we create a SQL statement as a string. Given a @KeyValue of 'Foo', that would create a string containing:

'INSERT INTO @tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'

At this point, it's just a string. But we can execute the contents of the string, as a dynamic SQL statement, using EXECUTE (or EXEC for short).

The old-school sp_executesql procedure is an alternative to EXEC, another way to execute dymamic SQL, which also allows you to pass parameters, rather than specifying all values as literals in the text of the statement.


FOLLOWUP

EBarr points out (correctly and importantly) that this approach is susceptible to SQL Injection.

Consider what would happen if @KeyValue contained the string:

'1 AS foo; DROP TABLE students; -- '

The string we would produce as a SQL statement would be:

'INSERT INTO @tmpTbl1 SELECT 1 AS foo; DROP TABLE students; -- AS fld1 ...'

When we EXECUTE that string as a SQL statement:

INSERT INTO @tmpTbl1 SELECT 1 AS foo;
DROP TABLE students;
-- AS fld1 FROM tbl1 AS foo; DROP ...

And it's not just a DROP TABLE that could be injected. Any SQL could be injected, and it might be much more subtle and even more nefarious. (The first attacks can be attempts to retreive information about tables and columns, followed by attempts to retrieve data (email addresses, account numbers, etc.)

One way to address this vulnerability is to validate the contents of @KeyValue, say it should contain only alphabetic and numeric characters (e.g. check for any characters not in those ranges using LIKE '%[^A-Za-z0-9]%'. If an illegal character is found, then reject the value, and exit without executing any SQL.

like image 51
spencer7593 Avatar answered Oct 07 '22 17:10

spencer7593