Veritabanındaki her tablodaki kayıt sayısını listeleme sorgusu


199

Veritabanındaki her tablonun satır sayısını listeleme. Bazı eşdeğeri

select count(*) from table1
select count(*) from table2
...
select count(*) from tableN

Bir çözüm yollayacağım ama diğer yaklaşımlar da hoş karşılanacak

Yanıtlar:


314

SQL Server 2005 ve sonraki sürümlerini kullanıyorsanız, bunu da kullanabilirsiniz:

SELECT 
    t.NAME AS TableName,
    i.name as indexName,
    p.[Rows],
    sum(a.total_pages) as TotalPages, 
    sum(a.used_pages) as UsedPages, 
    sum(a.data_pages) as DataPages,
    (sum(a.total_pages) * 8) / 1024 as TotalSpaceMB, 
    (sum(a.used_pages) * 8) / 1024 as UsedSpaceMB, 
    (sum(a.data_pages) * 8) / 1024 as DataSpaceMB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
WHERE 
    t.NAME NOT LIKE 'dt%' AND
    i.OBJECT_ID > 255 AND   
    i.index_id <= 1
GROUP BY 
    t.NAME, i.object_id, i.index_id, i.name, p.[Rows]
ORDER BY 
    object_name(i.object_id) 

Bence, sp_msforeachtableçıktıdan daha kolay işlenir.


1
Neden "dt" ile başlayan bir isimle tabloları filtrelemek herhangi bir fikir? Bu senaryoyu internetin her yerinde gördüm, ama bu kriterler hakkında bir açıklama yok. Hepimiz trolleniyor muyuz?
Skaue

6
@Skaue: "Veritabanı Diyagramı" işlevini kendi veritabanınıza yüklerseniz, bunun gibi bazı tablolarınız olur dtProperties; bunlar "sistem" tabloları olduğu için, bunlar hakkında rapor vermek istemiyorum.
marc_s

1
Bu komut dosyasında, tablename'in şema adıyla ön ek yapma olasılığı var mı?
gh0st

Nedense bu sorgu tüm tabloları döndürmüyor. Bir veritabanında 382 tablo var. Ancak bu sorgu yalnızca 270 satır döndürüyor (tablo bilgileri). Where koşulunu kaldırdıktan sonra 302 satır alıyorum. Bu tabloların bazılarının SYS tablolarından birindeki eksik olması nedeniyle birleşimler onları atlıyor. Veritabanı herhangi bir sistem tablosu içermiyor.
Ankesh Kushwah

Bu işe yarıyor. iki veritabanını karşılaştırmak için değiştirebilirsiniz.
sanjeewa

107

Http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=21021 adresinde bulduğum bir snippet bana yardımcı oldu:

select t.name TableName, i.rows Records
from sysobjects t, sysindexes i
where t.xtype = 'U' and i.id = t.id and i.indid in (0,1)
order by TableName;

5
JOINSözdizimini kullanmamıza rağmen bu çözümü beğendimfrom sysobjects t inner join sysindexes i on i.id = t.id and i.indid in (0,1) where t.xtype = 'U'
Shnugo

Ben de JOIN deyimlerini kullanmayı tercih ama buldum gibi kod snippet gönderdi. :)
Erik Anderson

32

SQL Management Studio'da bu bilgileri almak için veritabanına sağ tıklayın, ardından Raporlar -> Standart Raporlar -> Tabloya Göre Disk Kullanımı'nı seçin.


6
Yetersiz yaklaşım, bu hızlı bir şekilde # satır ve verilerin boyutunu gösteren sıralanabilir bir rapor oluşturur.
tbone

8
SELECT 
    T.NAME AS 'TABLE NAME',
    P.[ROWS] AS 'NO OF ROWS'
FROM SYS.TABLES T 
INNER JOIN  SYS.PARTITIONS P ON T.OBJECT_ID=P.OBJECT_ID;

3
Bu Sorgu, her tablodaki her dizin için bir satır sonucu döndürür. Bir WHERE P.INDEX_ID IN (0,1) değerini, küme veya kümelenmiş dizinlerle ayarlanan dönüş sonucunu yalnızca uygun olduğunda sınırlandırmak için ekleyin.
Rasmus Remmer Bielidt

6

Burada görüldüğü gibi, bu, meta veri tablolarını kullanan yöntemlerin yalnızca tahminleri döndüreceği doğru sayıları döndürür.

    CREATE PROCEDURE ListTableRowCounts 
    AS 
    BEGIN 
        SET NOCOUNT ON 

        CREATE TABLE #TableCounts
        ( 
            TableName VARCHAR(500), 
            CountOf INT 
        ) 

        INSERT #TableCounts
            EXEC sp_msForEachTable 
                'SELECT PARSENAME(''?'', 1), 
                COUNT(*) FROM ? WITH (NOLOCK)' 

        SELECT TableName , CountOf 
            FROM #TableCounts
            ORDER BY TableName 

        DROP TABLE #TableCounts
    END
    GO

Bu nedenle, bazen en güncel olmayan bilgilere sahip sistem tablolarını vs kullanarak belgelenmemiş stor proc sp_msForEachTable kullanmanın ödün vermesi gibi geliyor. +1 ve bağlantı için teşekkürler
kristof

3
sp_MSForEachTable 'DECLARE @t AS VARCHAR(MAX); 
SELECT @t = CAST(COUNT(1) as VARCHAR(MAX)) 
+ CHAR(9) + CHAR(9) + ''?'' FROM ? ; PRINT @t'

Çıktı:

resim açıklamasını buraya girin


Sql Server 2000 için bir şeye ihtiyacım vardı. Bu işe yaradı. Teşekkürler!
Alrekr

3

Neyse ki SQL Server yönetim stüdyosu bunu nasıl yapacağınıza dair bir ipucu verir. Bunu yap,

  1. SQL Server izlemesi başlatın ve yaptığınız etkinliği açın (yalnız değilseniz oturum açma kimliğinize göre filtreleyin ve uygulama Adını Microsoft SQL Server Management Studio olarak ayarlayın), izlemeyi duraklatın ve şimdiye kadar kaydettiğiniz sonuçları atın;
  2. Ardından, bir tabloya sağ tıklayın ve açılır menüden özellik seçin;
  3. izi yeniden başlat;
  4. Şimdi SQL Server Management Studio'da soldaki depolama özelliği öğesini seçin;

İzi duraklatın ve TSQL'in microsoft tarafından oluşturulduğuna bir göz atın.

Muhtemelen son sorguda ile başlayan bir ifade göreceksiniz exec sp_executesql N'SELECT

yürütülen kodu görsel stüdyoya kopyaladığınızda, bu kodun microsoft mühendislerinin özellik penceresini doldurmak için kullandığı tüm verileri oluşturduğunu göreceksiniz.

bu sorguda ılımlı değişiklikler yaptığınızda şöyle bir şey elde edersiniz:

SELECT
SCHEMA_NAME(tbl.schema_id)+'.'+tbl.name as [table], --> something I added
p.partition_number AS [PartitionNumber],
prv.value AS [RightBoundaryValue],
 fg.name AS [FileGroupName],
CAST(pf.boundary_value_on_right AS int) AS [RangeType],
CAST(p.rows AS float) AS [RowCount],
p.data_compression AS [DataCompression]
FROM sys.tables AS tbl
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) AND p.index_id=idx.index_id
LEFT OUTER JOIN sys.destination_data_spaces AS dds ON dds.partition_scheme_id = idx.data_space_id and dds.destination_id = p.partition_number
LEFT OUTER JOIN sys.partition_schemes AS ps ON ps.data_space_id = idx.data_space_id
LEFT OUTER JOIN sys.partition_range_values AS prv ON prv.boundary_id = p.partition_number and prv.function_id = ps.function_id
LEFT OUTER JOIN sys.filegroups AS fg ON fg.data_space_id = dds.data_space_id or fg.data_space_id = idx.data_space_id
LEFT OUTER JOIN sys.partition_functions AS pf ON  pf.function_id = prv.function_id

Şimdi sorgu mükemmel değil ve aklınıza gelebilecek diğer soruları karşılamak için güncelleyebilirsiniz, nokta, ilgilendiğiniz verileri yürüterek ve izlediğiniz soruların çoğuna ulaşmak için microsoft bilgisini kullanabilirsiniz. profiler kullanılarak oluşturulan TSQL.

MS mühendislerinin SQL sunucusunun nasıl çalıştığını bildiğini düşünmek istiyorum ve kullandığınız SSMS'nin sürümünü kullanarak çalışabileceğiniz tüm öğeler üzerinde çalışan TSQL üretecek, bu nedenle çok çeşitli yayınlarda, mevcut ve geleceği.

Ve unutmayın, sadece kopyalamayın, anlamaya çalışın, aksi takdirde yanlış çözümle karşılaşabilirsiniz.

Walter


2

Bu yaklaşımlar, orijinal soruda verilen örnek (ler) gibi tüm tablolarla ve sayılarıyla dinamik olarak bir ifade oluşturmak için dize birleştirmeyi kullanır:

          SELECT COUNT(*) AS Count,'[dbo].[tbl1]' AS TableName FROM [dbo].[tbl1]
UNION ALL SELECT COUNT(*) AS Count,'[dbo].[tbl2]' AS TableName FROM [dbo].[tbl2]
UNION ALL SELECT...

Son olarak bu EXEC:

DECLARE @cmd VARCHAR(MAX)=STUFF(
                    (
                        SELECT 'UNION ALL SELECT COUNT(*) AS Count,''' 
                              + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME) 
                              + ''' AS TableName FROM ' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME)
                        FROM INFORMATION_SCHEMA.TABLES AS t
                        WHERE TABLE_TYPE='BASE TABLE'
                        FOR XML PATH('')
                    ),1,10,'');
EXEC(@cmd);

Bu çözüm şema adını içerir (ki bu yararlı olabilir)
gordon613


1

Akla ilk gelen şey sp_msForEachTable kullanmaktı

exec sp_msforeachtable 'select count(*) from ?'

ancak tablo adlarını listelemediğinden,

exec sp_msforeachtable 'select parsename(''?'', 1),  count(*) from ?'

Burada sorun veritabanı 100'den fazla tablo varsa aşağıdaki hata iletisini alırsınız:

Sorgu, sonuç tablosunda görüntülenebilecek maksimum sonuç kümesi sayısını aştı. Izgarada yalnızca ilk 100 sonuç kümesi görüntülenir.

Böylece sonuçları depolamak için tablo değişkeni kullandım

declare @stats table (n sysname, c int)
insert into @stats
    exec sp_msforeachtable 'select parsename(''?'', 1),  count(*) from ?'
select 
    * 
from @stats
order by c desc

1

Kabul cevap Azure SQL benim için işe yaramadı, burada bir süper hızlı ve tam olarak ne istediğini demedin:

select t.name, s.row_count
from sys.tables t
join sys.dm_db_partition_stats s
  ON t.object_id = s.object_id
    and t.type_desc = 'USER_TABLE'
    and t.name not like '%dss%'
    and s.index_id = 1
order by s.row_count desc

1

Bu sql betiği, seçilen bir veritabanındaki her tablonun şemasını, tablo adını ve satır sayısını verir:

SELECT SCHEMA_NAME(schema_id) AS [SchemaName],
[Tables].name AS [TableName],
SUM([Partitions].[rows]) AS [TotalRowCount]
FROM sys.tables AS [Tables]
JOIN sys.partitions AS [Partitions]
ON [Tables].[object_id] = [Partitions].[object_id]
AND [Partitions].index_id IN ( 0, 1 )
-- WHERE [Tables].name = N'name of the table'
GROUP BY SCHEMA_NAME(schema_id), [Tables].name
order by [TotalRowCount] desc

Ref: https://blog.sqlauthority.com/2017/05/24/sql-server-find-row-count-every-table-database-efficiently/

Bunu yapmanın başka bir yolu:

SELECT  o.NAME TABLENAME,
  i.rowcnt 
FROM sysindexes AS i
  INNER JOIN sysobjects AS o ON i.id = o.id 
WHERE i.indid < 2  AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0
ORDER BY i.rowcnt desc

0

Bence en kısa, en hızlı ve en basit yol:

SELECT
    object_name(object_id) AS [Table],
    SUM(row_count) AS [Count]
FROM
    sys.dm_db_partition_stats
WHERE
    --object_schema_name(object_id) = 'dbo' AND 
    index_id < 2
GROUP BY
    object_id

0

Bunu deneyebilirsiniz:

SELECT  OBJECT_SCHEMA_NAME(ps.object_Id) AS [schemaname],
        OBJECT_NAME(ps.object_id) AS [tablename],
        row_count AS [rows]
FROM sys.dm_db_partition_stats ps
WHERE OBJECT_SCHEMA_NAME(ps.object_Id) <> 'sys' AND ps.index_id < 2
ORDER BY 
        OBJECT_SCHEMA_NAME(ps.object_Id),
        OBJECT_NAME(ps.object_id)

0
USE DatabaseName
CREATE TABLE #counts
(
    table_name varchar(255),
    row_count int
)

EXEC sp_MSForEachTable @command1='INSERT #counts (table_name, row_count) SELECT ''?'', COUNT(*) FROM ?'
SELECT table_name, row_count FROM #counts ORDER BY table_name, row_count DESC
DROP TABLE #counts

0

Bu sorudan: /dba/114958/list-all-tables-from-all-user-databases/230411#230411

@Aaron Bertrand tarafından sağlanan ve tüm veritabanlarını ve tüm tabloları listeleyen yanıta kayıt sayısı ekledim.

DECLARE @src NVARCHAR(MAX), @sql NVARCHAR(MAX);

SELECT @sql = N'', @src = N' UNION ALL 
SELECT ''$d'' as ''database'', 
    s.name COLLATE SQL_Latin1_General_CP1_CI_AI as ''schema'',
    t.name COLLATE SQL_Latin1_General_CP1_CI_AI as ''table'' ,
    ind.rows as record_count
  FROM [$d].sys.schemas AS s
  INNER JOIN [$d].sys.tables AS t ON s.[schema_id] = t.[schema_id]
  INNER JOIN [$d].sys.sysindexes AS ind ON t.[object_id] = ind.[id]
  where ind.indid < 2';

SELECT @sql = @sql + REPLACE(@src, '$d', name)
  FROM sys.databases
  WHERE database_id > 4
    AND [state] = 0
    AND HAS_DBACCESS(name) = 1;

SET @sql = STUFF(@sql, 1, 10, CHAR(13) + CHAR(10));

PRINT @sql;
--EXEC sys.sp_executesql @sql;

0

Tüm tablo kaydı sayılarını bir tabloya almak için bu kod parçasını kopyalayabilir, geçmiş ve yürütebilirsiniz. Not: Kod talimatlarla yorumlanmıştır

create procedure RowCountsPro
as
begin
--drop the table if exist on each exicution
IF OBJECT_ID (N'dbo.RowCounts', N'U') IS NOT NULL 
DROP TABLE dbo.RowCounts;
-- creating new table
CREATE TABLE RowCounts 
( [TableName]            VARCHAR(150)
, [RowCount]               INT
, [Reserved]                 NVARCHAR(50)
, [Data]                        NVARCHAR(50)
, [Index_Size]               NVARCHAR(50)
, [UnUsed]                   NVARCHAR(50))
--inserting all records
INSERT INTO RowCounts([TableName], [RowCount],[Reserved],[Data],[Index_Size],[UnUsed])
--  "sp_MSforeachtable" System Procedure, 'sp_spaceused "?"' param to get records and resources used
EXEC sp_MSforeachtable 'sp_spaceused "?"' 
-- selecting data and returning a table of data
SELECT [TableName], [RowCount],[Reserved],[Data],[Index_Size],[UnUsed]
FROM RowCounts
ORDER BY [TableName]
end

Bu kodu test ettim ve SQL Server 2014'te iyi çalışıyor.


0

Benim için neyin işe yaradığını paylaşmak istiyorum

SELECT
      QUOTENAME(SCHEMA_NAME(sOBJ.schema_id)) + '.' + QUOTENAME(sOBJ.name) AS [TableName]
      , SUM(sdmvPTNS.row_count) AS [RowCount]
FROM
      sys.objects AS sOBJ
      INNER JOIN sys.dm_db_partition_stats AS sdmvPTNS
            ON sOBJ.object_id = sdmvPTNS.object_id
WHERE 
      sOBJ.type = 'U'
      AND sOBJ.is_ms_shipped = 0x0
      AND sdmvPTNS.index_id < 2
GROUP BY
      sOBJ.schema_id
      , sOBJ.name
ORDER BY [TableName]
GO

Veritabanı Azure'da barındırılıyor ve nihai sonuç: resim açıklamasını buraya girin

Kredi bilgileri: https://www.mssqltips.com/sqlservertip/2537/sql-server-row-count-for-all-tables-in-a-database/


-1

MySQL> 4.x kullanıyorsanız bunu kullanabilirsiniz:

select TABLE_NAME, TABLE_ROWS from information_schema.TABLES where TABLE_SCHEMA="test";

Bazı depolama motorları için TABLE_ROWS'un bir tahmin olduğunu unutmayın.


6
Microsoft SQL Server olan yazısında (etiket olarak) "sql-server" dan bahsetti
marc_s

-1
select T.object_id, T.name, I.indid, I.rows 
  from Sys.tables T 
  left join Sys.sysindexes I 
    on (I.id = T.object_id and (indid =1 or indid =0 ))
 where T.type='U'

İşte indid=1bir KÜMELENMİŞ dizin ve indid=0bir HEAP


4
Merhaba ve Stack Overflow'a hoş geldiniz. Bu cevap zaten bir yaşında olanla aynı ... tekrar göndermeye gerek yoktu.
Ben
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.