为什么在此SQL While循环中返回相同的值?
我正在使用Microsoft SQL Server,并尝试将一些数据插入到临时表中。然后,我希望使用WHILE循环遍历临时表中的每一行。我不想使用光标。
请参见以下查询:
-- Create Table
DROP TABLE IF EXISTS #TMP_ABC
CREATE TABLE #TMP_ABC
(
[ABC] [varchar](3) NULL,
)
-- Insert Values
INSERT INTO [#TMP_ABC] VALUES ('AAA')
INSERT INTO [#TMP_ABC] VALUES ('BBB')
INSERT INTO [#TMP_ABC] VALUES ('CCC')
INSERT INTO [#TMP_ABC] VALUES ('DDD')
INSERT INTO [#TMP_ABC] VALUES ('EEE')
INSERT INTO [#TMP_ABC] VALUES ('FFF')
-- Display values
DECLARE @count INT
DECLARE @row INT
SET @row = 1;
DECLARE @ABC varchar(3)
SET @count = (SELECT COUNT(ABC) FROM #TMP_ABC)
WHILE (@row <= @count) BEGIN
SELECT @ABC = ABC FROM #TMP_ABC
PRINT @ABC
SET @row += 1
END
以下是查询返回的内容:
(1 row affected)
FFF
FFF
FFF
FFF
FFF
FFF
我希望返回以下内容:
(1 row affected)
AAA
BBB
CCC
DDD
EEE
FFF
请有人"好心"向我展示一下我前进道路上的错误,以及如何做到这一点?
解决方案
发生此问题是因为SQL Server没有将@row
与表中的行相关联(这种关联对您来说很明显,但SQL Server不是人)。
1 -> @count
时,它会反复运行相同的SELECT @ABC = ABC FROM #TMP_ABC
。没有WHERE
子句和TOP
,因此SQL Server每次都只是读取整个表,并将变量设置为等于它读取的最后ABC
值。
相反,您应该使用游标(如果您需要循环;通常不需要,根据@Larnu's comment)。您在某处读到了一些错误信息,认为游标是错误的,而While循环不是游标,但这两者都是错误的。
- Bad Habits to Kick : Thinking a WHILE loop isn't a CURSOR
- What impact can different cursor options have?
- Follow-up on cursor options
- Overlooked T-SQL Gems(请参阅为什么对游标使用局部变量比您可能使用的常规类型更好)
如果您确实出于某种原因需要循环,则重写如下:
CREATE TABLE #TMP_ABC(ABC varchar(3));
INSERT INTO #TMP_ABC(ABC) VALUES
('AAA'),('BBB'),('CCC'),('DDD'),('EEE'),('FFF');
DECLARE @ABC varchar(3), @c cursor;
SET @c = cursor LOCAL FAST_FORWARD
FOR SELECT ABC FROM #TMP_ABC;
OPEN @c;
FETCH NEXT FROM @c INTO @ABC;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @ABC;
FETCH NEXT FROM @c INTO @ABC;
END
输出:
AAA
BBB
CCC
DDD
EEE
FFF
- 示例db<>fiddle
但我不确定这比SELECT ABC FROM #TMP_ABC;
完成了什么。
相关文章