2013-02-28 90 views
0

我需要創建一個查看特定模式中的所有表的異常報表,然後計算跨列和行,列出每個列中包含NULL值的條目數量。如何動態統計數據庫模式中所有表和列中具有空值的所有行

如何在不使用遊標的情況下完成此操作?

實施例:

People_Table有3列(姓名,CONTACT_NO)
Entity_Table具有5列(ID,姓名,地址,TEL_NO,FAX_NO)

我需要生成一個列出每個表和列名稱的輸出以及每個列中包含NULL值的記錄數。

People_Table:NAME(4),姓氏(9),CONTACT_NO(120)
Entity_Table:ID(0),NAME(4),ADDRESS(90),TEL_NO(120),FAX_NO (100 )

請注意,輸出可以是常規數據集格式,並且不需要看起來像條目的連接!我只是以這種方式列出來描述數據輸出。

這是一個動態數據庫,隨着時間的推移而變化,在此階段沒有任何NULL條目的列在將來可能有一個NULL條目,所以我需要跟蹤這個。到目前爲止,我已經爲這個解決方案做了其他的事情,這是我現在需要的最後一個。任何建議?

+0

這有什麼錯用遊標? – Max 2013-02-28 14:45:45

回答

0
DECLARE @dbname VARCHAR(100) = 'dbname' 
DECLARE @schemaName VARCHAR(100) = 'schemaname' 
DECLARE @result TABLE ([NullValues] int,col VARCHAR(4000)) 

SELECT @dbname dbname 
     ,t.name tbl 
     ,c.name col 
INTO #Temp1 
FROM sys.columns c 
JOIN sys.tables t ON 
     t.object_id = c.object_id 
JOIN sys.schemas s ON 
     s.schema_id = t.schema_id 
WHERE c.is_nullable = 1 
AND  s.name in (@schemaName) 

DECLARE @sql NVARCHAR(MAX) = 
STUFF(
(
    SELECT 'UNION ALL SELECT Count(*) as [NullValues],''' + @dbname + '.' + @schemaName + '.' + tbl + '.' + col + ''' FROM ' + @dbname + '.' + @schemaName + '.' + tbl + ' WHERE ' + col + ' IS NULL ' 
    FROM #Temp1 
    FOR  XML PATH('') 
), 1, 10, ' ') 

INSERT @result 
EXEC(@sql) 

SELECT [NullValues], col 
INTO #Nulls 
FROM @result 
WHERE col IS NOT NULL AND [NullValues] > 0 

SELECT 
     [TABLE_CATALOG] + '.' + [TABLE_SCHEMA] + '.' + [TABLE_NAME] + '.' + [COLUMN_NAME] as SchemaTableColumn 
     ,[TABLE_CATALOG] as 'Database' 
     ,[TABLE_SCHEMA] as 'Schema' 
     ,[TABLE_NAME] as 'TableName' 
     ,[COLUMN_NAME] 
     ,[ORDINAL_POSITION] 
     ,[DATA_TYPE] 
INTO #Temp2 
    FROM [DW_LandingCR].[INFORMATION_SCHEMA].[COLUMNS] 
    WHERE 
    [TABLE_SCHEMA] = @schemaName 
    ORDER BY TABLE_SCHEMA,TABLE_NAME,ORDINAL_POSITION 

SELECT sc.name as [Schema],ta.name as [TableName],SUM(pa.rows) RowCnt 
INTO #Temp3 
FROM sys.tables ta 
INNER JOIN sys.partitions pa 
ON pa.OBJECT_ID = ta.OBJECT_ID 
INNER JOIN sys.schemas sc 
ON ta.schema_id = sc.schema_id 
WHERE ta.is_ms_shipped = 0 
AND pa.index_id IN (1,0) 
AND sc.name = @schemaName 
GROUP BY sc.name,ta.name 
ORDER BY sc.name,ta.name 

Select 
    tp2.*,tp3.RowCnt 
Into #Detail 
From 
    #Temp2 tp2 
    inner join #Temp3 tp3 on tp2.[Schema]=tp3.[Schema] and tp2.[TableName]=tp3.[TableName] 

Select 
    det.*, 
    n.[NullValues] 
From 
    #Nulls n 
    Inner Join #Detail det on det.SchemaTableColumn=n.col 
Order By 
    det.[Database], 
    det.[Schema], 
    det.TableName, 
    det.[ORDINAL_POSITION] 


Drop Table #Nulls 
Drop Table #Detail 
Drop Table #Temp1 
Drop Table #Temp2 
Drop Table #Temp3 
0

試試這個(使用遊標雖然):

DECLARE @tbl sysname 
DECLARE @col sysname 
DECLARE @sql nvarchar(max) 
DECLARE @cnt INT 

CREATE TABLE #result 
(
    tbl sysname, 
    col sysname, 
    nulls int 
) 

DECLARE crs CURSOR FOR 
select t.name, c.name 
from sys.columns c 
join sys.tables t on c.object_id = t.object_id 

OPEN crs 

FETCH NEXT FROM crs INTO @tbl, @col 

WHILE @@FETCH_STATUS=0 
BEGIN 

    SET @sql = 'select @cntOUT=count(*) from '[email protected]+' where '[email protected]+' is null' 

    SET @cnt = 0 
    exec sp_executesql @sql, N'@cntOUT INT OUTPUT', @[email protected] OUTPUT 

    INSERT INTO #result (tbl, col, nulls) 
    VALUES (@tbl, @col, @cnt) 


    FETCH NEXT FROM crs INTO @tbl, @col 
END 

CLOSE crs 
DEALLOCATE crs 

SELECT * FROM #result 

DROP TABLE #result 
+0

感謝您的努力。由於性能方面的原因,我需要阻止使用遊標,因爲此腳本將被插入任何格式的數據庫中,並且會返回相關的詳細信息。非常快速的迴應,這讓我更加適應這個論壇。我現在要發佈我的答案! – Domondios 2013-03-01 07:45:31

+0

哦,天哪,現在我必須花時間將代碼格式化爲論壇要求。當我有時間這樣做時,我會在這裏回答我的答案。我也可以發佈我的整個存儲過程,但需要版權,因爲這是檢查整個數據倉庫數據庫一致性的簡單方法,對任何開發人員都有好處。此Proc用於數據倉庫環境 – Domondios 2013-03-01 08:01:27

+0

因此,您找到了一種不使用遊標的方法?好奇看到你的解決方案。 – Max 2013-03-01 13:34:16

相關問題