Abfrage, um die Anzahl der Datensätze in jeder Tabelle in einer Datenbank aufzulisten

196

Auflisten der Zeilenanzahl jeder Tabelle in der Datenbank. Ein Äquivalent von

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

Ich werde eine Lösung veröffentlichen, aber andere Ansätze sind willkommen

kristof
quelle

Antworten:

310

Wenn Sie SQL Server 2005 und höher verwenden, können Sie auch Folgendes verwenden:

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) 

Meiner Meinung nach ist es einfacher zu handhaben als die sp_msforeachtableAusgabe.

marc_s
quelle
1
Irgendeine Idee, warum Tabellen mit einem Namen herausgefiltert werden, der mit "dt" beginnt? Ich habe dieses Skript im ganzen Netz gesehen, aber keine Erklärung zu diesen Kriterien. Werden wir alle getrollt?
Skaue
6
@Skaue: Wenn Sie die Funktion "Datenbankdiagramm" in einer Ihrer Datenbanken installieren, haben Sie einige Tabellen wie dtPropertiesund so weiter. Da es sich um "System" -Tabellen handelt, möchte ich nicht darüber berichten.
marc_s
1
Möglichkeit, dem Tabellennamen in diesem Skript den Schemanamen voranzustellen?
Gh0st
Aus irgendeinem Grund gibt diese Abfrage nicht alle Tabellen zurück. Ich habe 382 Tabellen in einer Datenbank. Diese Abfrage gibt jedoch nur 270 Zeilen (Tabelleninformationen) zurück. Nach dem Entfernen der where-Bedingung erhalte ich 302 Zeilen. Liegt es an der Tatsache, dass einige der Tabelleninformationen in einer der SYS-Tabellen fehlen, sodass die Verknüpfungen sie weglassen? Die Datenbank enthält keine Systemtabellen.
Ankesh Kushwah
Das funktioniert. können Sie es ändern, um zwei Datenbanken zu vergleichen.
Sanjeewa
107

Ein Ausschnitt, den ich unter http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=21021 gefunden habe und der mir geholfen hat:

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;
Erik Anderson
quelle
5
Ich mag diese Lösung, obwohl ich die JOINSyntax verwenden würdefrom sysobjects t inner join sysindexes i on i.id = t.id and i.indid in (0,1) where t.xtype = 'U'
Shnugo
Ich bevorzuge auch die Verwendung von JOIN-Anweisungen, habe aber das Code-Snippet so gepostet, wie ich es gefunden habe. :)
Erik Anderson
32

Um diese Informationen in SQL Management Studio abzurufen, klicken Sie mit der rechten Maustaste auf die Datenbank und wählen Sie Berichte -> Standardberichte -> Datenträgernutzung nach Tabelle.

petra
quelle
6
Unterschätzter Ansatz, der schnell einen sortierbaren Bericht generiert, der # Zeilen und Datengröße anzeigt.
Knochen
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;
ANG
quelle
3
Diese Abfrage gibt ein Zeilenergebnis für jeden Index für jede Tabelle zurück. Fügen Sie eine WHERE P.INDEX_ID IN (0,1) hinzu, um die Rückgabeergebnismenge nur gegebenenfalls auf Heaps oder Clustered-Indizes zu beschränken.
Rasmus Remmer Bielidt
6

Wie hier zu sehen ist, werden korrekte Zählungen zurückgegeben, wobei Methoden, die die Metadatentabellen verwenden, nur Schätzungen zurückgeben.

    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
KM.
quelle
Es klingt also wie ein Kompromiss zwischen der Verwendung von undokumentiertem Speicher proc sp_msForEachTable und der Verwendung von Systemtabellen mit manchmal nicht den aktuellsten Informationen. +1 und danke für den Link
kristof
3
sp_MSForEachTable 'DECLARE @t AS VARCHAR(MAX); 
SELECT @t = CAST(COUNT(1) as VARCHAR(MAX)) 
+ CHAR(9) + CHAR(9) + ''?'' FROM ? ; PRINT @t'

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Rikin Patel
quelle
Ich brauchte etwas für SQL Server 2000. Das hat funktioniert. Vielen Dank!
Alrekr
3

Zum Glück gibt Ihnen SQL Server Management Studio einen Hinweis dazu. Mach das,

  1. Starten Sie eine SQL Server-Ablaufverfolgung und öffnen Sie die von Ihnen ausgeführte Aktivität (filtern Sie nach Ihrer Anmelde-ID, wenn Sie nicht allein sind, und setzen Sie den Anwendungsnamen auf Microsoft SQL Server Management Studio), halten Sie die Ablaufverfolgung an und verwerfen Sie alle bisher aufgezeichneten Ergebnisse.
  2. Klicken Sie dann mit der rechten Maustaste auf eine Tabelle und wählen Sie die Eigenschaft aus dem Einblendmenü aus.
  3. Starten Sie die Ablaufverfolgung erneut.
  4. Wählen Sie nun in SQL Server Management Studio das Speichereigenschaftselement links aus.

Halten Sie den Trace an und sehen Sie sich an, was TSQL von Microsoft generiert.

In der wahrscheinlich letzten Abfrage sehen Sie eine Anweisung, die mit beginnt exec sp_executesql N'SELECT

Wenn Sie den ausgeführten Code nach Visual Studio kopieren, werden Sie feststellen, dass dieser Code alle Daten generiert, die die Ingenieure von Microsoft zum Auffüllen des Eigenschaftsfensters verwendet haben.

Wenn Sie mäßige Änderungen an dieser Abfrage vornehmen, erhalten Sie Folgendes:

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

Jetzt ist die Abfrage nicht perfekt und Sie können sie aktualisieren, um andere Fragen zu beantworten. Der Punkt ist, dass Sie das Wissen von Microsoft nutzen können, um zu den meisten Fragen zu gelangen, die Sie haben, indem Sie die Daten ausführen, an denen Sie interessiert sind, und diese verfolgen die mit dem Profiler generierte TSQL.

Ich denke gerne, dass MS-Ingenieure wissen, wie SQL Server funktioniert, und dass TSQL generiert wird, das für alle Elemente funktioniert, mit denen Sie mit der von Ihnen verwendeten SSMS-Version arbeiten können. Daher ist es für eine Vielzahl von Versionen, die aktuell und aktuell sind, recht gut Zukunft.

Und denken Sie daran, kopieren Sie nicht nur, sondern versuchen Sie es auch zu verstehen, sonst könnten Sie die falsche Lösung finden.

Walter

Walter Verhoeven
quelle
2

Bei diesem Ansatz wird die Verkettung von Zeichenfolgen verwendet, um eine Anweisung mit allen Tabellen und deren Anzahl dynamisch zu erstellen, wie in den Beispielen in der ursprünglichen Frage:

          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...

Schließlich wird dies ausgeführt mit 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);
Shnugo
quelle
Beachten Sie, dass diese Lösung den Namen des Schemas enthält (was nützlich sein kann)
gordon613
1

Das erste, was mir in den Sinn kam, war die Verwendung von sp_msForEachTable

exec sp_msforeachtable 'select count(*) from ?'

Die Tabellennamen werden jedoch nicht aufgelistet, sodass sie auf erweitert werden können

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

Das Problem hierbei ist, dass bei einer Datenbank mit mehr als 100 Tabellen die folgende Fehlermeldung angezeigt wird:

Die Abfrage hat die maximale Anzahl von Ergebnismengen überschritten, die im Ergebnisraster angezeigt werden können. Im Raster werden nur die ersten 100 Ergebnismengen angezeigt.

Also habe ich die Tabellenvariable verwendet, um die Ergebnisse zu speichern

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
kristof
quelle
1

Die akzeptierte Antwort hat in Azure SQL bei mir nicht funktioniert. Hier ist eine , die sehr schnell funktioniert und genau das getan hat, was ich wollte:

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
UnionP
quelle
1

Dieses SQL-Skript gibt das Schema, den Tabellennamen und die Zeilenanzahl jeder Tabelle in einer ausgewählten Datenbank an:

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/

Ein anderer Weg, dies zu tun:

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
rchacko
quelle
0

Ich denke, der kürzeste, schnellste und einfachste Weg wäre:

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
sotn
quelle
0

Sie könnten dies versuchen:

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)
Steve Ford
quelle
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
foluis
quelle
0

Aus dieser Frage: /dba/114958/list-all-tables-from-all-user-databases/230411#230411

Ich habe der Antwort von @Aaron Bertrand, die alle Datenbanken und alle Tabellen auflistet, die Anzahl der Datensätze hinzugefügt.

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;
Jeremy F.
quelle
0

Sie können diesen Code kopieren, einfügen und ausführen, um alle Tabellendatensätze in eine Tabelle aufzunehmen. Hinweis: Der Code wird mit Anweisungen kommentiert

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

Ich habe diesen Code getestet und er funktioniert unter SQL Server 2014 einwandfrei.

Mujtaba
quelle
0

Ich möchte mitteilen, was für mich funktioniert

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

Die Datenbank wird in Azure gehostet und das Endergebnis lautet: Geben Sie hier die Bildbeschreibung ein

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

d.danailov
quelle
-1

Wenn Sie MySQL> 4.x verwenden, können Sie Folgendes verwenden:

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

Beachten Sie, dass TABLE_ROWS für einige Speicher-Engines eine Annäherung ist.

David Poblador i Garcia
quelle
6
Er erwähnte "SQL-Server" in seinem Beitrag (als Tag), der Microsoft SQL Server ist
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'

Hier indid=1bedeutet ein CLUSTERED-Index und indid=0ist ein HEAP

Jyoti Prashad Chaulkara
quelle
4
Hallo und willkommen bei Stack Overflow. Diese Antwort ist identisch mit einer, die bereits ein Jahr alt ist ... es war nicht nötig, sie erneut zu posten.
Ben