SQL Serverのカーソルを既存のコードに置き換えた経験や、手続き的な人がカーソルを使って解決する方法を知りたいと思っています。カーソルを置き換えるさまざまな方法は何ですか?
カーソルを使用して解決した問題は何ですか?どのようにカーソルを置き換えましたか?
SQL Serverのカーソルを既存のコードに置き換えた経験や、手続き的な人がカーソルを使って解決する方法を知りたいと思っています。カーソルを置き換えるさまざまな方法は何ですか?
カーソルを使用して解決した問題は何ですか?どのようにカーソルを置き換えましたか?
データセットをループしないようにしてください。
複数の行を一度に挿入、更新、削除することができます。複数の行の挿入例をここに示します。
INSERT INTO YourTable
(col1, col2, col3, col4)
SELECT
cola, colb+Colz, colc, @X
FROM ....
LEFT OUTER JOIN ...
WHERE...
ループを見ると、内部で何が行われたかを確認できます。挿入/削除/更新だけの場合は、単一のコマンドを使用するように書き換えます。 IFがある場合は、CASE文または挿入/削除/更新時のWHERE条件にすることができるかどうかを確認します。その場合は、ループを削除してsetコマンドを使用します。
私はループを取り、セットベースのコマンドに置き換え、実行時間を数分から数秒に減らしました。私は多くのネストされたループとプロシージャコールでプロシージャを実行し、ループを保持しました(挿入/削除/更新のみを使用することは不可能でした)が、カーソルを削除し、ロック/ブロッキングと大幅なパフォーマンスの向上も見られませんでした。ここではセットの上にカーソルがループよりも優れている2つのループ方法...
あなたがループしている場合は、このような何かです:
--this looks up each row for every iteration
DECLARE @msg VARCHAR(250)
DECLARE @hostname sysname
--first select of currsor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
WHILE @hostname is not null
BEGIN
set @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(@hostname) + ' '
+ 'testing "'
print @msg
--EXEC (@msg)
--next select of cursor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
and hostname > @hostname
END
あなたはアイテムの合理的なセット(ない100,000持っている場合)あなたがループすることができます:
--this will capture each Key to loop over
DECLARE @msg VARCHAR(250)
DECLARE @From int
DECLARE @To int
CREATE TABLE #Rows
(
RowID int not null primary key identity(1,1)
,hostname varchar(100)
)
INSERT INTO #Rows
SELECT DISTINCT hostname
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
SELECT @From=0,@[email protected]@ROWCOUNT
WHILE @From<@To
BEGIN
SET @[email protected]+1
SELECT @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(hostname) + ' '
+ 'testing "'
FROM #Rows WHERE [email protected]
print @msg
--EXEC (@msg)
END
多くの場合、手続き型プログラミングに使用されるアプリケーション開発者は、習慣から逸脱します.SQLであっても手続き的にすべてを実行しようとします。
多くの場合、適切なパラメータを持つSELECTを使用することができます。または、UPDATE文を処理していることがあります。
ポイントは本当にあります:あなたは設定された操作で考え始める必要がありますし、RDBMSにあなたが何をしたいかを教えてください。
これに単一の「正しい」回答を与えるのは難しいです。具体的な例を示す必要がほとんどあります。
マーク
私は、特定の年に関連する財務データの合計を計算したコードを書いています。四半期ごとに、現在の四半期の値を実行中の合計に加算し、NULLを適切に処理して、前の四半期の実行中の合計が現在の四半期の値がNULLのときに引き継ぐようにしなければなりませんでした。
元はカーソルを使用してこれを行い、機能的な観点からはこれはビジネス要件を満たしていました。技術的な観点から見ると、データ量が増えるにつれてコードが指数関数的に長くなったため、これはショーストッパーとなりました。解決策は、カーソルを機能的要件を満たし、パフォーマンスの問題を排除した相関サブクエリで置き換えることでした。
これが役に立てば幸い、
ビル
私はWHILEループを持ついくつかのカーソルを交換しました。
DECLARE @SomeTable TABLE
(
ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
SomeNumber int,
SomeText varchar
)
DECLARE @theCount int
DECLARE @theMax int
DECLARE @theNumber int
DECLARE @theText varchar
INSERT INTO @SomeTable (SomeNumber, SomeText)
SELECT Number, Text
FROM PrimaryTable
SET @theCount = 1
SELECT @theMax = COUNT(ID) FROM @SomeTable
WHILE (@theCount <= @theMax)
BEGIN
SET @theNumber = 0
SET @theText = ''
SELECT @theNumber = IsNull(Number, 0), @theText = IsNull(Text, 'nothing')
FROM @SomeTable
WHERE ID = @theCount
-- Do something.
PRINT 'This is ' + @theText + ' from record ' + CAST(@theNumber AS varchar) + '.'
SET @theCount = @theCount + 1
END
PRINT 'Done'