web-dev-qa-db-ja.com

SELECTのみのアクセス権を持つデータベース内のすべてのビューの行をカウントするSQLスクリプト

SELECTのみのアクセス権が与えられているサードパーティデータベースのすべてのビューの行数を知る必要があります。次のスクリプトはテーブルでは機能しますが、ビューでは機能しません。

SELECT      SCHEMA_NAME(A.schema_id) + '.' +
        --A.Name, SUM(B.rows) AS 'RowCount'  Use AVG instead of SUM
          A.Name, AVG(B.rows) AS 'RowCount'
FROM        sys.objects A
INNER JOIN sys.partitions B ON A.object_id = B.object_id
WHERE       A.type = 'U'
GROUP BY    A.schema_id, A.Name
Order by AVG(B.rows) desc
GO

私はオンラインで見ましたが、すべての提案はテーブルに対してのみ機能するか、テーブルまたはプロシージャを作成する必要があります(このレベルの権限では実行できません)、またはビューごとに行を個別にカウントする必要があります。これは実行不可能です。このようなビューを多数含むデータベースの場合。

CREATEまたはEXECUTE権限を必要とせずに、データベース内のすべてのビューのすべての行をカウントするスクリプトのアイデアはありますか?

2
Mel

いくつかの改善。

  • QUOTENAME()は、不適切な名前を阻止します
  • スキーマが重要であるため、スキーマ名を追加します
  • 使用する sys.views の代わりに sys.objects(およびtypeを出力から削除)
  • 制限sys.partitionsからindex_id 0または1。追加の非クラスター化インデックスを持つインデックス付きビューの場合の二重カウントを防止します(AVGが何を実行すると思うかわからない-非インデックス付きのインデックス付きビューがある場合はどうなるかクラスター化filtered index?
  • 動的SQLを使用して、手動コピー/手動貼り付け/手動マッサージ/手動実行を回避する

    DECLARE @sql nvarchar(max) = N'';
    
    SELECT @sql += N'UNION ALL 
    SELECT ' 
      + 'N''' + QUOTENAME(s.name) + N'.' + QUOTENAME(v.name) + N''',
      FromMetadata = N' + CONVERT(varchar(11),COALESCE(SUM(p.rows),0)) + N',
      TheHarderWay = COUNT(*) FROM ' + QUOTENAME(s.name) + N'.' + QUOTENAME(v.name) +N'
    '
    FROM sys.views AS v
    INNER JOIN sys.schemas AS s
    ON v.schema_id = s.schema_id
    LEFT OUTER JOIN sys.partitions AS p
    ON v.object_id = p.object_id
    AND p.index_id IN (0,1)
    GROUP BY s.name, v.name
    ORDER BY s.name, v.name;
    
    SET @sql = STUFF(@sql, 1, CHARINDEX(N'SELECT', @sql)-1, N'');
    
    PRINT @sql;
    --EXEC sys.sp_executesql @sql;
    

ビューがインデックス付けされていない限り、FromMetadataは0になることに注意してください。

3
Aaron Bertrand

これは単一のスクリプトではありませんが、Andrey Nikolovがここで説明した方法は機能するようです。

https://stackoverflow.com/questions/53263435/how-do-i-get-the-list-of-all-views-present-in-a-database-and-its-record-count

テーブルのみではなくビューのみを返すバージョンのスクリプトを使用します。

select o.name, sum(p.rows) as RowsCount, o.type, concat('select ''', o.name, ''' as ObjectName, count(*) as RowsCount from ', o.name, ' union all ')
from sys.objects o
left join sys.partitions p on p.object_id = o.object_id
where o.type in ('V')
group by o.name, o.type
order by o.name

そして、最後のUNION ALLが削除された最後の列の結果をコピーして実行します。

(私の場合、データベースデザイナーがテーブルに「ユーザー」や「ケース」などの名前を付けていたため、角括弧とスキーマ名を追加して、最初のクエリの結果の最終列をコピーして生成されたスクリプトを変更する必要がありました。 )

これが同じ問題を抱えている他の人に役立つことを願っています!

2
Mel