A table name as a variable
Solution 1
For static queries, like the one in your question, table names and column names need to be static.
For dynamic queries, you should generate the full SQL dynamically, and use sp_executesql to execute it.
Here is an example of a script used to compare data between the same tables of different databases:
Static query:
SELECT * FROM [DB_ONE].[dbo].[ACTY]
EXCEPT
SELECT * FROM [DB_TWO].[dbo].[ACTY]
Since I want to easily change the name of table
and schema
, I have created this dynamic query:
declare @schema sysname;
declare @table sysname;
declare @query nvarchar(max);
set @schema = 'dbo'
set @table = 'ACTY'
set @query = '
SELECT * FROM [DB_ONE].' + QUOTENAME(@schema) + '.' + QUOTENAME(@table) + '
EXCEPT
SELECT * FROM [DB_TWO].' + QUOTENAME(@schema) + '.' + QUOTENAME(@table);
EXEC sp_executesql @query
Since dynamic queries have many details that need to be considered and they are hard to maintain, I recommend that you read: The curse and blessings of dynamic SQL
Solution 2
Change your last statement to this:
EXEC('SELECT * FROM ' + @tablename)
This is how I do mine in a stored procedure. The first block will declare the variable, and set the table name based on the current year and month name, in this case TEST_2012OCTOBER. I then check if it exists in the database already, and remove if it does. Then the next block will use a SELECT INTO statement to create the table and populate it with records from another table with parameters.
--DECLARE TABLE NAME VARIABLE DYNAMICALLY
DECLARE @table_name varchar(max)
SET @table_name =
(SELECT 'TEST_'
+ DATENAME(YEAR,GETDATE())
+ UPPER(DATENAME(MONTH,GETDATE())) )
--DROP THE TABLE IF IT ALREADY EXISTS
IF EXISTS(SELECT name
FROM sysobjects
WHERE name = @table_name AND xtype = 'U')
BEGIN
EXEC('drop table ' + @table_name)
END
--CREATES TABLE FROM DYNAMIC VARIABLE AND INSERTS ROWS FROM ANOTHER TABLE
EXEC('SELECT * INTO ' + @table_name + ' FROM dbo.MASTER WHERE STATUS_CD = ''A''')
Solution 3
Use:
CREATE PROCEDURE [dbo].[GetByName]
@TableName NVARCHAR(100)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @sSQL nvarchar(500);
SELECT @sSQL = N'SELECT * FROM' + QUOTENAME(@TableName);
EXEC sp_executesql @sSQL
END
Solution 4
You can't use a table name for a variable. You'd have to do this instead:
DECLARE @sqlCommand varchar(1000)
SET @sqlCommand = 'SELECT * from yourtable'
EXEC (@sqlCommand)
Solution 5
You'll need to generate the SQL content dynamically:
declare @tablename varchar(50)
set @tablename = 'test'
declare @sql varchar(500)
set @sql = 'select * from ' + @tablename
exec (@sql)
SoftwareGeek
Software Engineer & .NET Developer/Architect. I am passionate about application development with an eye towards quality & usability.
Updated on January 20, 2021Comments
-
SoftwareGeek over 3 years
I am trying to execute this query:
declare @tablename varchar(50) set @tablename = 'test' select * from @tablename
This produces the following error:
Msg 1087, Level 16, State 1, Line 5
Must declare the table variable "@tablename".
What's the right way to have the table name populated dynamically?
-
Davit Bidzhoyan about 9 yearsQUOTENAME is important for security. Thanks.
-
Suncatcher over 6 yearsBut how to return value from such query? E.g.
COUNT(*)
? -
Downhillski about 6 yearsthis example is very useful.
-
ColinMac over 4 yearsThis is the best answer.
-
B H over 4 yearsThis is the best answer because it's the most directly applicable to the OP's existing code.
-
double-beep about 4 yearsWelcome to Stack Overflow! While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply. From Review
-
can.do almost 4 yearsI like the simplicity of this answer, and it has the same 3 lines the question addresses. I don't think explanation is needed. Thank you.
-
RowanPD over 3 years@Suncatcher You could have an output parameter or return it as a result set. To show how to read it into a variable and without leading 'at' symbols on variables due to comment posting restrictions: declare nCount int Exec('select nCount = count(*) from ' + sTableName)
-
HABO over 3 yearsThe best practice when assembling object names into dynamic SQL statements is to use
QuoteName()
to avoid problems with odd names, e.g.New Table
with a space or reserved words likeFrom
. -
Adir D about 2 yearsOn its own,
EXEC('SELECT * FROM ' + @tablename)
is a really bad idea because it is begging for SQL injection.