表名作为变量

发布于 2024-09-01 11:11:22 字数 250 浏览 5 评论 0原文

我正在尝试执行此查询:

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

这会产生以下错误:

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

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

缱绻入梦 2024-09-08 11:11:22

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

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

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

静态查询:

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

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

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

由于动态查询有很多需要考虑的细节,而且它们很难维护,我建议您阅读:动态 SQL 的诅咒和祝福

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

红玫瑰 2024-09-08 11:11:22

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

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''')

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''')
み青杉依旧 2024-09-08 11:11:22

使用:

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

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
旧城烟雨 2024-09-08 11:11:22

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

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

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)
染年凉城似染瑾 2024-09-08 11:11:22

您需要动态生成 SQL 内容:

declare @tablename varchar(50)

set @tablename = 'test'

declare @sql varchar(500)

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

exec (@sql)

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)
友欢 2024-09-08 11:11:22

使用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

Use sp_executesql to execute any SQL, e.g.

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
梨涡少年 2024-09-08 11:11:22

您需要使用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

You need to use the SQL Server dynamic SQL:

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

SET @table = N'tableName';

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

Use EXEC to execute any SQL:

EXEC (@sql)

Use EXEC sp_executesql to execute any SQL:

EXEC sp_executesql @sql;

Use EXECUTE sp_executesql to execute any SQL:

EXECUTE sp_executesql @sql
心头的小情儿 2024-09-08 11:11:22
Declare  @tablename varchar(50) 
set @tablename = 'Your table Name' 
EXEC('select * from ' + @tablename)
Declare  @tablename varchar(50) 
set @tablename = 'Your table Name' 
EXEC('select * from ' + @tablename)
鹊巢 2024-09-08 11:11:22

希望这段代码有帮助

-- Start process check by counting rows item
SET @Count_Row = 0;
SET @SqlMain = 'SELECT @Cnt = COUNT(*) FROM ['+@Tab_Name+'] WHERE ['+@Col_Name+'] LIKE ''%'+@SearchVal+'%'''
SET @Parm = '@Cnt INT OUTPUT'

EXEC sp_executesql @SqlMain , @Parm , @Cnt = @Count_Row OUT

SET @TotalRow = @TotalRow + @Count_Row

IF  @Count_Row >= 1

    PRINT @Tab_Name+' - '+@Col_Name+' - '+ CONVERT(VARCHAR(10), @Count_Row)

FETCH NEXT FROM CUR_GET_INFO INTO @Tab_Name,@Col_Name

END

Hopefully this code helps

-- Start process check by counting rows item
SET @Count_Row = 0;
SET @SqlMain = 'SELECT @Cnt = COUNT(*) FROM ['+@Tab_Name+'] WHERE ['+@Col_Name+'] LIKE ''%'+@SearchVal+'%'''
SET @Parm = '@Cnt INT OUTPUT'

EXEC sp_executesql @SqlMain , @Parm , @Cnt = @Count_Row OUT

SET @TotalRow = @TotalRow + @Count_Row

IF  @Count_Row >= 1

    PRINT @Tab_Name+' - '+@Col_Name+' - '+ CONVERT(VARCHAR(10), @Count_Row)

FETCH NEXT FROM CUR_GET_INFO INTO @Tab_Name,@Col_Name

END

临风闻羌笛 2024-09-08 11:11:22

另外,您还可以使用这个...

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

Also, you can use this...

DECLARE @SeqID varchar(150);
DECLARE @TableName varchar(150);
SET @TableName = (Select TableName from Table);
SET @SeqID = 'SELECT NEXT VALUE FOR ' + @TableName + '_Data'
exec (@SeqID)
酒绊 2024-09-08 11:11:22
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文