0

組織のユーザーがデータを送信しているデータベースB内のアクティブなテーブルのリストを格納するテーブル(CoreTables)を含むデータベースAがあります。

データが入力されているCoreTables内のテーブルのみのリストを出力できるセットベースのクエリを作成できるようにしたいと思います。

動的に、私は通常次のようなことをします:

CoreTablesの各行についてテーブル名を取得しますテーブルが空の場合何もしませんそれ以外の場合はテーブル名を出力します

カーソルやその他の動的な方法なしでこれを行う方法はありますか?助けてくれてありがとう...

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 に答える