Is there a way to do something like this? People is the name of the table.
declare @placeholder varchar(20) = 'People'
select * from @placeholder
Or something like this where the table name is People_Backup.
declare @placeholder varchar(20) = '_Backup'
select * from People@placeholder
And is there a way to add in dynamic sql the value of a variable?
something like this:
declare @placeholder nvarchar(20) = 'people'
declare @name nvarchar(30) = 'antony'
declare @query nvarchar(1000) = 'select * from ' + @placeholder + ' where
first_name=' + @name
exec sp_executesql @query
I mean: without do this
exec sp_executesql @query, N'@name varchar(30)', @name
Thank you for the answers.
I mean: without do this exec sp_executesql @query, N'@name varchar(30)', @name
Yes, you can do that as
--Use MAX instead of 1000
DECLARE @SQL nvarchar(MAX) = N'SELECT * FROM ' + @placeholder + ' WHERE first_name = '''+@name +'''';
EXECUTE sp_executesql @SQL;
Not without dynamic SQL.
Parameters in SQL are placeholders for data, and can't be used as placeholders for anything else (which includes commands such as select
, update
etc' and identifiers such as database name, schema name, table name, column name etc').
The only way to parameterize table names is to use dynamic SQL - meaning you must build a string containing the SQL you want to execute, and then execute it.
Beware - dynamic SQL might be an open door for SQL injection attacks - so you must do it wisely - here are some ground rules:
Always white-list your identifiers (using system tables or views such as sys.Tables
or Information_schema.Columns
)
Always use sysname
as the datatype for identifiers.
The sysname
data type is used for table columns, variables, and stored procedure parameters that store object names. The exact definition of sysname is related to the rules for identifiers. Therefore, it can vary between instances of SQL Server.
Never pass SQL commands or clauses in parameters - set @placeholder = 'select a, b, c'
or set @placeholder = 'where x = y'
is a security hazard!
Always use parameters for data. Never concatenate parameters into your sql string: set @sql = 'select * from table where x = '+ @x
is a security hazard. Always create your dynamic SQL to use parameters as parameters: set @sql = 'select * from table where x = @x'
Always use sp_executeSql
to execute your dynamic SQL statement, not EXEC(@SQL)
.
For more information, read Kimberly Tripp's EXEC and sp_executesql – how are they different?
Always wrap identifiers with QUOTENAME()
to ensure correct query even when identifiers include chars like white-spaces
To recap - a safe version of what you are asking for (with an additional dynamic where clause to illustrate the other points) is something like this:
@DECLARE @TableName sysname = 'People',
@ColumnName sysname = 'FirstName'
@Search varchar(10) = 'Zohar';
IF EXISTS(
SELECT 1
FROM Information_Schema.Columns
WHERE TABLE_NAME = @TableName
AND COLUMN_NAME = @ColumnName
)
BEGIN
DECLARE @Sql nvarchar(4000) =
'SELECT * FROM +' QUOTENAME(@TableName) +' WHERE '+ QUOTENAME(@ColumnName) +' LIKE ''%''+ @Search +''%'';'
EXEC sp_executesql @Sql, N'@Search varchar(10)', @Search
END
-- you might want to raise an error if not
To answer your question after edited directly:
I mean: without do this exec sp_executesql @query, N'@name varchar(30)', @name
Yes, you can do it without using sp_executeSql
, but it's dangerous - it will enable an attacker to use something like '';DROP TABLE People;--
as the value of @name
, so that when you execute the sql, your People
table will be dropped.
To do that, you will need to wrap the @name
with '
-
declare @placeholder nvarchar(20) = 'people'
declare @name nvarchar(30) = 'antony'
declare @query nvarchar(1000) = 'select * from ' + QUOTENAME(@placeholder) + ' where
first_name=''' + @name +''''
exec(@query)