Select 来自 SQL 服务器中的表列表

Select from list of tables in SQL Server

我有一个 table 的列表,我最终想建立一些 JSON,如下所示:

{
    "Table1": [
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" }
    ],
    "Table2": [
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" }
    ],
    "Table3": [
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" },
        { "col1": "value", "col2": "value" }
    ]
}

创建 JSON 对我来说不是问题(虽然我不能在 SQL Server 2014 上使用 FOR JSON)而且我什至对 SQL:

declare @tables table (
    tabname varchar(100)
)
insert into @tables(tabname)
select 'Table1' union all
select 'Table2' union all
select 'Table3'

/* Master dataset */
select tabname from @tables 

declare tabcur cursor for select tabname from @tables 

open tabcur

declare @tabname varchar(100)

fetch tabcur into @tabname
while @@FETCH_STATUS = 0
begin
    /* Detail dataset */
    execute ('select * from [' + @tabname + ']')
    fetch tabcur into @tabname
end

close tabcur
deallocate tabcur

这背后的想法是我得到一个 table 的列表作为主数据集,并且对于每一行我还得到一个详细数据集。我可以通过索引匹配它们,或者通过将 table 名称添加到详细数据集来消除主数据集。

哪个都行。但是我的实际列表包含 724 table 并且性能很差。

然后我将其更改为构建一个 SQL 字符串的 union all 语句,并且仅在释放游标后才执行该字符串。这主要解决了我的性能问题。

但这似乎仍然是九十年代的做法。从那时起 SQL Server 添加了所有有趣的东西,我想一定有更简单的方法。我基本上希望使用主数据集作为第二个数据集的输入,该数据集包含所有 tables 中的行(我感兴趣的列在所有 tables 中都相同,所以它们将作为一个结果集工作)。

我的下一次尝试是创建一个接受 table 名称作为参数和 returns 结果集的函数。我想我可以交叉申请:

select tabname, result.col1, result.col2
from @tables 
cross apply dbo.SelectFromTable(@tables.tabname) result

但那是胎死腹中,因为 SQL 服务器不允许在函数内动态 SQL。

那么有没有一种没有游标的性能良好的方法呢?

它不漂亮,你真的应该看看不同的设计,但如果你坚持这样做,你可以避免 cursorfor xml(用于将所有行放入一个分隔列)和 stuff(用于删除前导分隔符,在本例中为 ' union all ' :

declare @tables table (
    tabname varchar(100)
);
insert into @tables(tabname)
select 'Table1' union all
select 'Table2' union all
select 'Table3';

select stuff((select ' union all select * from [' + tabname + ']'
                from @tables
                for xml path('')
                )
            ,1,11,'') as query

输出:

select * from [Table1] union all select * from [Table2] union all select * from [Table3]