表名作为变量

Sof*_*eek 153 sql t-sql sql-server variable-names tablename

我正在尝试执行此查询:

declare @tablename varchar(50)
set @tablename = 'test'
select * from @tablename
Run Code Online (Sandbox Code Playgroud)

这会产生以下错误:

Msg 1087,Level 16,State 1,Line 5

必须声明表变量"@tablename".

什么是动态填充表名的正确方法?

mdm*_*dma 116

如果查询是静态的,则表名和列名必须是静态的.对于动态表或列名,您应该动态生成完整的SQL,并使用sp_executesql来执行它.

这里有更多细节:动态SQL的诅咒和祝福

  • 将对象名称组装成动态 SQL 语句的最佳实践是使用 [`QuoteName()`](https://docs.microsoft.com/en-us/sql/t-sql/functions/quotename-transact-sql)以避免奇怪名称的问题,例如带有空格的“New Table”或保留字(如“From”)。 (2认同)

小智 92

将您的上一个陈述更改为:

EXEC('SELECT * FROM ' + @tablename)
Run Code Online (Sandbox Code Playgroud)

这就是我在存储过程中的方式.第一个块将声明变量,并根据当前年份和月份名称设置表名称,在本例中为TEST_2012OCTOBER.然后我检查它是否已存在于DB中,如果存在则删除.然后,下一个块将使用SELECT INTO语句创建表,并使用带参数的另一个表中的记录填充该表.

--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''')
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的答案。 (2认同)
  • 就其本身而言,“EXEC('SELECT * FROM ' + @tablename)”是一个非常糟糕的主意,因为它正在乞求 SQL 注入。 (2认同)

dcp*_*dcp 37

您不能为变量使用表名,而是必须这样做:

DECLARE @sqlCommand varchar(1000)
SET @sqlCommand = 'SELECT * from yourtable'
EXEC (@sqlCommand)
Run Code Online (Sandbox Code Playgroud)


Atu*_*ary 35

回答迟到但应该帮助其他人:

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
Run Code Online (Sandbox Code Playgroud)

  • QUOTENAME对安全很重要.谢谢. (13认同)
  • 但是如何从此类查询返回值?例如`COUNT(*)`吗? (2认同)

Pau*_* pk 14

你需要动态生成sql:

declare @tablename varchar(50) 

set @tablename = 'test' 

declare @sql varchar(500)

set @sql = 'select * from ' + @tablename 

exec (@sql)
Run Code Online (Sandbox Code Playgroud)


小智 6

使用sp_executesql执行任何SQL,如

DECLARE @tbl    sysname,
        @sql    nvarchar(4000),
        @params nvarchar(4000),
        @count  int

DECLARE tblcur CURSOR STATIC LOCAL FOR
   SELECT object_name(id) FROM syscolumns WHERE name = 'LastUpdated'
   ORDER  BY 1
OPEN tblcur

WHILE 1 = 1
BEGIN
   FETCH tblcur INTO @tbl
   IF @@fetch_status <> 0
      BREAK

   SELECT @sql =
   N' SELECT @cnt = COUNT(*) FROM dbo.' + quotename(@tbl) +
   N' WHERE LastUpdated BETWEEN @fromdate AND ' +
   N'                           coalesce(@todate, ''99991231'')'
   SELECT @params = N'@fromdate datetime, ' +
                    N'@todate   datetime = NULL, ' +
                    N'@cnt      int      OUTPUT'
   EXEC sp_executesql @sql, @params, '20060101', @cnt = @count OUTPUT

   PRINT @tbl + ': ' + convert(varchar(10), @count) + ' modified rows.'
END

DEALLOCATE tblcur
Run Code Online (Sandbox Code Playgroud)