比方说,我有以下简单的表格变量。
declare @databases table
(
DatabaseID int,
Name varchar(15),
Server varchar(15)
)
-- insert a bunch rows into @databases
如果我想遍历这些行,声明并使用游标是我唯一的选择吗?还有别的办法吗?
首先,你应该绝对确定你需要遍历每一行--在我能想到的每一种情况下,基于集合的操作会执行得更快,而且通常会使用更简单的代码。
根据你的数据,可能只需要使用选择语句就可以实现循环,如下图所示。
Declare @Id int
While (Select Count(*) From ATable Where Processed = 0) > 0
Begin
Select Top 1 @Id = Id From ATable Where Processed = 0
--Do some processing here
Update ATable Set Processed = 1 Where Id = @Id
End
另一种方法是使用一个临时表。
Select *
Into #Temp
From ATable
Declare @Id int
While (Select Count(*) From #Temp) > 0
Begin
Select Top 1 @Id = Id From #Temp
--Do some processing here
Delete #Temp Where Id = @Id
End
你应该选择哪种方案,其实取决于你的数据结构和数量。
注意:如果你使用的是SQL Server,你最好使用。
WHILE EXISTS(SELECT * FROM #Temp)
使用 "COUNT "将不得不触及表中的每一条记录,而 "EXISTS "只需要触及第一条记录(见下面Josef'的答案)。
我是这样做的。
Select Identity(int, 1,1) AS PK, DatabaseID
Into #T
From @databases
Declare @maxPK int;Select @maxPK = MAX(PK) From #T
Declare @pk int;Set @pk = 1
While @pk <= @maxPK
Begin
-- Get one record
Select DatabaseID, Name, Server
From @databases
Where DatabaseID = (Select DatabaseID From #T Where PK = @pk)
--Do some processing here
--
Select @pk = @pk + 1
End
[编辑] 因为我第一次看问题时可能跳过了"变量"这个词,所以这里有一个更新的回答......
declare @databases table
(
PK int IDENTITY(1,1),
DatabaseID int,
Name varchar(15),
Server varchar(15)
)
-- insert a bunch rows into @databases
--/*
INSERT INTO @databases (DatabaseID, Name, Server) SELECT 1,'MainDB', 'MyServer'
INSERT INTO @databases (DatabaseID, Name, Server) SELECT 1,'MyDB', 'MyServer2'
--*/
Declare @maxPK int;Select @maxPK = MAX(PK) From @databases
Declare @pk int;Set @pk = 1
While @pk <= @maxPK
Begin
/* Get one record (you can read the values into some variables) */
Select DatabaseID, Name, Server
From @databases
Where PK = @pk
/* Do some processing here */
/* ... */
Select @pk = @pk + 1
End