Truy vấn để liệt kê số lượng bản ghi trong mỗi bảng trong cơ sở dữ liệu


196

Cách liệt kê số lượng hàng của từng bảng trong cơ sở dữ liệu. Một số tương đương với

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

Tôi sẽ đăng một giải pháp nhưng các cách tiếp cận khác đều được chào đón

Câu trả lời:


311

Nếu bạn đang sử dụng SQL Server 2005 trở lên, bạn cũng có thể sử dụng:

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) 

Theo tôi, nó dễ xử lý hơn sp_msforeachtableđầu ra.


1
Có ai biết tại sao nó lại lọc ra các bảng có tên bắt đầu bằng "dt" không? Tôi đã xem kịch bản này trên mạng, nhưng không có lời giải thích nào về tiêu chí đó. Có phải tất cả chúng ta đều bị troll?
Skaue

6
@Skaue: nếu bạn cài đặt chức năng "Sơ đồ cơ sở dữ liệu" vào cơ sở dữ liệu của bạn, thì bạn sẽ có một số bảng như dtPropertiesvậy; vì đó là các bảng "hệ thống", tôi không muốn báo cáo về các bảng đó.
marc_s

1
Khả năng của tiền tố tablename với tên lược đồ trong tập lệnh này?
gh0

Vì một số lý do, truy vấn này không trả về tất cả các bảng. Tôi có 382 bảng trong cơ sở dữ liệu. Nhưng truy vấn này chỉ trả về 270 hàng (thông tin bảng). Sau khi loại bỏ điều kiện nơi tôi nhận được 302 hàng. Có phải do thực tế là một số thông tin bảng bị thiếu trong một trong các bảng SYS nên các phép nối được bỏ qua chúng. Cơ sở dữ liệu không chứa bất kỳ bảng hệ thống.
Ankesh Kushwah

Đây là làm việc. bạn có thể sửa đổi nó để so sánh hai cơ sở dữ liệu.
sanjeewa

107

Một đoạn mã tôi tìm thấy tại http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=21021 đã giúp tôi:

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
Tôi thích giải pháp này, mặc dù tôi sử dụng JOINcú phápfrom sysobjects t inner join sysindexes i on i.id = t.id and i.indid in (0,1) where t.xtype = 'U'
Shnugo

Tôi cũng thích sử dụng các câu lệnh THAM GIA nhưng đã đăng đoạn mã khi tôi tìm thấy nó. :)
Erik Anderson

32

Để có được thông tin đó trong SQL Management Studio, nhấp chuột phải vào cơ sở dữ liệu, sau đó chọn Báo cáo -> Báo cáo chuẩn -> Sử dụng đĩa theo bảng.


6
Cách tiếp cận không bị khuất phục, điều này nhanh chóng tạo ra một báo cáo có thể sắp xếp hiển thị # hàng và kích thước của dữ liệu.
xương sống

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
Truy vấn này sẽ trả về kết quả hàng cho mỗi chỉ mục trên mỗi bảng. Thêm WHERE P.INDEX_ID IN (0,1) để giới hạn kết quả trả về được đặt thành đống hoặc chỉ mục cụm khi thích hợp.
Rasmus Remmer Bielidt

6

Như đã thấy ở đây, điều này sẽ trả về số đếm chính xác, trong đó các phương thức sử dụng bảng dữ liệu meta sẽ chỉ trả về ước tính.

    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

Vì vậy, nó có vẻ như là một sự thỏa hiệp của việc sử dụng kho lưu trữ không có giấy tờ Proc sp_msForEachTable so với việc sử dụng các bảng hệ thống với thông tin đôi khi không cập nhật nhất. +1 và cảm ơn vì liên kết
kristof

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

Đầu ra:

nhập mô tả hình ảnh ở đây


Tôi cần một cái gì đó cho Sql Server 2000. Điều này đã làm việc. Cảm ơn!
Alrekr

3

May mắn thay, studio quản lý SQL Server cung cấp cho bạn một gợi ý về cách thực hiện việc này. Làm cái này,

  1. bắt đầu theo dõi SQL Server và mở hoạt động bạn đang thực hiện (lọc theo ID đăng nhập của bạn nếu bạn không đơn độc và đặt Tên ứng dụng thành Microsoft SQL Server Management Studio), tạm dừng theo dõi và loại bỏ mọi kết quả bạn đã ghi lại cho đến bây giờ;
  2. Sau đó, nhấp chuột phải vào bảng và chọn thuộc tính từ menu bật lên;
  3. bắt đầu lại dấu vết;
  4. Bây giờ trong SQL Server Management studio chọn mục thuộc tính lưu trữ ở bên trái;

Tạm dừng theo dõi và xem TSQL được tạo bởi microsoft.

Trong truy vấn có lẽ cuối cùng, bạn sẽ thấy một câu lệnh bắt đầu bằng exec sp_executesql N'SELECT

Khi bạn sao chép mã được thực thi vào visual studio, bạn sẽ thấy rằng mã này tạo ra tất cả dữ liệu mà các kỹ sư tại microsoft sử dụng để điền vào cửa sổ thuộc tính.

Khi bạn thực hiện các sửa đổi vừa phải cho truy vấn đó, bạn sẽ nhận được một cái gì đó như thế này:

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

Bây giờ truy vấn không hoàn hảo và bạn có thể cập nhật nó để đáp ứng các câu hỏi khác mà bạn có thể có, vấn đề là, bạn có thể sử dụng kiến ​​thức về microsoft để có được hầu hết các câu hỏi bạn có bằng cách thực hiện dữ liệu bạn quan tâm và theo dõi TSQL được tạo bằng profiler.

Tôi muốn nghĩ rằng các kỹ sư của MS biết máy chủ SQL hoạt động như thế nào và nó sẽ tạo ra TSQL hoạt động trên tất cả các mục bạn có thể làm việc bằng cách sử dụng phiên bản trên SSMS mà bạn đang sử dụng vì vậy nó khá tốt trên các phiên bản phát hành lớn, hiện tại và Tương lai.

Và hãy nhớ, đừng chỉ sao chép, hãy cố gắng hiểu nó cũng như bạn có thể sẽ gặp phải giải pháp sai.

Walter


2

Cách tiếp cận này sử dụng nối chuỗi để tạo ra một câu lệnh với tất cả các bảng và số đếm của chúng một cách linh hoạt, giống như (các) ví dụ được đưa ra trong câu hỏi ban đầu:

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

Cuối cùng, điều này được thực hiện với 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);

lưu ý rằng giải pháp này bao gồm tên của lược đồ (có thể hữu ích)
gordon613


1

Điều đầu tiên tôi nghĩ đến là sử dụng sp_msForEachTable

exec sp_msforeachtable 'select count(*) from ?'

tuy nhiên không liệt kê tên bảng, vì vậy nó có thể được mở rộng thành

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

Vấn đề ở đây là nếu cơ sở dữ liệu có hơn 100 bảng, bạn sẽ nhận được thông báo lỗi sau:

Truy vấn đã vượt quá số lượng tập kết quả tối đa có thể được hiển thị trong lưới kết quả. Chỉ 100 bộ kết quả đầu tiên được hiển thị trong lưới.

Vì vậy, tôi đã kết thúc bằng cách sử dụng biến bảng để lưu trữ kết quả

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

Câu trả lời được chấp nhận không làm việc cho tôi trên Azure SQL, đây là một trong đó đã làm, đó là siêu nhanh và đã làm chính xác những gì tôi muốn:

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

Kịch bản lệnh sql này cung cấp lược đồ, tên bảng và số hàng của mỗi bảng trong cơ sở dữ liệu được chọn:

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

Tham khảo: https://blog.sqlauthority.com/2017/05/24/sql-server-find-row-count-every-table-database- hiệu quả /

Một cách khác để làm điều này:

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

Tôi nghĩ rằng cách ngắn nhất, nhanh nhất và đơn giản nhất sẽ là:

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

Bạn có thể thử điều này:

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

Từ câu hỏi này: /dba/114958/list-all-tables-from-all-user-database/230411#230411

Tôi đã thêm số lượng bản ghi vào câu trả lời được cung cấp bởi @Aaron Bertrand liệt kê tất cả các cơ sở dữ liệu và tất cả các bảng.

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

Bạn có thể sao chép, quá khứ và thực thi đoạn mã này để lấy tất cả số lượng bản ghi bảng vào một bảng. Lưu ý: Mã được nhận xét với hướng dẫn

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

Tôi đã kiểm tra mã này và nó hoạt động tốt trên SQL Server 2014.


0

Tôi muốn chia sẻ những gì làm việc cho tôi

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

Cơ sở dữ liệu được lưu trữ trong Azure và kết quả cuối cùng là: nhập mô tả hình ảnh ở đây

Tín dụng: https://www.mssqltips.com/sqlservertip/2537/sql-server-row-count-for-all-tables-in-a-database/


-1

Nếu bạn sử dụng MySQL> 4.x, bạn có thể sử dụng:

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

Hãy nhớ rằng đối với một số công cụ lưu trữ, TABLE_lawS là một xấp xỉ.


6
ông đã đề cập đến "máy chủ sql" trong bài đăng của mình (dưới dạng thẻ) là 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'

Ở đây indid=1có nghĩa là một chỉ số CLUSTERED và indid=0là một HEAP


4
Xin chào và chào mừng đến với Stack Overflow. Câu trả lời này giống hệt với câu trả lời đã được một năm tuổi ... không cần phải đăng lại.
Ben
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.