从SQL Server中的表列表中进行选择

时间:2017-01-13 09:23:04

标签: sql sql-server json cursor sql-server-2014

我有一个表列表,我最终想要构建一些看起来像这样的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

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

无论哪种方法都有效。但我的实际列表包含724个表,性能很差。

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

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

我的下一次尝试是创建一个接受表名作为参数并返回结果集的函数。我以为我可以交叉申请:

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

但这仍然是死产,因为SQL Server不允许在函数中使用动态SQL。

在没有光标的情况下,有没有一种表现良好的方法呢?

1 个答案:

答案 0 :(得分:1)

它不漂亮而你 真的 应该看一个不同的设计,但是如果你这样做是困难的,你可以避免使用cursor for 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]