0

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

我希望能够有一个基于集合的查询,它可以输出仅包含 CoreTables 中填充了数据的那些表的列表。

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

对于 CoreTables 中的每一行 获取表名 如果表为空 什么都不做 Else 打印表名

有没有办法在没有游标或其他动态方法的情况下做到这一点?感谢您的任何帮助...

4

4 回答 4

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 表中聚合捕获的重叠架构),您可能需要构建一个视图,例如:

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;

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

于 2012-05-25T16:14:20.777 回答
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

于 2012-05-25T15:58:17.653 回答
0

像这样的东西?

//
            foreach (System.Data.DataTable dt in yourDataSet.Tables)
            {
                if (dt.Rows.Count != 0) { PrintYourTableName(dt.TableName); }
            }
            //
于 2012-05-25T15:49:59.007 回答
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
于 2012-05-25T16:12:22.337 回答