我有一个数据库 A,其中包含一个表(CoreTables),该表存储了数据库 B 中的活动表列表,组织的用户正在向这些表发送数据。
我希望能够有一个基于集合的查询,它可以输出仅包含 CoreTables 中填充了数据的那些表的列表。
动态地,我通常会做类似的事情:
对于 CoreTables 中的每一行 获取表名 如果表为空 什么都不做 Else 打印表名
有没有办法在没有游标或其他动态方法的情况下做到这一点?感谢您的任何帮助...
我有一个数据库 A,其中包含一个表(CoreTables),该表存储了数据库 B 中的活动表列表,组织的用户正在向这些表发送数据。
我希望能够有一个基于集合的查询,它可以输出仅包含 CoreTables 中填充了数据的那些表的列表。
动态地,我通常会做类似的事情:
对于 CoreTables 中的每一行 获取表名 如果表为空 什么都不做 Else 打印表名
有没有办法在没有游标或其他动态方法的情况下做到这一点?感谢您的任何帮助...
可能最有效的选择是:
SELECT c.name
FROM dbo.CoreTables AS c
WHERE EXISTS
(
SELECT 1
FROM sys.partitions
WHERE index_id IN (0,1)
AND rows > 0
AND [object_id] = OBJECT_ID(c.name)
);
请注意,由于进行中的事务,sys.sysindexes、sys.partitions 和 sys.dm_db_partition_stats 中的计数不能保证完全同步。
虽然您可以只在数据库的上下文中运行此查询,但您可以对不同的数据库执行此操作,如下所示(再次假设 CoreTables 的名称中不包含架构):
SELECT c.name
FROM DatabaseA.CoreTables AS c
WHERE EXISTS
(
SELECT 1
FROM DatabaseB.sys.partitions AS p
INNER JOIN DatabaseB.sys.tables AS t
ON p.[object_id] = t.object_id
WHERE t.name = c.name
AND p.rows > 0
);
如果您需要对都包含相同架构的多个数据库执行此操作(或者至少是您在中央 CoreTables 表中聚合捕获的重叠架构),您可能需要构建一个视图,例如:
CREATE VIEW dbo.CoreTableCounts
AS
SELECT db = 'DatabaseB', t.name, MAX(p.rows)
FROM DatabaseB.sys.partitions AS p
INNER JOIN DatabaseB.sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN DatabaseA.dbo.CoreTables AS ct
ON t.name = ct.name
WHERE p.index_id IN (0,1)
GROUP BY t.name
UNION ALL
SELECT db = 'DatabaseC', t.name, rows = MAX(p.rows)
FROM DatabaseC.sys.partitions AS p
INNER JOIN DatabaseC.sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN DatabaseA.dbo.CoreTables AS ct
ON t.name = ct.name
WHERE p.index_id IN (0,1)
GROUP BY t.name
-- ...
GO
现在您的查询不会那么高效,但不需要将数据库名称硬编码为对象前缀,而是可以:
SELECT name
FROM dbo.CoreTableCounts
WHERE db = 'DatabaseB'
AND rows > 0;
如果执行起来很痛苦,您可以为每个数据库创建一个视图。
这是您可以做到的一种方式,它依赖于系统表,因此请注意,它可能并不总是适用于未来的 SQL 版本。牢记这一强烈警告。
select distinct OBJECT_NAME(id) as tabName,rowcnt
from sys.sysindexes si
join sys.objects so on si.id=si.id
where indid=1 and so.type='U'
您将在 where 子句中添加您感兴趣的表和 rowcnt <1
像这样的东西?
//
foreach (System.Data.DataTable dt in yourDataSet.Tables)
{
if (dt.Rows.Count != 0) { PrintYourTableName(dt.TableName); }
}
//
在 SQL Server 中,您可以执行以下操作:
SELECT o.name, st.row_count
FROM sys.dm_db_partition_stats st join
sys.objects o
on st.object_id = o.object_id
WHERE index_id < 2 and st.row_count > 0
顺便说一句,这特别不使用 OBJECT_ID() 或 OBJECT_NAME() 因为它们是在当前数据库中评估的。上面的代码继续适用于另一个数据库,使用 3 部分命名。此版本还考虑了多个分区:
SELECT o.name, sum(st.row_count)
FROM <dbname>.sys.dm_db_partition_stats st join
<dbname>.sys.objects o
on st.object_id = o.object_id
WHERE index_id < 2
group by o.name
having sum(st.row_count) > 0