खाली टेबल के लिए डेटाबेस की क्वेरी कैसे करें


28

कुछ 'डेवलपर्स' के कारण हम अपने सिस्टम पर काम कर रहे थे, हमारे पास खाली टेबल के साथ समस्या थी। हमने पाया है कि क्लाउड में स्थानांतरण के दौरान कई तालिकाओं की प्रतिलिपि बनाई गई थी, लेकिन उनमें डेटा नहीं था।

मैं एक टेबल को सिस्टम टेबल चलाना चाहता हूं ताकि यह पता लगाया जा सके कि उपयोगकर्ता टेबल क्या खाली हैं। हम MS SQL 2008 R2 का उपयोग कर रहे हैं।

सहायता के लिए धन्यवाद।

जवाबों:


46

उत्तोलन 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 का मतलब है कि आप केवल अपने ढेर या क्लस्टर इंडेक्स के लिए पंक्ति की संख्या को देख रहे हैं।


9

जैसा कि माइक फाल और किन दोनों ने नोट किया है, सिस्टम टेबल आपके दोस्त हैं।

अधिक कोड-पूर्ण संस्करण के लिए, मैं निम्नलिखित के साथ आया हूं, जो आपको अपने डेटाबेस में प्रत्येक तालिका द्वारा उपयोग किए गए कुल डेटा स्थान को देखने की अनुमति देगा।

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 कथनों के परिणाम:

यहाँ छवि विवरण दर्ज करें


6

यहाँ एक PowerShell संस्करण है:

SQL सर्वर प्रबंधन ऑब्जेक्ट्स (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
}

4

यहां अन्य प्रतिक्रियाएं बहुत अच्छी हैं, लेकिन पूर्णता के लिए: SQL सर्वर प्रबंधन स्टूडियो> DB> रिपोर्ट> मानक रिपोर्ट> डिस्क उपयोग तालिका पर राइट-क्लिक करें


यह सभी तालिकाओं को लौटा देगा, न कि केवल वे जो खाली हैं। मुझे विश्वास नहीं है कि आप उन रिपोर्टों पर फ़िल्टर लागू कर सकते हैं।
शॉन मेल्टन

यह सच है। पैड पैड पैड
onupdatecascade

लेकिन यह बहुत अच्छा जवाब है। बस 2 क्लिक की दूरी पर, पहले से कहीं ज्यादा आसान।
मैरियन

हालाँकि, आप सूची को रिकॉर्ड कर सकते हैं
रॉबर्ट माइक्स

1

मैं आमतौर पर केवल एक क्वेरी बनाता हूं जो वह क्वेरी बनाता है जो मैं चाहता हूं और फिर उस मैन्युअल रूप से निष्पादित करता हूं, लेकिन यदि आप यह सब एक बार में चाहते हैं ...

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;

1

एक अतिरिक्त जवाब के रूप में, undocumented सिस्टम संग्रहीत कार्यविधि 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 ;

अनिर्दिष्ट सुविधाओं के बारे में सामान्य चेतावनी लागू होती है।

आप मास्टर में प्रक्रिया के स्रोत कोड को देख सकते हैं यदि आप उत्सुक हैं या यदि आप निश्चित होना चाहते हैं तो इसका कोई बुरा दुष्प्रभाव नहीं है। यह कर्सर बनाने के लिए गतिशील SQL का उपयोग करता है, जो प्रदर्शन के लिए खराब है (कर्सर = धीमा!), इसलिए केवल एक-टास्क के लिए इस प्रक्रिया का उपयोग करें।

इसके अतिरिक्त, sp_MSforeachtableAzure डेटाबेस में उपलब्ध नहीं है।


1
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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.