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。
那么有没有一种没有游标的性能良好的方法呢?
它不漂亮,你真的应该看看不同的设计,但如果你坚持这样做,你可以避免 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]
我有一个 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。
那么有没有一种没有游标的性能良好的方法呢?
它不漂亮,你真的应该看看不同的设计,但如果你坚持这样做,你可以避免 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]