A table name as a variable

498,716

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)
Share:
498,716
SoftwareGeek
Author by

SoftwareGeek

Software Engineer & .NET Developer/Architect. I am passionate about application development with an eye towards quality & usability.

Updated on January 20, 2021

Comments

  • SoftwareGeek
    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
    Davit Bidzhoyan about 9 years
    QUOTENAME is important for security. Thanks.
  • Suncatcher
    Suncatcher over 6 years
    But how to return value from such query? E.g. COUNT(*) ?
  • Downhillski
    Downhillski about 6 years
    this example is very useful.
  • ColinMac
    ColinMac over 4 years
    This is the best answer.
  • B H
    B H over 4 years
    This is the best answer because it's the most directly applicable to the OP's existing code.
  • double-beep
    double-beep about 4 years
    Welcome 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
    can.do almost 4 years
    I 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
    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
    HABO over 3 years
    The 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 like From.
  • Adir D
    Adir D about 2 years
    On its own, EXEC('SELECT * FROM ' + @tablename) is a really bad idea because it is begging for SQL injection.