例えば、次のような単純なテーブル変数があるとします。
declare @databases table
(
DatabaseID int,
Name varchar(15),
Server varchar(15)
)
-- insert a bunch rows into @databases
行を反復処理したい場合、カーソルを宣言して使用することが唯一の選択肢でしょうか?他に方法はありますか?
まず最初に、各行を反復処理する必要があるかどうか、絶対に確認する必要があります。
データによっては、以下のようにselect文だけでループ処理が可能な場合もあります。
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's answerを参照)。
私ならこうします。
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
[編集] 最初に質問を読んだときに、おそらく "variable"という言葉を読み飛ばしてしまったので、ここで回答を更新します...
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