在T-SQL中,当迭代游标的结果时,通常的做法是在FETCH
循环之前重复WHILE
语句。以下示例来自Microsoft:
DECLARE Employee_Cursor CURSOR FOR
SELECT EmployeeID, Title FROM AdventureWorks2012.HumanResources.Employee
WHERE JobTitle = 'Marketing Specialist';
OPEN Employee_Cursor;
FETCH NEXT FROM Employee_Cursor;
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM Employee_Cursor;
END;
CLOSE Employee_Cursor;
DEALLOCATE Employee_Cursor;
GO
(注意FETCH NEXT FROM Employee_Cursor;
如何出现两次。)
如果FETCH
选择了很长的变量列表,那么我们就会有一个大的重复语句,这个语句既丑陋又当然是“非干”代码。
我不知道后置条件控制流T-SQL语句所以看来WHILE(TRUE)
然后BREAK
@@FETCH_STATUS
}不是零。这对我来说很笨拙。
我还有其他选择吗?
答案 0 :(得分:10)
Chris Oldwood在网上发布了一个很好的结构,非常优雅:
DECLARE @done bit = 0
WHILE (@done = 0)
BEGIN
-- Get the next author.
FETCH NEXT FROM authors_cursor
INTO @au_id, @au_fname, @au_lname
IF (@@FETCH_STATUS <> 0)
BEGIN
SET @done = 1
CONTINUE
END
--
-- stuff done here with inner cursor elided
--
END
答案 1 :(得分:6)
这就是我所采用的(羞耻):
WHILE (1=1)
BEGIN
FETCH NEXT FROM C1 INTO
@foo,
@bar,
@bufar,
@fubar,
@bah,
@fu,
@foobar,
@another,
@column,
@in,
@the,
@long,
@list,
@of,
@variables,
@used,
@to,
@retrieve,
@all,
@values,
@for,
@conversion
IF (@@FETCH_STATUS <> 0)
BEGIN
BREAK
END
-- Use the variables here
END
CLOSE C1
DEALLOCATE C1
你可以看到我发布问题的原因。我不喜欢当if
语句应该位于while
时,如何将流控制隐藏在{{1}}语句中。
答案 2 :(得分:4)
第一个Fetch
不应该是Fetch next
,只能是fetch
。
然后你不会重复自己。
我会花更多的精力摆脱光标,而不是干的教条,(但如果真的很重要,你可以使用GOTO
:) - 抱歉,M。Dijkstra)
GOTO Dry
WHILE @@FETCH_STATUS = 0
BEGIN
--- stuff here
Dry:
FETCH NEXT FROM Employee_Cursor;
END;
答案 3 :(得分:0)
这是我的不起眼的贡献。一条FETCH语句,没有GOTO,没有BREAK,没有CONTINUE。
-- Sample table
DROP TABLE IF EXISTS #tblEmployee;
CREATE TABLE #tblEmployee(ID int, Title varchar(100));
INSERT INTO #tblEmployee VALUES (1, 'First One'), (2, 'Second Two'), (3, 'Third Three'), (3, '4th Four');
-- Cursor with one FETCH statement
DECLARE @bEOF bit=0, @sTitle varchar(200), @nID int;
DECLARE cur CURSOR LOCAL FOR SELECT ID, Title FROM #tblEmployee;
OPEN cur;
WHILE @bEOF=0
BEGIN
FETCH NEXT FROM cur INTO @nID, @sTitle;
IF @@FETCH_STATUS<>0
SET @bEOF=1;
ELSE
BEGIN
PRINT Str(@nID)+'. '+@sTitle;
END;
END;
CLOSE cur;
DEALLOCATE cur;
-- Cleanup
DROP TABLE IF EXISTS #tblEmployee;
答案 4 :(得分:-2)
很明显,游标是指向记录集中当前行的指针。但除非可以使用,否则仅仅指点是没有意义的。这里有Fetch语句进入场景。这将从记录集中获取数据,将其存储在提供的变量中。因此,如果删除第一个fetch语句,while循环将不起作用,因为没有“FETCHED”记录进行操作,如果删除最后一个fetch语句,“while”将不会循环。
因此有必要让fetch语句循环遍历整个记录集。
答案 5 :(得分:-3)
简单地说你不能......这就是SQL中哪些语句的工作原理。您需要在循环之前获取第一行,然后在while语句中再次执行此操作。
更好的问题是如何摆脱光标并尝试在没有它的情况下解决你的问题。