サーバー内のすべてのテーブルの行数を取得しようとしています (特定のデータベースではなく、msdb、モデル、マスターなどを除く、サーバー上のすべてのデータベース)。データベース名、テーブル名、および行数以外の詳細を返す必要はありません。
この問題に対する私のアプローチは、サーバー内のすべてのデータベースを取得し、それらに ID を配置することです。これは while ループで参照されます (ID 1 から始まり、最大 ID まで)。次に、while ループ内で、一致するデータベース ID のテーブルと行数を取得します。私の問題は、USE DatabaseName では動的にすることができないように見えることです。つまり、データベース名を変数に格納して、行カウント クエリを使用してテーブルを実行するときに参照データベースとして使用することはできません。
私が見逃している別のアプローチはありますか(他の多くの例を見てきました-カーソルを使用することが多く、コードがはるかに長く、より多くのリソースを使用しているように見えます.次のデータベースなどにヒットしないことを除いて、テーブルごとの最大のデータベース)、またはこれを動的にするコードに明らかな何かが欠けていますか?
DECLARE @ServerTable TABLE(
DatabaseID INT IDENTITY(1,1),
DatabaseName VARCHAR(50)
)
DECLARE @count INT
DECLARE @start INT = 1
SELECT @count = COUNT(*) FROM sys.databases WHERE name NOT IN ('master','tempdb','model','msdb')
INSERT INTO @ServerTable (DatabaseName)
SELECT name
FROM sys.databases
WHERE name NOT IN ('master','tempdb','model','msdb')
WHILE @start < @count
BEGIN
DECLARE @db VARCHAR(50)
SELECT @db = DatabaseName FROM @ServerTable WHERE DatabaseID = @start
-- This is the problem, as the USE doesn't seem to allow it to be dynamic.
USE @db
GO
SELECT @db
,o.name [Name]
,ddps.row_count [Row Count]
FROM sys.indexes AS i
INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID AND i.index_id = ddps.index_id
WHERE i.index_id < 2 AND o.is_ms_shipped = 0
ORDER BY o.NAME
SET @start = @start + 1
END
注: sys.objects と sys.indexes をチェックインして、データベース名でフィルター処理できるかどうかを確認しようとしましたが、うまくいきませんでした。
更新:を動的なものに変えてみSELECT
ましたが、成功しませんでした (以下のコードは変更のみを示していることに注意してくださいSELECT
):
SET @sql = '
SELECT ' + @db + ' [Database]
,o.name [Name]
,ddps.row_count [Row Count]
FROM ' + @db + '.sys.objects
INNER JOIN ' + @db + ' sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
INNER JOIN ' + @db + ' sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID AND i.index_id = ddps.index_id
WHERE i.index_id < 2 AND o.is_ms_shipped = 0
ORDER BY o.NAME'