Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何确定数据库中的一组特定表是否为空_Sql_Sql Server 2008 - Fatal编程技术网

Sql 如何确定数据库中的一组特定表是否为空

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

我有一个数据库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
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的所有建议。多数据库查询当前没有返回我期望的结果,因此我正在调试,并将在看到故障所在时进行更新。