循环问题

时间:2012-08-01 18:04:12

标签: sql tsql sql-server-2005 while-loop

这个查询应该是从sql DB中删除临时表/视图但是当删除最后一个表/视图时它会保持循环。任何人都有一个答案,为什么这会在放弃最后一个表时进入无限循环?

DECLARE @name VARCHAR(128)

DECLARE @SQL VARCHAR(254)

DECLARE @type VARCHAR(50)

DECLARE @tmp_table TABLE
    (
      table_name VARCHAR(50)
    , table_type VARCHAR(50)
    )

;WITH    cte_tempTables

          AS (
               SELECT
                table_name
              , crdate
              , crdate + 90 [ExperiationDate]
              , TABLE_TYPE
               FROM
                INFORMATION_SCHEMA.TABLES t
               inner join sysobjects s
                on s.name = t.table_name
               WHERE
                TABLE_CATALOG = 'SBR_Temp'
                AND t.table_name NOT IN ( 'DaleDelq' ,'tblCancelContract' ,
                                          'tblCreateContracts' ,'MWFRTPay' )

             )

    INSERT INTO
        @tmp_table
        (
          table_name
        , table_type 
        )
        select
            table_name
          , table_type

        FROM
            [cte_tempTables]
        WHERE
            ExperiationDate < GETDATE()

SELECT TOP 1
    @name = [table_name]
  , @type = CASE WHEN [table_type] = 'BASE TABLE' THEN 'TABLE'
                 ELSE 'VIEW'
            END

FROM
    @tmp_table

WHILE @name IS NOT NULL

    OR @name <> ''

    BEGIN
        SELECT
            @SQL = 'DROP ' + @type + ' SBR_Temp.[dbo].[' + RTRIM(@name) + ']'
            --EXEC (@SQL)
        PRINT 'Dropped ' + @type + ':' + @name

        DELETE
            @tmp_table
        WHERE
            [table_name] = @name

        SELECT TOP 1
            @name = [table_name]
          , @type = CASE WHEN [table_type] = 'BASE TABLE' THEN 'TABLE'
                         ELSE 'VIEW'
                    END
        FROM
            @tmp_table
            SELECT @name
    END
GO

这是结果的一个例子

(受影响的4行) 丢弃的视图:vue_SunsetCoveClientInventory

(1行受影响)

(1行(s)受影响) 丢弃的视图:vue_SunsetCoveClientCoOwners

(1行受影响)

(1行(s)受影响) 丢弃的表:BKDischarge

(1行受影响)

(1行(s)受影响) 丢弃的视图:vue_nocoop

(1行受影响)

(1行(s)受影响) 丢弃的视图:vue_nocoop

(0行(s)受影响)

(1行(s)受影响) 丢弃的视图:vue_nocoop

(0行(s)受影响)

(1行(s)受影响) 丢弃的视图:vue_nocoop

(0行(s)受影响)

(1行(s)受影响) 丢弃的视图:vue_nocoop

(0行(s)受影响)

(1行(s)受影响) 丢弃的视图:vue_nocoop

(0行(s)受影响)

1 个答案:

答案 0 :(得分:3)

@tmp_table中没有更多行后,您不再更改@name的值。我认为你宁愿使用:

WHILE EXISTS (SELECT NULL FROM @tmp_table)
BEGIN
    SELECT TOP 1...

更改为这种检查方式还有以下好处:

  • 您不再假设您至少有一行开头。
  • 您不必在两个地方保持相同的SELECT TOP 1...

您可以运行此演示代码以简化形式查看您的问题:

-- Setup two rows of example data
declare @table table (
    id int primary key
)
insert into @table select 1
insert into @table select 2

declare @id int

-- Select, display and delete the first row
select top 1 @id = id from @table
select @id
delete from @table where id = @id

-- Select, display and delete the second row
select top 1 @id = id from @table
select @id
delete from @table where id = @id

-- Nothing left to select, but @id still retains its value!
select top 1 @id = id from @table
select @id