表名作为变量

Posted

技术标签:

【中文标题】表名作为变量【英文标题】:A table name as a variable 【发布时间】:2011-02-19 18:38:27 【问题描述】:

我正在尝试执行此查询:

declare @tablename varchar(50)
set @tablename = 'test'
select * from @tablename

这会产生以下错误:

消息 1087,第 16 级,状态 1,第 5 行

必须声明表变量“@tablename”。

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

【问题讨论】:

【参考方案1】:

对于静态查询,例如您问题中的查询,表名和列名需要是静态的。

对于动态查询,应动态生成完整的 SQL,并使用 sp_executesql 执行。

这是一个用于比较不同数据库的相同表之间数据的脚本示例:

静态查询:

SELECT * FROM [DB_ONE].[dbo].[ACTY]
EXCEPT
SELECT * FROM [DB_TWO].[dbo].[ACTY]

由于我想轻松更改tableschema 的名称,我创建了这个动态查询:

declare @schema varchar(50)
declare @table varchar(50)
declare @query nvarchar(500)

set @schema = 'dbo'
set @table = 'ACTY'

set @query = 'SELECT * FROM [DB_ONE].[' + @schema + '].[' + @table + '] EXCEPT SELECT * FROM [DB_TWO].[' + @schema + '].[' + @table + ']'

EXEC sp_executesql @query

由于动态查询有很多细节需要考虑,而且很难维护,我建议你阅读:The curse and blessings of dynamic SQL

【讨论】:

将对象名称组装成动态 SQL 语句时的最佳做法是使用 QuoteName() 以避免出现奇怪名称的问题,例如New Table 带有空格或保留字,例如 From【参考方案2】:

将您的最后一条语句更改为:

EXEC('SELECT * FROM ' + @tablename)

这就是我在存储过程中的操作方式。第一个块将声明变量,并根据当前年份和月份名称设置表名,在本例中为 TEST_2012OCTOBER。然后我检查它是否已经存在于数据库中,如果存在则删除。然后下一个块将使用 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''')

【讨论】:

这是最好的答案。 这是最好的答案,因为它最直接适用于 OP 的现有代码。【参考方案3】:

用途:

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

【讨论】:

QUOTENAME 对安全很重要。谢谢。 但是如何从这样的查询中返回值呢?例如。 COUNT(*)? @Suncatcher 您可以有一个输出参数或将其作为结果集返回。为了展示如何将它读入变量并且由于评论发布限制而在变量上不带前导“at”符号:declar nCount int Exec('select nCount = count(*) from ' + sTableName)【参考方案4】:

您不能为变量使用表名。你必须这样做:

DECLARE @sqlCommand varchar(1000)
SET @sqlCommand = 'SELECT * from yourtable'
EXEC (@sqlCommand)

【讨论】:

【参考方案5】:

您需要动态生成 SQL 内容:

declare @tablename varchar(50)

set @tablename = 'test'

declare @sql varchar(500)

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

exec (@sql)

【讨论】:

【参考方案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

【讨论】:

这个例子很有用。【参考方案7】:

你需要使用SQL Server动态SQL:

DECLARE @table     NVARCHAR(128),
        @sql       NVARCHAR(MAX);

SET @table = N'tableName';

SET @sql = N'SELECT * FROM ' + @table;

使用 EXEC 执行任何 SQL:

EXEC (@sql)

使用 EXEC sp_executesql 执行任何 SQL:

EXEC sp_executesql @sql;

使用 EXECUTE sp_executesql 执行任何 SQL:

EXECUTE sp_executesql @sql

【讨论】:

【参考方案8】:
Declare  @tablename varchar(50) 
set @tablename = 'Your table Name' 
EXEC('select * from ' + @tablename)

【讨论】:

欢迎来到 Stack Overflow!虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的答案添加解释并说明适用的限制和假设。 From Review 我喜欢这个答案的简单性,它与问题地址有相同的 3 行。我认为不需要解释。谢谢。【参考方案9】:

另外,你可以用这个...

DECLARE @SeqID varchar(150);
DECLARE @TableName varchar(150);
SET @TableName = (Select TableName from Table);
SET @SeqID = 'SELECT NEXT VALUE FOR ' + @TableName + '_Data'
exec (@SeqID)

【讨论】:

【参考方案10】:
Declare @fs_e int, @C_Tables CURSOR, @Table varchar(50)

SET @C_Tables = CURSOR FOR
        select name from sysobjects where OBJECTPROPERTY(id, N'IsUserTable') = 1 AND name like 'TR_%'
OPEN @C_Tables
FETCH @C_Tables INTO @Table
    SELECT @fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '@C_Tables'

WHILE ( @fs_e <> -1)
    BEGIN
        exec('Select * from ' + @Table)
        FETCH @C_Tables INTO @Table
        SELECT @fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '@C_Tables'
    END

【讨论】:

以上是关于表名作为变量的主要内容,如果未能解决你的问题,请参考以下文章

在 azure synapse 存储过程中将表名作为参数传递时将查询结果分配给变量

python的pymysql中以表名作为变量传递进查询语句中

如何通过 PL/SQL 过程和表名作为变量打印动态 SQL 中的所有表行?

如何创建一个以表名作为输入的简单存储过程

添加逗号,变量名作为后缀

Bash 将变量名作为参数传递