SQL Server 2008에서 while 루프 수행


120

do whileSQL Server 2008에서 루프 를 구현하는 방법이 있습니까?


5
Rahul이 제공 한 대답은 정확하지만 정확히 무엇을 달성하려고합니까? 루프는 세트 기반 솔루션에 비해 비쌉니다. 아마도 루프를 완전히 피할 수 있습니다.
Lieven Keersmaekers 2010

가능하면 루프를 사용하지 마십시오. 95 % 이상의 시간을 피하는 것이 가능하다고 추정합니다. 루프와 커서는 성능을 저하시키는 요소이며 최소 5 년의 성능 튜닝 경험이있는 DBA가 아닌 사람이 작성해서는 안됩니다.
HLGEM

1
어. 약간 극적인 HLGEM, 루프 및 커서는 테이블의 모든 행을 반복하지 않는 한 실제로 매우 깔끔합니다. 카테고리 또는 사이트 목록 또는 상대적으로 높은 수준의 항목이있는 경우 루프가 쿼리를 실행하는 가장 효율적인 방법 일 수 있습니다.
Geoff Griswald

답변:


190

MS SQL Server 2008의 DO-WHILE에 대해 잘 모르겠지만 DO-WHILE 루프처럼 사용하기 위해 WHILE 루프 논리를 변경할 수 있습니다.

예는 여기에서 가져옵니다 : http://blog.sqlauthority.com/2007/10/24/sql-server-simple-example-of-while-loop-with-continue-and-break-keywords/

  1. WHILE 루프의 예

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
    END
    GO

    ResultSet :

    1
    2
    3
    4
    5
  2. BREAK 키워드가있는 WHILE 루프의 예

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
        IF @intFlag = 4
            BREAK;
    END
    GO

    ResultSet :

    1
    2
    3
  3. CONTINUE 및 BREAK 키워드가있는 WHILE 루프의 예

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
        CONTINUE;
        IF @intFlag = 4 -- This will never executed
            BREAK;
    END
    GO

    ResultSet :

    1
    2
    3
    4
    5

그러나 데이터베이스 수준에서 루프피하십시오 . 참조 .


17
동일한 예가 여기에 있습니다.이 웹 사이트의 작성자입니까? blog.sqlauthority.com/2007/10/24/...
anar khalilov

1
그는 그렇지 않지만 왜 중요합니까? 정답이 주어졌습니다. 다른 웹 사이트에 연결하는 것은 고통스럽고 여기에 답변을 복사하여 붙여 넣는 것이 도움이됩니다.
Geoff Griswald

61

GOTO키워드로 인해 기분이 상하지 않으면 T-SQL에서 DO/ 를 시뮬레이션하는 데 사용할 수 있습니다 WHILE. 의사 코드로 작성된 다음과 같은 다소 무의미한 예를 고려하십시오.

SET I=1
DO
 PRINT I
 SET I=I+1
WHILE I<=10

다음은 goto를 사용하는 동등한 T-SQL 코드입니다.

DECLARE @I INT=1;
START:                -- DO
  PRINT @I;
  SET @I+=1;
IF @I<=10 GOTO START; -- WHILE @I<=10

GOTO활성화 된 솔루션과 원본 DO/ WHILE의사 코드 간의 일대일 매핑을 확인하십시오 . WHILE루프를 사용하는 유사한 구현 은 다음과 같습니다.

DECLARE @I INT=1;
WHILE (1=1)              -- DO
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF NOT (@I<=10) BREAK; -- WHILE @I<=10
 END

이제는 물론이 특정 예제를 간단한 WHILE루프 로 다시 작성할 수 있습니다. DO/ WHILE구조에 대한 좋은 후보가 아니기 때문 입니다. DO/ WHILE가 필요한 합법적 인 사례 는 드물기 때문에 적용 가능성보다는 예를 간략하게 강조했습니다 .


REPEAT / UNTIL, 누구든지 (T-SQL에서 작동하지 않음)?

SET I=1
REPEAT
  PRINT I
  SET I=I+1
UNTIL I>10

... 그리고 GOTOT-SQL 의 기반 솔루션 :

DECLARE @I INT=1;
START:                    -- REPEAT
  PRINT @I;
  SET @I+=1;
IF NOT(@I>10) GOTO START; -- UNTIL @I>10

키워드 GOTO를 통한 창의적인 사용 과 논리 반전을 통해 NOT원래 의사 코드와 GOTO기반 솔루션 사이에 매우 밀접한 관계가 있습니다. WHILE루프를 사용하는 유사한 솔루션 은 다음과 같습니다.

DECLARE @I INT=1;
WHILE (1=1)       -- REPEAT
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF @I>10 BREAK; -- UNTIL @I>10
 END

인수는의 경우에 있다고 할 수 REPEAT/ UNTILWHILE은 if 조건이 반전되지 않기 때문에 기반 솔루션은 간단하다. 반면에 더 장황합니다.

를 사용하는 것에 대한 모든 경멸이 아니었다면 GOTO명확성을 위해 T-SQL 코드에서 이러한 특정 (사악한) 루프 구조가 필요한 경우에 대한 관용적 솔루션 일 수도 있습니다.

동료 개발자들이 많이 악의적 인 .NET을 사용하여 당신을 잡을 때 분노를 겪지 않도록 노력하면서 자신의 재량에 따라 이것을 사용하십시오 GOTO.


6
+1 : 허용 된 답변보다 질문에 확실히 더 잘 답변합니다.
루이 KOTTMANN

나는 WHILE (1 = 1) 접근 방식을 선호합니다. 두려운 GOTO를 사용하지 않고 기능적으로 목적에 맞기 때문입니다.
kad81

두 방법 모두 유효합니다. 나는 GOTO를 사용하는 의사 루프를 좋아하는데 꽤 영리합니다.
Geoff Griswald

18

나는이 기사를 두 번 이상 읽었던 것을 기억하는 것 같고, 대답은 내가 필요한 것에 가깝다 .

일반적으로 DO WHILET-SQL에서 필요하다고 생각할 때 커서를 반복하고 있기 때문에 주로 최적의 명확성을 찾고 있습니다 (최적 속도 대비). WHILE TRUE/ 에 맞는 것처럼 보이는 T-SQL에서 IF BREAK.

이것이 당신을 여기에 가져온 시나리오라면,이 스 니펫은 당신을 잠시 절약 할 수 있습니다. 그렇지 않으면 다시 환영합니다. 이제 나는 여기에 두 번 이상 있었다는 것을 확신 할 수 있습니다. :)

DECLARE Id INT, @Title VARCHAR(50)
DECLARE Iterator CURSOR FORWARD_ONLY FOR
SELECT Id, Title FROM dbo.SourceTable
OPEN Iterator
WHILE 1=1 BEGIN
    FETCH NEXT FROM @InputTable INTO @Id, @Title
    IF @@FETCH_STATUS < 0 BREAK
    PRINT 'Do something with ' + @Title
END
CLOSE Iterator
DEALLOCATE Iterator

불행히도 T-SQL은이 무한 루프보다 루프 작업을 단독으로 정의하는 더 깨끗한 방법을 제공하지 않는 것 같습니다.


커서를 사용하는 것은 실제로 필요한 리소스가 훨씬 더 많이 필요하기 때문에 좋은 옵션이 아닙니다.
greektreat 2014 년

10
@greektreat : 반대표에 감사드립니다 :),하지만 혼란 스러워요! "커서가 결코 좋은 옵션이 아니라면", 항상 좋은 옵션이어야합니다. 그렇다면 왜 반대 투표를해야합니까? 그러나 진지하게도 커서는 매우 실용적인 용도가 많이 있습니다. 개인 테이블에 대해, 명확성 / 간결성> 성능이있는 소규모 작업, 결정적 작업을 사용할 수없는 유지 관리 작업, 특정 작업에 관계없이 원자 적 트랜잭션으로 발생해야하는 경우 등. 최근의 경우에는 저장 프로 시저 전용으로 들어오는 테이블 변수를 수집했습니다. 절대적인 칭찬은 결코 좋은 생각이 아닙니다!
shannon

5
@greektreat : 요약하면 때때로 데이터를 반복하는 것이 유일한 옵션입니다. 이 경우에는 여전히 좋은 옵션이 아니라고 주장 할 수 있지만 그렇다고 이런 종류의 코드가 불필요하고 반대 투표가 필요하다는 의미는 아닙니다.
shannon

1
나는 SQL에서 루프와 커서를 사용하는 다른 사람들에 대해 매우 화가 난 인터넷상의 사람들의 광적인 군대가 있다고 생각합니다. 이 웹 사이트에서 약 30 초 후에 SQL에서 루프를 사용한다고 언급하더라도받은 편지함에는 어떤 상황에서도 사용하지 말라고 말하는 무지한 사람들이
넘쳐날 것입니다

4

코드를 좀 더 읽기 쉽게하려면 exit 변수를 사용할 수도 있습니다.

DECLARE @Flag int = 0
DECLARE @Done bit = 0

WHILE @Done = 0 BEGIN
    SET @Flag = @Flag + 1
    PRINT @Flag
    IF @Flag >= 5 SET @Done = 1
END

더 복잡한 루프가 있고 논리를 추적하려고 할 때 더 관련이있을 수 있습니다. 명시된 루프는 비싸므로 가능하면 다른 방법을 사용하십시오.


내 말은 ... 우리는 데이터베이스 서버가 주어진 순간에 10 ~ 20 개의 CPU 코어가 유휴 상태이고 스토리지 컨트롤러가 사용 가능한 대역폭을 기가비트 단위로 측정하는 시대에 살고 있습니다. "LOOP = BAD"는 여전히 적용됩니다.
Geoff Griswald

1

SQL 서버는 While Loop 만 공식적으로 지원합니다. 이미 DO while 루프에 대한 답변 이 있습니다. SQL 서버에서 다양한 유형의 루프를 달성하는 방법에 대한 답변을 자세히 설명하고 있습니다.

어쨌든 루프의 첫 번째 반복을 완료해야하는 경우 SQL 서버의 DO..WHILE 또는 REPEAT..UNTIL 버전을 시도 할 수 있습니다 .

DO..WHILE 루프

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

REPEAT..UNTIL 루프

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

FOR 루프

DECLARE @cnt INT = 0;

WHILE @cnt < 10
BEGIN
   PRINT 'Inside FOR LOOP';
   SET @cnt = @cnt + 1;
END;

PRINT 'Done FOR LOOP';

참고


이것은 stackoverflow.com/a/46362450/8239061 에서 복사-붙여 넣기-재주문처럼 보입니다 .
SecretAgentMan

@SecretAgentMan : 두 답변 모두 다른 질문에 답하고 있습니다. 두 답변에 제공된 추가 데이터.
Somnath Muluk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.