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

时间:2012-05-25 15:46:21

标签: sql sql-server-2008

我有一个数据库A,它包含一个表(CoreTables),用于存储组织用户正在向其发送数据的数据库B中的活动表列表。

我希望能够拥有一个基于集合的查询,该查询只能输出CoreTables中填充了数据的那些表的列表。

动态地,我通常会做类似的事情:

对于CoreTables中的每一行    获取表名    如果表是空的       没做什么    其他       打印表格名称

有没有办法在没有游标或其他动态方法的情况下执行此操作?谢谢你的帮助......

4 个答案:

答案 0 :(得分:1)

可能最有效的选择是:

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表中聚合的模式),您可能需要构建一个视图,例如: / p>

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;

如果执行起来很痛苦,您可以为每个数据库创建一个视图。

答案 1 :(得分:0)

这样的事情?

//
            foreach (System.Data.DataTable dt in yourDataSet.Tables)
            {
                if (dt.Rows.Count != 0) { PrintYourTableName(dt.TableName); }
            }
            //

答案 2 :(得分:0)

这是一种可以执行此操作的方法,它依赖于系统表,因此AWARE在未来的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

答案 3 :(得分:0)

在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