답변:
활용 sys.tables
및 sys.partitions
:
select
t.name table_name,
s.name schema_name,
sum(p.rows) total_rows
from
sys.tables t
join sys.schemas s on (t.schema_id = s.schema_id)
join sys.partitions p on (t.object_id = p.object_id)
where p.index_id in (0,1)
group by t.name,s.name
having sum(p.rows) = 0;
분할 된 테이블과 혼동되지 않도록 행 합계를 사용하십시오. Index_ID가 0 또는 1이면 힙 또는 클러스터형 인덱스의 행 수만보고 있음을 의미합니다.
Mike Fal과 Kin이 언급했듯이 시스템 테이블은 친구입니다.
보다 완전한 코드 완성 버전을 위해 다음을 생각해 보았습니다. 데이터베이스의 각 테이블에서 사용하는 총 데이터 공간을 볼 수 있습니다.
USE master;
CREATE DATABASE TestDB;
GO
USE tempdb;
ALTER DATABASE TestDB SET RECOVERY SIMPLE;
GO
USE TestDB;
CREATE TABLE Test1 (
Test1ID INT NOT NULL PRIMARY KEY IDENTITY(1,1)
, TestData nvarchar(255) CONSTRAINT DF_Test1_TestData DEFAULT (NEWID())
);
GO
TRUNCATE TABLE Test1;
SELECT s.name + '.' + t.name AS TableName,
sum(p.rows) AS TotalRows,
SUM(au.data_pages) AS DataPagesUsed
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.partitions p ON t.object_id = p.object_id
INNER JOIN sys.allocation_units au ON p.hobt_id = au.container_id
WHERE au.type = 1 or au.type = 3
AND t.is_ms_shipped = 0
GROUP BY s.name, t.name
ORDER BY SUM(au.data_pages) DESC;
INSERT INTO Test1 DEFAULT VALUES;
SELECT s.name + '.' + t.name AS TableName,
sum(p.rows) AS TotalRows,
SUM(au.data_pages) AS DataPagesUsed
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.partitions p ON t.object_id = p.object_id
INNER JOIN sys.allocation_units au ON p.hobt_id = au.container_id
WHERE au.type = 1 or au.type = 3
AND t.is_ms_shipped = 0
GROUP BY s.name, t.name
ORDER BY SUM(au.data_pages) DESC;
마지막 3 개의 진술 결과 :
PowerShell 버전은 다음과 같습니다.
SQL Server 관리 개체 (SMO) 사용
function Find-EmptyTables ($server,$database)
{
# Load SMO assembly
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
$s = New-Object 'Microsoft.SqlServer.Management.Smo.Server' $server
$db = $s.Databases.Item($database)
$db.Tables | Where-Object { $_.RowCount -eq 0 } | Select Schema, Name, RowCount
}
데이터베이스 수에 따라 하나의 서버를 처리하는 경우 변수에 채워진 각 데이터베이스 이름 목록에 대해 위 함수를 사용하고 동시에 모두 출력 할 수 있습니다.
$DBList = 'MyDatabase1','MyDatabase2'
foreach ($d in $DBList) {
Find-EmptyTables -server MyServer -database $d |
Select @{Label="Database";Expression={$d}}, Schema, Name, RowCount
}
다른 응답은 훌륭하지만 완전성입니다. SQL Server Management Studio> DB> 보고서> 표준 보고서> 테이블 별 디스크 사용량을 마우스 오른쪽 단추로 클릭하십시오.
나는 일반적으로 원하는 쿼리를 생성 한 다음 수동으로 실행하는 쿼리를 작성하지만 원하는 경우 한 번에 원하는 경우 ...
declare @sql nvarchar(max) ;
set @sql = ';with cte as (' + (select
(
SELECT case when row_number()
over (order by table_schema, table_name) = 1 then ' '
else ' union ' end +
'select count(*) rws, ''[' +
t.TABLE_SCHEMA +'].[' + t.table_name +
']'' tbl from ' + '['+
t.TABLE_SCHEMA + '].[' + TABLE_NAME + ']' +
CHAR(10) AS [data()]
FROM INFORMATION_SCHEMA.TABLES t
FOR XML PATH ('')
)) + ') select * from cte where rws = 0;'
execute sp_executesql @sql;
추가 답변으로, 문서화되지 않은 시스템 저장 프로 시저 sp_MSforeachtable
가 여기에 유용합니다.
CREATE TABLE #CountRows ( TableName nvarchar(260), NumRows int) ;
GO
EXEC sp_MSforeachtable 'insert into #CountRows select ''?'', count(*) from ?' ;
SELECT * FROM #CountRows WHERE NumRows = 0 ORDER BY TableName ;
DROP TABLE #CountRows ;
문서화되지 않은 기능에 대한 일반적인 경고가 적용됩니다.
궁금한 점이 있거나 부작용이 없는지 확인하려면 master에서 프로 시저의 소스 코드를 볼 수 있습니다. 동적 SQL을 사용하여 성능을 저하시키는 커서를 작성하므로 (cursor = slow!)이 절차는 일회성 작업에만 사용하십시오.
또한 sp_MSforeachtable
Azure Database에서는 사용할 수 없습니다.
DECLARE @toCheck INT;
DECLARE @countoftables INT;
DECLARE @Qry NVARCHAR(100);
DECLARE @name VARCHAR(100);
BEGIN
IF object_id('TEMPDB.DBO.#temp') IS NOT NULL drop table #temp;
SELECT ROW_NUMBER() OVER(ORDER BY name) AS ROW,CountStatement = 'SELECT @toCheck = COUNT(*) FROM ' + name,name INTO #temp FROM SYS.TABLES WITH (NOLOCK)
--SELECT * FROM #temp ORDER BY ROW
SET @countoftables =(SELECT COUNT(*) FROM #temp)
WHILE (@countoftables > 0)
BEGIN
SET @Qry = (SELECT CountStatement FROM #temp WITH (NOLOCK) WHERE ROW = @countoftables);
SET @name = (SELECT name FROM #temp WITH (NOLOCK) WHERE ROW = @countoftables);
EXEC SP_EXECUTESQL @qry,N'@toCheck INT OUTPUT',@toCheck OUTPUT;
IF(@toCheck=0)
BEGIN
PRINT 'Table: ' + @name + ', count: ' + convert(varchar(10),@toCheck);
END
--ELSE
-- BEGIN
-- PRINT 'Table: ' + @name + ', count: ' + convert(varchar(10),@toCheck);
-- END
SET @countoftables = @countoftables -1;
END
END
SELECT T.name [Table Name],i.Rows [Number Of Rows]
FROM sys.tables T
JOIN sys.sysindexes I ON T.OBJECT_ID = I.ID
WHERE indid IN (0,1) AND i.Rows<1
ORDER BY i.Rows DESC,T.name