- PR -

T-SQLで動的カーソルの実行について

1
投稿者投稿内容
mso
ぬし
会議室デビュー日: 2003/12/04
投稿数: 496
お住まい・勤務地: 宮城
投稿日時: 2005-01-04 12:07
msoです。

環境:
WindowsXP SP1
SqlServer2000



T-SQLでわからないことがあるので、教えてください。

動的にCURSORを生成して、処理を行うとしていたのですが
期待通りに動作をしてくれません。
#エラーが出ます
そこで下記のようなサンプルを作成し、テストをしたのですが
やはりエラーがでたままとなり動作をしてくれません。

そこでご存知の方がいたら何が良くないのか、
ひょっとしたら出来ないことをやろうとしているのか教えていただきたいと
思います

下記のソースの途中で生成したSQLをPRINTしている箇所があり、
そのSQLからSELECT文を実行すると正しく動作することは確認が
取れています。


実行したいT-SQL
コード:
CREATE PROCEDURE SP_SAMPLE2
	@W_TABLENAME VARCHAR(256)		--テーブル名称
	,@W_ROWNAME1 VARCHAR(256)		--列名称
	,@W_ROWNAME2 VARCHAR(256)		--列名称
AS
	--変数宣言
	DECLARE @SQL_STRING			VARCHAR(2048)
	DECLARE @STR_ID				VARCHAR(128)
	DECLARE @STR_NAME			VARCHAR(128)
BEGIN
	SET @SQL_STRING = 'DECLARE CUR_LOOP CURSOR LOCAL FOR'
	+ ' SELECT ' + @W_ROWNAME1 + ' ,' + @W_ROWNAME2
	+ ' FROM ' + @W_TABLENAME

	PRINT @SQL_STRING

	EXECUTE sp_executesql @SQL_STRING
	OPEN CUR_LOOP

	FETCH NEXT FROM CUR_LOOP
	INTO @STR_ID,@STR_NAME

	WHILE (@@FETCH_STATUS = 0)
	BEGIN

		PRINT '---------'
		PRINT @STR_ID
		PRINT @STR_NAME

		FETCH NEXT FROM CUR_LOOP
		INTO @STR_ID,@STR_NAME

	END

	--カーソルを閉じる
	CLOSE CUR_LOOP
	DEALLOCATE CUR_LOOP

END
GO





クエリアナライザから実行するときの方法
コード:
EXECUTE SP_SAMPLE2 'M_SYAIN','SYAIN_ID','SYAIN_NAME'



エラーメッセージ
コード:
サーバー : メッセージ 214、レベル 16、状態 2、プロシージャ sp_executesql、行 17
パラメータを @statement データ型をからプロシージャが必要とする ntext/nchar/nvarchar データ型に変換できません。


mso
ぬし
会議室デビュー日: 2003/12/04
投稿数: 496
お住まい・勤務地: 宮城
投稿日時: 2005-01-04 13:06
msoです。

引用:

エラーメッセージ
コード:
サーバー : メッセージ 214、レベル 16、状態 2、プロシージャ sp_executesql、行 17
パラメータを @statement データ型をからプロシージャが必要とする ntext/nchar/nvarchar データ型に変換できません。






宣言しているところをvarchar→NVARCHARにしたら上記のエラーが消えました。
ただ、
コード:
サーバー : メッセージ 16916、レベル 16、状態 1、プロシージャ SP_SAMPLE2、行 20
名前 'CUR_LOOP' を持つカーソルが存在しません。


というエラーが発生するようになっています。

ケアレスミスのにおいが漂うメッセージなので、
見直しをしたい再度実行していきます。
mso
ぬし
会議室デビュー日: 2003/12/04
投稿数: 496
お住まい・勤務地: 宮城
投稿日時: 2005-01-04 13:06
#2重投稿してしまったので、削除

[ メッセージ編集済み 編集者: mso 編集日時 2005-01-04 13:07 ]
mso
ぬし
会議室デビュー日: 2003/12/04
投稿数: 496
お住まい・勤務地: 宮城
投稿日時: 2005-01-04 13:11
msoです。

自己解決しました。

コード:
CREATE PROCEDURE SP_SAMPLE2
	@W_TABLENAME NVARCHAR(256)		--テーブル名称
	,@W_ROWNAME1 NVARCHAR(256)		--列名称
	,@W_ROWNAME2 NVARCHAR(256)		--列名称
AS
	--変数宣言
--	DECLARE @SQL_STRING			VARCHAR(2048)
	DECLARE @SQL_STRING			NVARCHAR(2048)
	DECLARE @STR_ID				NVARCHAR(128)
	DECLARE @STR_NAME			NVARCHAR(128)
BEGIN
	SET @SQL_STRING = 'DECLARE CUR_LOOP CURSOR FOR'
	+ ' SELECT ' + @W_ROWNAME1 + ' ,' + @W_ROWNAME2
	+ ' FROM ' + @W_TABLENAME

	PRINT @SQL_STRING

	EXECUTE sp_executesql @SQL_STRING

	OPEN CUR_LOOP

	FETCH NEXT FROM CUR_LOOP
	INTO @STR_ID,@STR_NAME

	WHILE (@@FETCH_STATUS = 0)
	BEGIN

		PRINT '---------'
		PRINT @STR_ID
		PRINT @STR_NAME

		FETCH NEXT FROM CUR_LOOP
		INTO @STR_ID,@STR_NAME

	END

	--カーソルを閉じる
	CLOSE CUR_LOOP
	DEALLOCATE CUR_LOOP

END
GO



具体的に修正したところは
1:varchar→nvarchar
2:'DECLARE CUR_LOOP CURSOR LOCAL FOR'

  'DECLARE CUR_LOOP CURSOR FOR'
とlocalを削除したところです。

2のlocalを削除したらうまくいった理由が良くわからないのですが、
動的カーソルはすべてグローバルになるのでしょうか?
それともローカルとかグローバルという概念がないものなのでしょうか?

未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-01-04 16:23
引用:

動的カーソルはすべてグローバルになるのでしょうか?
それともローカルとかグローバルという概念がないものなのでしょうか?



まず「動的カーソル」という言葉の意味が曖昧ですね。通常、「動的カーソル」といった場合、カーソルを開いたあとでもテーブルの変更が反映されるものを指します。また、データベース用語では、クエリ文字列などを「動的」に組み立てることを「動的ステートメント」と言うことがあります。

で、本題。カーソル自体は静的でも動的でも構いません。今回の場合は、カーソルを開くためのクエリ文字列を動的に組み立てて EXECUTE sp_executesql @SQL_STRING で実行していますね。sp_executesql で実行されるステートメントは、呼び出し元とは別スコープになるので、sp_executesql の内外でローカル変数にお互いにアクセスすることはできないわけです。sp_executesql の内外で同じ変数にアクセスしたい場合は @@ を付けてグローバル変数にしたり、(今回のように) LOCAL をはずしてグローバルカーソルにする必要があります。
1

スキルアップ/キャリアアップ(JOB@IT)