Запит на перелік кількості записів у кожній таблиці бази даних


199

Як перелічити кількість рядків кожної таблиці в базі даних. Якийсь еквівалент

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

Я опублікую рішення, але інші підходи вітаються

Відповіді:


314

Якщо ви використовуєте SQL Server 2005 і новіші версії, ви також можете скористатися цим:

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) 

На мою думку, це легше впоратися, ніж sp_msforeachtableвихід.


1
Будь-яка ідея, чому вона фільтрує таблиці з назвою, що починається з "dt"? Я бачив цей сценарій по всій мережі, але жодних пояснень за цими критеріями. Ми всі проходимо навчання?
Скауе

6
@Skaue: якщо ви встановите функціонал "Діаграма баз даних" у вашу базу даних, ви матимете такі таблиці, як dtPropertiesтощо; оскільки це "системні" таблиці, я не хочу повідомляти про них.
marc_s

1
Можливість префіксації імені таблиці з назвою схеми в цьому сценарії?
gh0st

Чомусь цей запит не повертає всіх таблиць. У мене в базі даних 382 таблиці. Але цей запит повертає лише 270 рядків (інформація таблиці). Після видалення умови, де я отримую 302 рядки. Це пов'язано з тим, що в одній із таблиць SYS відсутня інформація про деякі таблиці, тому з'єднання їх опускають. База даних не містить жодних системних таблиць.
Ankesh Kushwah

Це працює. чи можете ви змінити його для порівняння двох баз даних.
sanjeewa

107

Фрагмент, який я знайшов на веб- сайті http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=21021, який допоміг мені:

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
Мені подобається це рішення, хоча я б використовував JOINсинтаксисfrom sysobjects t inner join sysindexes i on i.id = t.id and i.indid in (0,1) where t.xtype = 'U'
Shnugo

Я також вважаю за краще використовувати заяви JOIN, але розмістив фрагмент коду, коли я його знайшов. :)
Ерік Андерсон

32

Щоб отримати цю інформацію в SQL Management Studio, клацніть правою кнопкою миші на базі даних, а потім виберіть Звіти -> Стандартні звіти -> Використання диска за таблицею.


6
Занижений підхід, це швидко створює сортовий звіт, що показує # рядки та розмір даних.
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
Цей Запит поверне результат рядків для кожного індексу в кожній таблиці. Додайте WHERE P.INDEX_ID IN (0,1), щоб обмежити результат повернення, встановлений на купи або кластерні індекси, лише там, де це доречно.
Расмус Реммер Білідт

6

Як бачимо тут, це поверне правильні підрахунки, коли методи, що використовують метадані таблиці, повертають лише оцінки.

    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

Таким чином, це здається компромісом використання незадокументованого stor proc sp_msForEachTable vs використання системних таблиць з часом не найбільш актуальною інформацією. +1 і спасибі за посилання
kristof

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

Вихід:

введіть тут опис зображення


Мені потрібно щось для Sql Server 2000. Це спрацювало. Дякую!
Alrekr

3

На щастя, студія управління SQL Server дає вам підказку, як це зробити. Зробити це,

  1. запустити трасування SQL Server та відкрити активність, яку ти робиш (відфільтруй свій ідентифікатор входу, якщо ти не один, і встановиш ім'я програми на Microsoft SQL Server Management Studio), призупини трасування та відкидай усі результати, записані до цих пір;
  2. Потім клацніть правою кнопкою миші таблицю та виберіть властивість у спливаючому меню;
  3. почати слід знову;
  4. Тепер у студії управління SQL Server виберіть елемент властивості зберігання зліва;

Призупиніть трасування і подивіться, що TSQL генерується мікрософт.

У, ймовірно, останньому запиті ви побачите заяву, починаючи з exec sp_executesql N'SELECT

коли ви скопіюєте виконаний код у візуальну студію, ви помітите, що цей код генерує всі дані, які інженери в Microsoft використовували для заповнення вікна властивості.

коли ви внесете помірні зміни до цього запиту, ви отримаєте щось подібне:

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

Тепер запит не є ідеальним, і ви можете оновити його, щоб відповідати іншим питанням, справа в тому, що ви можете використовувати знання Microsoft, щоб дістатись до більшості запитань, виконавши потрібні вам дані та простежити TSQL, згенерований за допомогою профілера.

Мені хотілося б думати, що інженери MS знають, як працює сервер SQL, і він генерує TSQL, який працює над усіма елементами, з якими можна працювати, використовуючи версію для SSMS, яку ви використовуєте, тому це досить добре для великої кількості випусків, що випускають попередньо, поточну та майбутнє

І пам’ятайте, не просто копіюйте, намагайтеся зрозуміти це, як інакше, можливо, ви отримаєте неправильне рішення.

Вальтер


2

Цей підхід використовує конкатенацію рядків для створення оператора з усіма таблицями та їх підрахунками динамічно, як приклад (и), наведені в оригінальному запитанні:

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

Нарешті це виконується за допомогою 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);

зауважте, що це рішення включає в себе назву схеми (яка може бути корисною)
gordon613


1

Перше, що прийшло в голову, - це використовувати sp_msForEachTable

exec sp_msforeachtable 'select count(*) from ?'

що не перелічує назви таблиць, тому її можна поширити на

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

Проблема тут полягає в тому, що якщо база даних містить більше 100 таблиць, ви отримаєте таке повідомлення про помилку:

Запит перевищив максимальну кількість наборів результатів, які можуть відображатися у сітці результатів. У сітці відображаються лише перші 100 наборів результатів.

Тож я зрештою використовував змінну таблиці для зберігання результатів

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

Прийнятий відповідь не працює для мене на Лазурному SQL, ось один , що зробили, це дуже швидко і зробив саме те , що я хотів:

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

Цей скрипт sql дає схему, ім'я таблиці та кількість рядків кожної таблиці у вибраній базі даних:

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

Довідка: https://blog.sqlauthority.com/2017/05/24/sql-server-find-row-count-every-table-database-efficient/

Ще один спосіб зробити це:

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

Я думаю, що найкоротшим, найшвидшим та найпростішим способом було б:

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

Ви можете спробувати це:

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

З цього питання: /dba/114958/list-all-tables-from-all-user-databases/230411#230411

Я додав підрахунок записів до відповіді, наданої @Aaron Bertrand, у якій перераховані всі бази даних та всі таблиці.

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

Ви можете скопіювати, пропустити та виконати цей фрагмент коду, щоб отримати всі підрахунки таблиць у таблицю. Примітка. Код коментується інструкціями

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

Я перевірив цей код, і він прекрасно працює на SQL Server 2014.


0

Я хочу поділитися тим, що працює на мене

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

База даних розміщується в Azure, і кінцевий результат: введіть тут опис зображення

Кредит: https://www.mssqltips.com/sqlservertip/2537/sql-server-row-count-for-all-tables-in-a-database/


-1

Якщо ви використовуєте MySQL> 4.x, ви можете скористатися цим:

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

Майте на увазі, що для деяких двигунів зберігання даних TABLE_ROWS є наближенням.


6
він згадував "sql-сервер" у своєму дописі (як тег), який є Microsoft SQL Server
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'

Тут indid=1означає CLUSTERED індекс і indid=0є HEAP


4
Привіт, ласкаво просимо до Stack Overflow. Ця відповідь ідентична відповіді, якій вже рік, ... знову не було потреби її публікувати.
Бен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.