游标循环 - > while(@@ FETCH_STATUS = 0)不进入循环

时间:2016-12-06 12:58:35

标签: sql sql-server sql-server-2008 sql-server-2012 sql-server-2008-r2

我的代码如下:

declare @prefix varchar(50)
set @prefix = 'schema1'

declare @TablesAndIdentifiers table (TableT0 varchar(50), TableX0 varchar(50), IdentifierT0 varchar(50), IdentifierX0 varchar(50))
insert into @TablesAndIdentifiers(TableT0, TableX0, IdentifierT0, IdentifierX0)
values 
 ('table1', 'table2', 'external_Id', 'Key Details | External Id')
declare @TableT varchar(50)
declare @TableX varchar(50)
declare @IdentifierT varchar(50)
declare @IdentifierX varchar(50)

------------------------------------------OUTER LOOP------------------------------------------
declare @OuterCursor cursor
set @OuterCursor = cursor for select * from @TablesAndIdentifiers
open @OuterCursor
fetch next from @OuterCursor into @TableT, @TableX, @IdentifierT, @IdentifierX
while(@@FETCH_STATUS = 0)
begin

declare @ColList2 table (ColListT varchar(50), ColListX varchar(50))
    insert into @ColList2(ColListT,ColListX)
    select ColListT, ColListX
    from (
    select COLUMN_NAME as ColListT, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
    where table_name = @TableT and COLUMN_NAME!=@IdentifierT) a
    full outer join
    (select COLUMN_NAME as ColListX, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
    where table_name = @TableX and COLUMN_NAME!=@IdentifierX) b
    on a.r = b.r

    --Declare and set variables containing the query which will insert the mismatch columns into a new table
    --@sqlfull is a concatenation of @sqlpre, @sql, @sqlpost, @sqlwhere, @sqlpregroup, @sqlgroupstatement, @sqlpostgroup
    --The reason for this is that @sql is the only part of the query we want to be contained in the loop - the others should run outside of the loop
    declare @sqlpre varchar(max)
    declare @sql varchar(max)
    declare @sqlpost varchar(max)
    declare @sqlgroupstatement varchar(max)
    declare @sqlpostgroup varchar(max)
    declare @sqlfull varchar(max)

    set @sqlpre = 'select * from (select '
    set @sql = ''
    set @sqlpost =  @IdentifierT + ' from '+@prefix+'.dbo.' +@TableX +' x inner join '+@prefix+'.dbo.' +@TableT + ' t on t.' +@IdentifierT + ' = x.[' + @IdentifierX +'])dt1 group by '
    set @sqlgroupstatement = ''
    set @sqlpostgroup = ' ' + @IdentifierT


declare @Cursor cursor, @ColListTvar varchar(100), @ColListXvar varchar(100)
        set @Cursor = cursor for select * from @ColList2
        open @Cursor
        fetch next from @Cursor into @ColListTvar,@ColListXvar
        Print 'Before While => ' + CAST(@@FETCH_STATUS  AS varchar(32))
        while (@@FETCH_STATUS = 0)
        begin
        Print 'Inside while -=> ' + CAST(@@FETCH_STATUS  AS varchar(32))
        set @sql = @sql + 'case when t.' +@ColListTvar + ' != x.[' +@ColListXvar + '] then 1 else null end as ' + @ColListTvar+'_mismatch, '
        set @sqlgroupstatement = @sqlgroupstatement + @ColListTvar+'_mismatch, '
        fetch next from @Cursor into @ColListTvar,@ColListXvar
        end
    close @Cursor
    Print 'After While => ' + CAST(@@FETCH_STATUS  AS varchar(32))
    set @sqlfull = concat(@sqlpre,@sql,@sqlpost,@sqlgroupstatement,@sqlpostgroup)
    print(@sqlfull)
    --exec(@sqlfull)


    declare @ColListMismatch varchar(max)
        select @ColListMismatch = coalesce(@ColListMismatch+'_count,' ,'') + column_name
        from INFORMATION_SCHEMA.COLUMNS where table_name = 'mismatches_' + @TableT and COLUMN_NAME!=@IdentifierT
        -- The last column in the list won't get a '_count' in its name (but it needs it as the rest of the code assumes this is the naming convention)
        -- See below for workaround to get round this

    --Create table variable containing the list of mismatch columns (in which we want to count the non-nulls - non-null implies there has been a mismatch)
    declare @ColListMismatchTable table (ColListM varchar(50))
        insert into @ColListMismatchTable(ColListM)
        select ColListM
        from (select [COLUMN_NAME] as ColListM from INFORMATION_SCHEMA.Columns
        where table_name = 'mismatches_'+@TableT and COLUMN_NAME!=@IdentifierT)dt1

    --Declare variables for use in queries
    declare @sqlpre2 varchar(max)
    declare @sqlloop varchar(max)
    declare @sqlpost2 varchar(max)
    declare @sqlfull2 varchar(max)
    -- Select counts from the transformation layer table and the XPLAN table; also select the count of the table produced as a result of the inner join between the two
    -- If the migration has functioned correctly, these three counts should all be the same
    set @sqlpre2 = 'select countXPLAN, countTransfLayer, countXPLAN-countTransfLayer as CountDiff, countMatchedIdentifiers, ' 
    -- As mentioned above, the       "+ @ColListMismatch + '_count into "     part of the below is necessary to append the _count to the last variable
    + @ColListMismatch + '_count into '+@prefix+'.[dbo].report_' + @TableT + ' from '
    set @sqlloop = ''
    set @sqlpost2 = ' select * from ((select count(*) as countTransfLayer from '+@prefix+'.dbo.'+@TableT+')dt1 cross join (select count(*) as countXPLAN from '+@prefix+'.dbo.['+@TableX+'])dt2 cross join  (select count(*) as countMatchedIdentifiers from '+@prefix+'.dbo.mismatches_'+@TableT+')dt4)' 

------------------------------------------SECOND INNER LOOP------------------------------------------
    --Use Cursor to create loop to produce counts for each column in mismatches_*   
    declare @Cursor2 cursor, @ColListMismatchvar varchar(50)
        set @Cursor2 = cursor for select * from @ColListMismatchTable
        open @Cursor2
        fetch next from @Cursor2 into @ColListMismatchvar
        while(@@FETCH_STATUS = 0)
        begin
        -- Select all the counts of non-nulls
        set @sqlloop = @sqlloop + '(select count(*) as '+ @ColListMismatchvar + '_count from mismatches_' + @TableT + ' where ' + @ColListMismatchvar + '=1)dt_' + @ColListMismatchvar + ' cross join '
        fetch next from @Cursor2 into @ColListMismatchvar
        end
        -- Remove variables so that they can be reused by the next data entity
        delete @ColListMismatchTable
        select @ColListMismatch=null
    close @Cursor2
    print('in loop to execute sqlfull2')
    set @sqlfull2 = concat(@sqlpre2,@sqlloop,@sqlpost2)
    print(@sqlfull2)
--  exec(@sqlfull2)
    print('executed sqlfull2')

fetch next from @OuterCursor into @TableT, @TableX, @IdentifierT, @IdentifierX
end
close @OuterCursor

out put of:

(1行受影响)

(0行(s)受影响)

在While =>之前-1

在While =>之后-1

select * from (select external_Id from schema1.dbo.table22 x inner join schama1.dbo.table1 t on t.external_Id = x.[Key Details | External Id])dt1 group by  external_Id

(0行(s)受影响)

(0行(s)受影响) 在循环中执行sqlfull2 ..

我遇到代码的问题不会进入下面的代码循环

declare @Cursor cursor, @ColListTvar varchar(100), @ColListXvar varchar(100)
        set @Cursor = cursor for select * from @ColList2
        open @Cursor
        fetch next from @Cursor into @ColListTvar,@ColListXvar
        Print 'Before While => ' + CAST(@@FETCH_STATUS  AS varchar(32))
        while (@@FETCH_STATUS = 0)
        begin
        Print 'Inside while -=> ' + CAST(@@FETCH_STATUS  AS varchar(32))
        set @sql = @sql + 'case when t.' +@ColListTvar + ' != x.['     +@ColListXvar + '] then 1 else null end as ' + @ColListTvar+'_mismatch, '
        set @sqlgroupstatement = @sqlgroupstatement +     @ColListTvar+'_mismatch, '
        fetch next from @Cursor into @ColListTvar,@ColListXvar
        end
    close @Cursor
    Print 'After While => ' + CAST(@@FETCH_STATUS  AS varchar(32))
    set @sqlfull = concat(@sqlpre,@sql,@sqlpost,@sqlgroupstatement,@sqlpostgroup)
    print(@sqlfull)
    --exec(@sqlfull)

任何建议都将不胜感激。

提前致谢。

1 个答案:

答案 0 :(得分:0)

经过大量分析后我发现了

的问题
select ColListT, ColListX
from (
select COLUMN_NAME as ColListT, row_number() over (order by table_name) as r          from INFORMATION_SCHEMA.Columns
where table_name = @TableT and COLUMN_NAME!=@IdentifierT) a
full outer join
(select COLUMN_NAME as ColListX, row_number() over (order by table_name) as  r from INFORMATION_SCHEMA.Columns
where table_name = @TableX and COLUMN_NAME!=@IdentifierX) b
on a.r = b.r

如果我使用内连接,那么取代全外连接,它起作用。

2个表中的列数存在问题,其中一个表的列数少于其他表,这就是它无法正常工作的原因。