Verschiedene Methoden zum Zählen aller Tabellenzeilen in SQL Server

Es gibt mehrere Ansätze, um die Zeilenanzahl aller Tabellen einer Datenbank zu ermitteln. Die Methoden unterscheiden sich in GenauigkeitGeschwindigkeit und Aufwand. Im Folgenden werden die gängigsten Möglichkeiten vorgestellt.


1. Über sys.partitions (schnell, aber potenziell ungenau)

Verwendet die Systemkatalogsicht sys.partitions, die für jede Tabelle die Anzahl der Zeilen pro Partition speichert. Die Werte werden asynchron aktualisiert (z. B. bei Indexrebuilds oder Statistikupdates) und können bei häufig geänderten Tabellen abweichen.

SELECT 
    OBJECT_NAME(p.object_id) AS TableName,
    SUM(p.rows) AS RowCount
FROM sys.partitions p
WHERE p.index_id IN (0, 1)  -- 0 = Heap, 1 = Clustered Index
GROUP BY p.object_id
ORDER BY TableName;

Vorteile: sehr schnell, keine Sperren, keine Belastung der Datenbank.
Nachteile: nicht immer genau (Differenzen möglich), benötigt VIEW DATABASE STATE-Berechtigung.

 

2. Über sys.dm_db_partition_stats (empfohlen für Genauigkeit)

Diese dynamische Verwaltungssicht liefert tatsächliche Zeilenanzahlen aus dem Speicher-Engine, ist aber etwas langsamer als sys.partitions.

SELECT 
    OBJECT_NAME(s.object_id) AS TableName,
    SUM(s.row_count) AS RowCount
FROM sys.dm_db_partition_stats s
WHERE s.index_id IN (0, 1)
GROUP BY s.object_id
ORDER BY TableName;

Vorteile: genau, schnell (meist Millisekunden), keine Tabellensperren.
Nachteile: benötigt VIEW DATABASE STATE; bei sehr vielen Partitionen etwas höhere Latenz.

 

3. Dynamisches SQL mit COUNT(*) für jede Tabelle (langsam, aber 100 % genau)

Führt für jede Tabelle ein SELECT COUNT(*) aus – das ist die exakteste Methode, aber auch die langsamste, da jede Tabelle vollständig gescannt wird.

DECLARE @sql NVARCHAR(MAX) = '';

SELECT @sql = STRING_AGG(
    'SELECT ''' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + ''' AS TableName, COUNT(*) AS RowCount FROM ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name),
    ' UNION ALL '
)
FROM sys.tables;

EXEC sp_executesql @sql;

Vorteile: 100 % genaue Werte (auch bei laufenden Änderungen).
Nachteile: extrem langsam bei großen Tabellen, hohe E/A- und CPU-Last, kann Sperren verursachen.

4. Mit der unvollständigen Systemprozedur sp_MSforeachtable

Diese undocumented Systemprozedur führt einen Befehl für jede Tabelle aus. Sie ist einfach zu schreiben, aber nicht offiziell unterstützt und kann bei bestimmten Tabellennamen (mit Sonderzeichen) versagen.

CREATE TABLE #RowCounts (TableName sysname, RowCount INT);

EXEC sp_MSforeachtable 
    'INSERT INTO #RowCounts (TableName, RowCount) 
     SELECT ''?'', COUNT(*) FROM ?';

SELECT * FROM #RowCounts ORDER BY TableName;
DROP TABLE #RowCounts;

 

5. Cursor oder While‑Schleife mit COUNT(*)

Alternative zu dynamischem SQL: Eine Schleife über alle Tabellen, die einzeln gezählt werden. Ähnlich langsam wie Methode 3, aber mit besserer Fehlerkontrolle.

 

DECLARE @TableName sysname, @SchemaName sysname, @RowCount BIGINT;
DECLARE @sql NVARCHAR(500);

DECLARE cur CURSOR FOR
    SELECT SCHEMA_NAME(schema_id), name FROM sys.tables;

CREATE TABLE #Results (TableName sysname, RowCount BIGINT);

OPEN cur;
FETCH NEXT FROM cur INTO @SchemaName, @TableName;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = N'SELECT @cnt = COUNT(*) FROM ' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName);
    EXEC sp_executesql @sql, N'@cnt BIGINT OUTPUT', @cnt = @RowCount OUTPUT;
    INSERT INTO #Results VALUES (@SchemaName + '.' + @TableName, @RowCount);
    FETCH NEXT FROM cur INTO @SchemaName, @TableName;
END;

CLOSE cur;
DEALLOCATE cur;

SELECT * FROM #Results ORDER BY TableName;
DROP TABLE #Results;

Vorteile: genau, volle Kontrolle, gute Fehlerbehandlung möglich.
Nachteile: sehr langsam, Cursor Overhead, tabellenweise sequentielle Scans.