我使用两个光标。但我想把它最小化到一个光标

时间:2017-10-04 13:16:25

标签: sql-server

declare @tab_name varchar(100)
declare @col_name varchar(100)
declare @sqlquery nvarchar(max)

declare cursor_table cursor
for
SELECT  TABLE_NAME FROM INFORMATION_SCHEMA.TABLES --where table_name!='tab'

open cursor_table 
fetch next from cursor_table into @tab_name
while @@fetch_status = 0
begin
    declare cursor_count cursor 
    for
    SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tab_name
    open cursor_count
    fetch next from cursor_count into @col_name
    while @@FETCH_STATUS =0
    begin
    set @sqlquery='

     select '+''''+@tab_name+''''+','+''''+ @col_name+''''+',count('+@col_name+') as count from '+@tab_name+' where ISNULL('+@col_name+','''') !='''' '
    print @sqlquery         
    exec sp_executesql @sqlquery
    fetch next from cursor_count into @col_name
    End
    CLOSE cursor_count  
    DEALLOCATE cursor_count 
    print @tab_name
fetch next from cursor_table into @tab_name
end
CLOSE cursor_table  
DEALLOCATE cursor_table 

2 个答案:

答案 0 :(得分:0)

如果我“需要”获得每个列,每个表的所有空值的计数,我会这样接近它。

这是非常低效的查询,可能需要一段时间才能执行,因为您必须对所有非索引字段执行多个全表扫描。对于本练习,我建议您将其限制在几张桌子上。

SELECT CommandOrder=1,'DECLARE @TEMP TABLE(TableName NVARCHAR(100), ColumnName NVARCHAR(100), NullRecordCount INT)'
UNION
SELECT CommandOrder=3,
    'INSERT @TEMP SELECT '''+S.Name+'.'+T.Name+''','''+C.Name+''', COUNT(*) FROM '+S.Name+'.'+T.Name+' WHERE COALESCE('+C.Name+',NULL)=NULL' 
    FROM 
        SYS.Columns C 
        INNER JOIN SYS.Tables T ON C.object_id = T.object_id 
        INNER JOIN SYS.Schemas S ON T.schema_id = S.schema_id
UNION
SELECT CommandOrder=4,'SELECT * FROM @TEMP T WHERE NullRecordCount > 0 ORDER BY TableName,ColumnName'

答案 1 :(得分:0)

  

如果要求至少将其最小化为一个光标,请使用此方法。

如果你真的必须使用游标,请使用FAST_FORWARD游标选项。

declare @tab_name varchar(100)
declare @col_name varchar(100)
declare @sqlquery nvarchar(max)

DECLARE @mainTable TABLE(
Id INT IDENTITY(1,1) PRIMARY KEY,
TABLE_NAME Varchar(500)
)

--GET TABLES data into main table 
INSERT INTO @mainTable 
SELECT  TABLE_NAME FROM INFORMATION_SCHEMA.TABLES 

DECLARE @startTables INT = 1
DECLARE @finalTables INT = 0

SELECT @finalTables = MAX(Id) FROM @mainTable
-- Do a while loop over id
WHILE @startTables <= @finalTables
BEGIN 
    -- Get the table name
    SELECT @tab_name  =  TABLE_NAME  FROM @mainTable WHERE Id = @startTables
    -- Initialize cursor 
    declare cursor_count cursor 
    for
    SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tab_name
    open cursor_count
    fetch next from cursor_count into @col_name
    while @@FETCH_STATUS =0
    begin
    set @sqlquery='select '+''''+@tab_name+''''+','+''''+ @col_name+''''+',count('+@col_name+') as count from '+@tab_name+' where ISNULL('+@col_name+','''') !='''' '
    print @sqlquery         
    exec sp_executesql @sqlquery
    fetch next from cursor_count into @col_name
    End
    CLOSE cursor_count  
    DEALLOCATE cursor_count 
    print @tab_name
 SET @startTables = @startTables + 1 
END
  

根本不使用光标,请使用此功能。

declare @tab_name varchar(100)
declare @col_name varchar(100)
declare @sqlquery nvarchar(max)

-- Table stores Id, table name, Query in one go.
DECLARE @secondaryTable TABLE(
Id INT IDENTITY(1,1) PRIMARY KEY,
TABLE_NAME Varchar(500),
Query Varchar(8000)
)

INSERT INTO @secondaryTable 
SELECT a.TABLE_NAME, 'select '+''''+a.TABLE_NAME+''''+','+''''+ b.COLUMN_NAME+''''+',count('+b.COLUMN_NAME+') as count from '+a.TABLE_NAME+' where ISNULL('+b.COLUMN_NAME+','''') !='''' ' 
FROM INFORMATION_SCHEMA.TABLES a INNER JOIN INFORMATION_SCHEMA.COLUMNS b ON a.TABLE_NAME = b.TABLE_NAME
--SELECT * FROM @secondaryTable

DECLARE @startTables INT = 1
DECLARE @finalTables INT = 0

SELECT @finalTables = MAX(Id) FROM @secondaryTable
-- Loop through the table, get the table name and query. Execute the query.
WHILE @startTables <= @finalTables
BEGIN 
    SELECT @tab_name = TABLE_NAME, @sqlquery = Query FROM @secondaryTable WHERE Id = @startTables
    print @sqlquery
    exec sp_executesql @sqlquery
    print @tab_name
 SET @startTables = @startTables + 1 
END