【问题标题】:is there a way to make table name as variable in sql server? [duplicate]有没有办法在 sql server 中将表名作为变量? [复制]
【发布时间】:2022-01-26 03:34:45
【问题描述】:

使用 SQL Server

我有使用表名的查询

Select *
from MyDB..Table1 A inner join MyDB..Table1 B ON A.ID = B.ParentID

SELECT * FROM MyDB..Table1 WHERE No > @X

.
.
.

我必须为 10 多个表运行这些查询

我不想讨论数据库的架构

但这是现状

我想要一种方法使表名可变(如果可能)并在一个地方而不是所有地方进行更改

@declare @T as Table = MyDB..Table1
Select *
from @T A inner join @T B ON A.ID = B.ParentID

SELECT * FROM @T WHERE No > @X

.
.
.

【问题讨论】:

  • @MitchWheat,我已将问题标记为重复。你能不能也这样做。

标签: sql sql-server tsql


【解决方案1】:

不直接。一个适用于 SELECT 查询的选项是创建一个视图:

CREATE VIEW allTables (name, a, b)
AS
  SELECT 'Table1' as name, a, b
  FROM Table1
      UNION ALL
  SELECT 'Table2' ..

-- with constant; same as writing SELECT a, b FROM Table2
SELECT a, b
FROM allTables
WHERE name = 'Table2'

-- with variable; without PEO, all tables in QP even if not accessed
SELECT a, b
FROM allTables
WHERE name = @T
-- OPTION (RECOMPILE) -- get PEO, at expense of recompilation

如果应用 PEO 或常量折叠,SQL Server 将完全优化不相关的 UNION ALL 情况,就好像视图/查询中根本不存在 UNION ALL 分支一样! p>

即使没有 PEO,只有在名称与 SQL Server 匹配时才会查询表将在执行期间消除“不可访问”的 UNION ALL 分支。但是,此过滤器在查询执行期间应用,并且表仍包含在查询计划中。 (如果所有表都没有相同的首选索引,有时这可能会导致奇怪的计划。)

不幸的是,这种方法对 DML 有限制(例如,视图是不可更新),对于 DML,我发现动态 SQL(如另一个答案所示)可以很好地工作。

【讨论】:

    【解决方案2】:

    您不能在静态 SQL 中执行此操作,但对于动态 SQL 来说这是微不足道的,例如

    declare @T as sysname = 'Table1'
    
    declare @sql nvarchar(max) = 'Select * from TableNamePlaceholder A inner join TableNamePlaceholder B ON A.ID = B.ParentID'
    set @sql = replace(@sql,'TableNamePlaceholder',quotename(@T))
    exec (@sql)
    

    【讨论】:

    • 使用说明:即使在查询中添加了原始文本,使用 quotename 也可以防止愚蠢的错误并减轻 SQL 注入。
    猜你喜欢
    • 2017-12-21
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 2020-09-02
    相关资源
    最近更新 更多