利用カーソルの動的SQLを格納手続き
-
20-08-2019 - |
質問
私の動的SQL文を私に保存されている。いのに対して繰り返し処理を実行する結果をカーソルを移動させます。んも考えられない早いスピートと右の構文です。ここで僕がやってます。
SELECT @SQLStatement = 'SELECT userId FROM users'
DECLARE @UserId
DECLARE users_cursor CURSOR FOR
EXECUTE @SQLStatment --Fails here. Doesn't like this
OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC asp_DoSomethingStoredProc @UserId
END
CLOSE users_cursor
DEALLOCATE users_cursor
何をなす。
解決
カーソルだけが実行されている文の宣言カーソルの一部を作る、select文を受け入れます。サーバーがグローバルカーソルを使用する必要があります作業するには、以下のため。
Declare @UserID varchar(100)
declare @sqlstatement nvarchar(4000)
--move declare cursor into sql to be executed
set @sqlstatement = 'Declare users_cursor CURSOR FOR SELECT userId FROM users'
exec sp_executesql @sqlstatement
OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId
WHILE @@FETCH_STATUS = 0
BEGIN
Print @UserID
EXEC asp_DoSomethingStoredProc @UserId
FETCH NEXT FROM users_cursor --have to fetch again within loop
INTO @UserId
END
CLOSE users_cursor
DEALLOCATE users_cursor
あなたはグローバルカーソルを使用しないように必要がある場合は、、あなたはまた、一時テーブルにあなたの動的SQLの結果を挿入し、カーソルを移入し、そのテーブルを使用することができます。
Declare @UserID varchar(100)
create table #users (UserID varchar(100))
declare @sqlstatement nvarchar(4000)
set @sqlstatement = 'Insert into #users (userID) SELECT userId FROM users'
exec(@sqlstatement)
declare users_cursor cursor for Select UserId from #Users
OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC asp_DoSomethingStoredProc @UserId
FETCH NEXT FROM users_cursor
INTO @UserId
END
CLOSE users_cursor
DEALLOCATE users_cursor
drop table #users
他のヒント
このコードでは、カーソルと動的な列のための非常に良い例です。
ALTER PROCEDURE dbo.spTEST
AS
SET NOCOUNT ON
DECLARE @query NVARCHAR(4000) = N'' --DATA FILTER
DECLARE @inputList NVARCHAR(4000) = ''
DECLARE @field sysname = '' --COLUMN NAME
DECLARE @my_cur CURSOR
EXECUTE SP_EXECUTESQL
N'SET @my_cur = CURSOR FAST_FORWARD FOR
SELECT
CASE @field
WHEN ''fn'' then fn
WHEN ''n_family_name'' then n_family_name
END
FROM
dbo.vCard
WHERE
CASE @field
WHEN ''fn'' then fn
WHEN ''n_family_name'' then n_family_name
END
LIKE ''%''+@query+''%'';
OPEN @my_cur;',
N'@field sysname, @query NVARCHAR(4000), @my_cur CURSOR OUTPUT',
@field = @field,
@query = @query,
@my_cur = @my_cur OUTPUT
FETCH NEXT FROM @my_cur INTO @inputList
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @inputList
FETCH NEXT FROM @my_cur INTO @inputList
END
RETURN
非リレーショナルデータベース(IDMS誰ですか?)ODBC接続を介しての操作カーソルと動的SQLが唯一のルート思わ当時の一つとしての資格ます。
select * from a where a=1 and b in (1,2)
は、1秒未満で実行されます句でなしのキーセットを使用するように書き換えながら応答するために45分かかります
select * from a where (a=1 and b=1)
union all
select * from a where (a=1 and b=2)
B列のための文でindidivudal文を作成し、動的SQLはWHERE句で使用するよりもはるかに高速であるとして、それらを実行するために、カーソルを使用して、1145行が含まれている場合。愚かなちょっと?
そして、はい、カーソルのは、使用すべきであるリレーショナルデータベースには時間がありません。私はちょうど私がカーソルループが数倍速くなり、インスタンス間で来ていると信じていないことができます。
まず最初にすべての可能性であれば、カーソルを使用しないでください。ここでは、せずにあなたが行うことができないと思われるときにそれを根絶するためのいくつかのリソースがあります:
あなたのカーソルを失う15個の方法...パート1、はじめに存在しなければなりませんの
カーソルをせずに行ごとの処理
これは、しかし、あなたはすべての後に1で立ち往生することができる、と述べた - 私はそれらのいずれかが適用されていることを確認するためにあなたの質問から十分に知りません。そのような場合、あなたは別の問題を持っている - あなたのカーソルのSELECT文は、の実際ののSELECT文ではなく、EXECUTE文でなければなりません。あなたは立ち往生してます。
しかし、一時テーブルの使用について(私が書いていた間、入って来た)cmsjrからの回答を参照してください。私は
.... のグローバルのカーソル "プレーン" のものよりもさらにを避けるだろう後の切り替えてからOracle、SQLサーバー(事業主)、更にカーソルを支援SQLサーバーは遅れています。カーソルは必ずしも悪にも必要なものの方が早く、時にはリーダーと調整の複雑なクエリの再配置または追加を最適化します。の"カーソルの悪意見書"はすでに顕著にSQLサーバーです。
ねこの答えは、スイッチをOracleまたはMSの手掛かり
- Oracleの実行を即時にカーソル
- ループを通じて暗黙的にカーソル (
for
ループを暗黙のうちに を定義し/開閉す カーソルを!)
私はあなたと共有したいもう一つの例があります
:D
http://www.sommarskog.se/dynamic_sql.html#cursor0する
は、SQL Serverの別のオプションは、その後、ストアドプロシージャでテーブル変数に動的なクエリのすべてを行う照会し、それを処理するためにカーソルを使用することです。恐ろしいカーソルの議論については:)、私は適切に設定している場合、いくつかの状況では、カーソルが実際に速くすることができることを示した研究を見てきました。 (私のため;)必要なクエリが複雑すぎる、またはちょうどない人間とき、私は彼らに自分自身を使用しています。)可能
このコードでは、あなたのために役立つことがあります。
SQL Serverでカーソル使用の例
DECLARE sampleCursor CURSOR FOR
SELECT K.Id FROM TableA K WHERE ....;
OPEN sampleCursor
FETCH NEXT FROM sampleCursor INTO @Id
WHILE @@FETCH_STATUS <> -1
BEGIN
UPDATE TableB
SET
...