如果BREAK

时间:2015-12-15 19:09:03

标签: sql-server control-structure

在SQL Server 2012存储过程中,我有几个嵌套结构。我想打破它们的单层。

我认为msdn https://msdn.microsoft.com/en-CA/library/ms181271.aspx中对BREAK的描述就在我身边。但是我在通过调试单步执行时会遇到一些奇怪的行为。我说奇怪,因为它不一致。有时它会逃到我期望的层面。有时它会跳过一对。

WHILE ... BEGIN
  stuff1
  IF...BEGIN
    stuff2
    WHILE ... BEGIN
      stuff3
      IF .... BEGIN
        stuff4
        IF @NumberRecords=0 BREAK
        stuff5
      END
      --stuff6
      if @NumberRecords=0 and @loopBOMRowCount=@ResultsSOloopstart-1 break
      --on the last occasion I observed, @loopBOMRowCount was 6 and @ResultsSOloopstart 71 and it never highlighted this section, either way

      SET @loopBOMRowCount = @loopBOMRowCount + 1
    END
    stuff7 --nothing actually here
  END
  --stuff8
  SET @periodloopcount=@periodloopcount+1 
  --this is where it ended up highlighting on that last occasion
END
stuff9

所以如果NumberRecords = 0,那么下一个op应该是if在stuff6,对吗?即使stuff4包含,例如,EXEC调用存储过程的INSERT INTO表?没有什么能够将堆栈混淆出层?

是的,我意识到这是丑陋的SQL。大多数指令都是在两个临时表上编辑的,我避免将它们来回传递给存储过程,否则会清理代码。

修改

我设法让它按照我想要的方式进行路由,在内部IF周围添加一个虚拟WHILE循环,我想首先突破。但我真的很想知道我是如何误解msdn信息的。似乎BREAK应该突破IF,只要它有END语句。

退出 WHILE语句中最内层循环或WHILE循环内的IF ... ELSE语句。将执行END关键字后面出现的任何语句,标记循环结束。

2 个答案:

答案 0 :(得分:7)

我同意documentation有点令人困惑。这条线似乎暗示你可以突破IF。

  

退出WHILE语句或IF ... ELSE语句中的最内层循环   在WHILE循环中。 END关键字后出现的任何语句,   标记循环结束,执行。 BREAK经常发生,但是   并不总是,从IF测试开始。

然而事实并非如此。 BREAK从其位置退出最内部的WHILE。文档的关键部分是“在END关键字后面出现的任何语句,标记循环结束,都会被执行。”。

此示例演示了这一点。

示例1

DECLARE @X INT = 1;

PRINT 'Start'

/* WHILE loop required to use BREAK.
 */
WHILE @X = 1
BEGIN

    /* Outer IF.
     */
    IF 1 = 1 
    BEGIN
        /* Inner IF.
         */
        IF 2 = 2
        BEGIN
            BREAK
            PRINT '2'
        END

        PRINT '1'
    END

    SET @X = @X + 1;
END

PRINT 'End'

仅打印“开始”和“结束”文本。因为BREAK存在WHILE,所以不打印1。

您还可以在此处看到此行为:

示例2

/* Anti-Pattern.
 * Breaking outside a WHILE is not allowed.
 */
IF 1 = 1 
BEGIN
    BREAK 
    PRINT 1
END

此查询返回错误:

  

消息135,级别15,状态1,行4不能使用BREAK语句   超出WHILE声明的范围。

答案 1 :(得分:0)

如果您真的想要打破IF语句,打印“开始,1,结束”,如上例所示,您可以执行以下操作

DECLARE @X INT = 1;

PRINT 'Start'

/* WHILE loop required to use BREAK.
 */
WHILE @X = 1
BEGIN

    /* Outer IF.
     */
    IF 1 = 1 
    BEGIN
        /* Inner IF.
         */
        IF 2 = 2
        BEGIN
            GOTO skip2
            PRINT '2'
        END
        skip2:

        PRINT '1'
    END

    SET @X = @X + 1;
END

PRINT 'End'

现在您可以使用它来使用以下

来处理OP的示例
WHILE ... BEGIN
  stuff1
  IF...BEGIN
    stuff2
    WHILE ... BEGIN
      stuff3
      IF .... BEGIN
        stuff4
        IF @NumberRecords=0
            GOTO startstuff6
        stuff5
      END
      startstuff6:
      --stuff6
      if @NumberRecords=0 and @loopBOMRowCount=@ResultsSOloopstart-1
        GOTO startstuff7
      --on the last occasion I observed, @loopBOMRowCount was 6 and @ResultsSOloopstart 71 and it never highlighted this section, either way

      SET @loopBOMRowCount = @loopBOMRowCount + 1
    END
    startstuff7:
    stuff7 --nothing actually here
  END
  --stuff8
  SET @periodloopcount=@periodloopcount+1 
  --this is where it ended up highlighting on that last occasion
END
stuff9

通常认为反转布尔逻辑的方法更好,例如:

IF NOT @NumberRecords=0
BEGIN
        stuff5
END