我在 SQL 2012 中遇到了 T-SQL 中的 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 循环中超过 1300 万次迭代后挂起并崩溃:
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;
但是,当我强制上述代码在 1300 万处停止 WHILE 循环时,它永远不会挂起,然后围绕该循环创建一个 WHILE 循环,而 @countDown > 0,它似乎继续运行良好数据库中超过 13+ 百万笔交易......它现在仍在运行,接近 2600 万......而且还在继续......
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;
有没有其他人遇到过这个?或者,你能复制它吗?我想知道这是否是我的 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)
好奇的反馈。(对不起,这么长的帖子。)