2013-09-04 3 views
1

이전에 보지 못했던 T-SQL의 WHILE 루프가있는 SQL 2012에서 뭔가가 발생했습니다. 문제를 해결 한 후에 내가 맞은 것처럼 보이지만이 문제를두고 다른 사람이 출동했는지 또는 그들이 복제 할 수 있는지 확인하고 싶었습니다.T-SQL 2012 While 루프 최대 반복?

WHILE 루프는 최대 반복 횟수가 1300 만 회를 약간 넘는 것처럼 보입니다. 아래의 코드 두 개를 제공 할 것입니다. 하나는 고장 났고 다른 하나는이 제한을 해결했습니다. (왜 내가 그 일을하는지 알고 싶다면 나중에 테스팅에 사용할 수있는 반 무작위 데이터 선택으로 "데이터웨어 하우스"를 만들고 싶습니다.이 방법은 가장 쉬운 방법입니다. 그래서이 코드 샘플은 단순히 내가 그렇게 할 수 있습니다 확인하기 위해 테스트입니다)

DATABASE: TESTDB 
    TABLE: tbl_A 
    COLUMNS: 
     a (PK, bigint, not null) --Starts at zero, count upward 
     b (bigint, not null) -- Starts at 1 Quadrilion, count downward 
     c (bitint, null) -- empty for now 

그럼 삽입 한 레코드 :. 그런 다음

INSERT INTO tbl_A (a, b) VALUES (0, 999999999999999); 

나는에 VS 2012의 원인이 다음을 실행 while 루프에서 1,300 만 개가 넘는 반복 작업을 거쳐 멈추고 충돌합니다.

USE TESTDB 
GO 
SET NOCOUNT ON; 
--------------------------------------------------------------------- 
DECLARE @countUp bigint = (SELECT max(a)+1 FROM [dbo].[tbl_A]); 
DECLARE @countDown bigint = (SELECT min(b)-1 FROM [dbo].[tbl_A]); 
--------------------------------------------------------------------- 
WHILE (@countDown > 0) 
BEGIN 
    INSERT INTO tbl_A (a, b) VALUES (@countUp, @countDown); 
    SET @countUp += 1; 
    SET @countDown -= 1; 

    IF ((@countDown % 1000000) = 0) 
     PRINT char(9) + char(9) + char(9) + char(9) + CAST(@loop AS VARCHAR) + ': ' + CAST(@countDown AS VARCHAR) + ' <--- (' + CONVERT(varchar, GETDATE(), 120) + ')'; 
    ELSE IF ((@countDown % 200000) = 0) 
     PRINT CAST(@loop AS VARCHAR) + ': ' + CAST(@countDown AS VARCHAR); 
END 
--------------------------------------------------------------------- 
SET NOCOUNT OFF; 

그러나 위의 코드에서 WHILE 루프를 1300 만분의 1 초 동안 멈추게하면 매달리기 시점에 도달하지 못하고 그 둘레에 WHILE 루프가 생기고 @countDown> 0이면 계속됩니다. DB에 잘 13 세 이상 만 거래를 넘어 잘 실행 ...

SET NOCOUNT ON; 
--------------------------------------------------------------------- 
DECLARE @loop int = 1; 
DECLARE @countUp bigint = (SELECT max(a)+1 FROM [dbo].[tbl_A]); 
DECLARE @countDown bigint = (SELECT min(b)-1 FROM [dbo].[tbl_A]); 
DECLARE @StopValue bigint; 
    IF (@countDown > 13000000) 
     SET @StopValue = @countDown - 13000000; 
    ELSE 
     SET @StopValue = 0; 

WHILE (@countDown > 0) 
BEGIN 
     --------------------------------------------------------------------- 
     WHILE (@countDown <> @StopValue) 
     BEGIN 
      INSERT INTO tbl_A (a, b) VALUES (@countUp, @countDown); 
      SET @countUp += 1; 
      SET @countDown -= 1; 

      IF ((@countDown % 1000000) = 0) 
       PRINT char(9) + char(9) + char(9) + char(9) + CAST(@loop AS VARCHAR) + ': ' + CAST(@countDown AS VARCHAR) + ' <--- (' + CONVERT(varchar, GETDATE(), 120) + ')'; 
      ELSE IF ((@countDown % 200000) = 0) 
       PRINT CAST(@loop AS VARCHAR) + ': ' + CAST(@countDown AS VARCHAR); 
     END 
     --------------------------------------------------------------------- 
     SET @loop += 1; 
     SELECT @countUp=(max(a)+1) FROM [dbo].[tbl_A]; 
     SELECT @countDown=(min(b)-1) FROM [dbo].[tbl_A]; 
     IF (@countDown > 13000000) 
      SET @StopValue = @countDown - 13000000; 
     ELSE 
      SET @StopValue = 0; 
     --------------------------------------------------------------------- 
END 

SET NOCOUNT OFF; 

다른 누구도이 발생했습니다 ... 지금 아직도 거의 2,600 만 실행 ... 아직이야? 또는 복제 할 수 있습니까? 나는 그것이 내 VS 2012의 일부 설정이라면, 일반적인 최대 설정 MS가 WHILE 루프 또는 특정 시스템에 특정한 것을 설정하는지 궁금합니다 ...

내 시스템에도 충분한 디스크 공간과 전원이있는 것 같습니다. 그래서 나는 그것이이 한계에 어떤 영향을 미칠지 의심 스럽다.

Windows 7 Ultimate 64bit 
    SQL Server 2012 Dev. Ed. 64bit 
    6-core 3.47 GHz (12-way with hyper threading) 
    24 GB DDR3-1600 Memory 
    OS on SSD (3 Gbps SATA II) 
    DB is on two SSD drives in RAID 0 config (on 6 Gbps SATA III) 

피드백에 대한 호기심. (예 : 긴 게시물에 대한 죄송합니다.)

답변

1

우리의 루프 조건이 "동일 또는 숫자보다 큰 수는"이면, 우리의 테스트 우리가 선택할 수있는 T-SQL number types, BIGINT 유형을 가진.

다음 문 때문에 :

DECLARE @LoopLimit BIGINT = 9223372036854775807 
SET @LoopLimit = @LoopLimit + 1 
GO 

DECLARE @LoopLimit BIGINT = -9223372036854775808 
SET @LoopLimit = @LoopLimit - 1 
GO 

생성 :

메시지 8115, 수준 16, 상태 2, 줄 3 산술 오버플로 오류 데이터 유형 BIGINT로 표현을 변환.

내가 가장 큰 반복주기는 다음과 같은 추측 : 나는 직장에서, 그리고 난이 실행되는 전체 쿼리 대기 할 수없는 생각, 불행하게도

SET NOCOUNT ON 
GO 

    DECLARE @LoopLimit BIGINT = 9223372036854775807 

    WHILE @LoopLimit <> -9223372036854775808 
    BEGIN 
     SET @LoopLimit = @LoopLimit - 1 
    END 

SET NOCOUNT OFF 
GO 

(I 실행할 수 있습니다 그것은) 침대에 가기 전에 집에서,하지만 난 13 수백만의 반복이 전달되었는지 확인하기 위해 다음과 같은 쿼리를 가지고 :

SET NOCOUNT ON 
GO 

    DECLARE @LoopLimit BIGINT = 9223372036854775807 
    DECLARE @MilionsCounter BIGINT = 0 

    WHILE @LoopLimit <> -9223372036854775808 
    BEGIN 
     SET @LoopLimit = @LoopLimit - 1 
     SET @MilionsCounter = @MilionsCounter + 1 
     IF @MilionsCounter % 1000000 = 0 PRINT @MilionsCounter/1000000 
    END 

SET NOCOUNT OFF 
GO 

enter image description here

그래서 아직 실행 중입니다. 1,300 만 가지의 제한이 없다는 것을 스스로 확인할 수 있습니다 (SQL Management Studio 2012에서 테스트 됨).