有没有办法让 table name 作为 sql 服务器中的变量?
is there a way to make table name as variable in sql server?
使用 SQL 服务器
我有使用 table 名称的查询
Select *
from MyDB..Table1 A inner join MyDB..Table1 B ON A.ID = B.ParentID
SELECT * FROM MyDB..Table1 WHERE No > @X
.
.
.
我必须 运行 这些查询 10+ tables
我不想讨论数据库的架构
但这就是现状
我想要一种方法来制作 table 名称变量(如果可能)并在一个地方而不是所有地方更改它
@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
.
.
.
您不能在静态 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)
不直接。一个适用于 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
SQL如果应用 PEO 或常量折叠,服务器将完全优化掉不相关的 UNION ALL 情况,就好像 UNION ALL 分支甚至不存在于视图/查询!
即使没有 PEO,只有名称匹配时才会查询表,因为 SQL 服务器 将在执行期间消除 'non reachable' UNION ALL 分支 。但是,此过滤器在查询执行期间应用,并且表仍包含在查询计划中。 (如果所有表都没有相同的偏好索引,有时这会导致奇怪的计划。)
不幸的是,这种方法对 DML 有局限性(例如,视图 不可更新 ),对于 DML,我发现动态 SQL,如其他答案,好好工作。
使用 SQL 服务器
我有使用 table 名称的查询
Select *
from MyDB..Table1 A inner join MyDB..Table1 B ON A.ID = B.ParentID
SELECT * FROM MyDB..Table1 WHERE No > @X
.
.
.
我必须 运行 这些查询 10+ tables
我不想讨论数据库的架构
但这就是现状
我想要一种方法来制作 table 名称变量(如果可能)并在一个地方而不是所有地方更改它
@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
.
.
.
您不能在静态 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)
不直接。一个适用于 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
SQL如果应用 PEO 或常量折叠,服务器将完全优化掉不相关的 UNION ALL 情况,就好像 UNION ALL 分支甚至不存在于视图/查询!
即使没有 PEO,只有名称匹配时才会查询表,因为 SQL 服务器 将在执行期间消除 'non reachable' UNION ALL 分支 。但是,此过滤器在查询执行期间应用,并且表仍包含在查询计划中。 (如果所有表都没有相同的偏好索引,有时这会导致奇怪的计划。)
不幸的是,这种方法对 DML 有局限性(例如,视图 不可更新 ),对于 DML,我发现动态 SQL,如其他答案,好好工作。