Sql 如何确定数据库中的一组特定表是否为空
我有一个数据库A,其中包含一个表(CoreTables),该表在数据库B中存储了一个活动表列表,组织的用户正在向数据库B发送数据 我希望能够有一个基于集合的查询,只输出CoreTables中那些填充了数据的表的列表 在动态方面,我通常会做如下操作:Sql 如何确定数据库中的一组特定表是否为空,sql,sql-server-2008,Sql,Sql Server 2008,我有一个数据库A,其中包含一个表(CoreTables),该表在数据库B中存储了一个活动表列表,组织的用户正在向数据库B发送数据 我希望能够有一个基于集合的查询,只输出CoreTables中那些填充了数据的表的列表 在动态方面,我通常会做如下操作: SELECT o.name, st.row_count FROM sys.dm_db_partition_stats st join sys.objects o on st.object_id = o.object_id WHER
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
对于CoreTable中的每一行
获取表名
如果表是空的
无所事事
其他的
打印表名
有没有一种不用光标或其他动态方法就能做到这一点的方法?谢谢你的帮助……像这样的事情
//
foreach (System.Data.DataTable dt in yourDataSet.Tables)
{
if (dt.Rows.Count != 0) { PrintYourTableName(dt.TableName); }
}
//
这是一种依赖于系统表的方法,因此请注意,它在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'
您可以将感兴趣的表和SQL Server中的rowcnt添加到where子句中,您可以执行以下操作:
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
选择o.name、st.row\u计数
从sys.dm\u db\u分区\u stats st join
系统对象
在st.object\u id=o.object\u id上
其中索引id<2且st.row\U计数>0
顺便说一下,这并不使用OBJECT_ID()或OBJECT_NAME(),因为它们是在当前数据库中计算的。上述代码继续适用于另一个数据库,使用三部分命名。此版本还考虑了多个分区:
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
选择o.name,总和(st.row\U计数)
FROM.sys.dm_db_partition_stats st join
.sys.o
在st.object\u id=o.object\u id上
其中索引_id<2
按o.name分组
总和(圣罗w_计数)>0
最有效的选择可能是:
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的名称中不包含schema):
如果需要对多个数据库执行此操作,而这些数据库都包含相同的架构(或至少包含在中心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;
如果执行起来很痛苦,您可以为每个数据库创建一个视图。请不要使用sys.sysindex-这是一个向后兼容视图。您应该使用sys.partitions或sys.dm_db_partition_stats,它们是公共的和有文档记录的目录视图/DMV,与将来的更改隔离得多。感谢Aaron,我知道它是向后兼容的,并想警告OP。感谢您展示了更好的视图来使用…对于分区表,如果任何这样的表在多个分区中包含数据,您将得到重复的行。我也不知道SUM是否是正确答案,您只需要一个分区至少包含一行。Aaron,这是真的,您的观点非常正确。但是,我经常使用版本(带总和)来获取表的行数。在此基础上构建似乎最容易,除非他有数千个表,这可能会减慢查询速度。是的,我的意思是他不需要求和,因为他只想知道它是否为空(是/否)。只是澄清一下,你没有试图根据结果构建CoreTable中的表列表,对吗?CoreTables已经有一组预填充的表,您想运行一个查询,显示当前至少有一行的那些表的子集吗?是的,这是正确的。谢谢你的回复。我仍在努力解决这些问题,以确保我理解所有要点。因此,我想明确一点,如果不求助于至少一个系统级结构(例如,系统分区),就无法完成上述工作?我不知道你所说的“不求助于上述工作”是什么意思。。。您是否尝试过发布的任何解决方案?此外,如果有多个表具有相同的名称但具有不同的模式,则应小心。如果DBO.CaleTabes包含模式名,那么上面应该是OK,否则您可能想考虑添加它。如果DBO.CalePipe和表中的表在不同的数据库中,有没有修改这个查询的方法?例如,如果CoreTables位于数据库A中,而引用的表位于数据库B中?@user1417733能否更新原始问题以包含跨数据库要求?非常感谢Aaron的所有建议。多数据库查询当前没有返回我期望的结果,因此我正在调试,并将在看到故障所在时进行更新。