我正在寻找一个SQL脚本,可用于确定是否有任何数据(即行计数)在给定数据库的任何表。

这样做的目的是在存在任何行(在任何数据库中)的情况下重新具体化数据库。

这里所说的数据库是Microsoft SQL SERVER。

谁能建议一个示例脚本?


当前回答

下面的SQL语句将得到数据库中所有表的行数:

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

输出将是一个表列表及其行数。

如果你只想要整个数据库的总行数,追加:

SELECT SUM(row_count) AS total_row_count FROM #counts

将获得整个数据库中总行数的单个值。

其他回答

如果您希望通过传递时间和资源来计数(*)您的300万行表。试试Kendal Van Dyke的SQL SERVER Central。


使用sysindexes进行行计数 如果你在使用SQL 2000,你需要像这样使用sysindexes:

-- Shows all user tables and row counts for the current database 
-- Remove OBJECTPROPERTY function call to include system objects 
SELECT o.NAME,
  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 o.NAME

如果你正在使用SQL 2005或2008查询sysindexes仍然可以工作,但微软建议sysindexes可能会在SQL Server的未来版本中被删除,因此作为一个良好的实践,你应该使用dmv,如下所示:

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name,
  ddps.row_count 
FROM sys.indexes AS i
  INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
  INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID
  AND i.index_id = ddps.index_id 
WHERE i.index_id < 2  AND o.is_ms_shipped = 0 ORDER BY o.NAME 

短而甜

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

输出:

不要使用SELECT COUNT(*) FROM TABLENAME,因为这是一个资源密集型操作。应该使用SQL Server动态管理视图或系统目录来获取数据库中所有表的行数信息。

我会对弗雷德里克的方案做些小改动。我将使用sp_spaceused系统存储过程,它还将包括数据和索引大小。


declare c_tables cursor fast_forward for 
select table_name from information_schema.tables 

open c_tables 
declare @tablename varchar(255) 
declare @stmt nvarchar(2000) 
declare @rowcount int 
fetch next from c_tables into @tablename 

while @@fetch_status = 0 
begin 

    select @stmt = 'sp_spaceused ' + @tablename 

    exec sp_executesql @stmt

    fetch next from c_tables into @tablename 

end 

close c_tables 
deallocate c_tables 

我觉得这个看起来比其他的好。

USE  [enter your db name here]
GO

SELECT      SCHEMA_NAME(A.schema_id) + '.' +
        --A.Name, SUM(B.rows) AS 'RowCount'  Use AVG instead of SUM
          A.Name, AVG(B.rows) AS 'RowCount'
FROM        sys.objects A
INNER JOIN sys.partitions B ON A.object_id = B.object_id
WHERE       A.type = 'U'
GROUP BY    A.schema_id, A.Name
GO