- PR -

VB6でテーブル型を返すストアドプロシージャをレコードセットで取得する方法について

投稿者投稿内容
未記入
会議室デビュー日: 2007/10/16
投稿数: 3
投稿日時: 2007-10-16 11:27
お世話になります。
SQL Server 2000上にテーブル型を返すストアドプロシージャを作成し、クエリーアナライザで検証後、VB6.0でこのストアドプロシージャを利用しようとADO(OLE DB)レコードセットを生成しますが、いざ読み出そうとすると「オブジェクトが閉じている場合は、操作は許可されません」と出て、読み出す事が出来ません。
※クエリーアナライザでは、結果を正しく返してきます。

そもそも、ストアドプロシージャを実行した後、メモリー上から解放されるので、継続して結果を操作することは出来ない気もしています。

ストアドプロシージャで必要な処理を行った結果をテーブル型やテンポラリーテーブルに保存し読出したい場合、どのような方法で実現できるのでしょうか?
※複数クライアントから利用する事を考え、固定的にテーブルを作成して、それに結果を格納して利用する方法は取れません。

例)
◆ストアドプロシージャ
CREATE PROCEDURE TEST
@kana AS varchar(20)
AS

DECLARE @tmpTOKUI table
(
code int NOT NULL,
name1 varchar(40) NOT NULL,
kana varchar(40) ,
)

INSERT INTO @tmpTOKUI
SELECT code, name1, kana
FROM masTOKUI
WHERE kana LIKE '%'+@kana+'%'

SELECT * FROM @tmpTOKUI

◆VB6ソース
Dim adoRS As New ADODB.Recordset

adoRS.Open "TEST 'yama'", CN, adOpenDynamic, adLockOptimistic

if adoRS.EOF then ←エラー発生



上総
大ベテラン
会議室デビュー日: 2006/06/22
投稿数: 107
投稿日時: 2007-10-16 12:06
ADOでのストアードの呼び出し方は分かりませんが、
テンポラリテーブルを使用するのであれば

1.DBへ接続(セッションの確立)
2.テンポラリテーブルを作成
3.ストアードか何かで、2.のテンポラリテーブルへデータを追加
4.テンポラリテーブルの呼び出し
5.DBから切断(セッションの破棄によりテンポラリテーブルを自動消去)

で、問題無いかと思います。

参考資料
 ISBN:4-7741-1755-2
 [改定新版]SQL ポケットリファレンス

 ※一応【SQL Server 6.5/7.0/2000】に対応との記述あり。
nakaP
大ベテラン
会議室デビュー日: 2005/09/27
投稿数: 138
お住まい・勤務地: 高知
投稿日時: 2007-10-16 12:54
こんにちは。

たぶん最初のINSERT文の結果が返ってきているのだと思います。
SET NOCOUNTを加えるといいでしょう。

#関係ないですが、この一時テーブル必要ですかね?
上総
大ベテラン
会議室デビュー日: 2006/06/22
投稿数: 107
投稿日時: 2007-10-16 21:19
引用:
--------------------------------------------------------------------------------

J.J.さんの書き込み (2007-10-16 12:54) より:
#関係ないですが、この一時テーブル必要ですかね?

--------------------------------------------------------------------------------

例の通りの結果が必要であれば、特に必要ないですね。
OakBow
ベテラン
会議室デビュー日: 2007/09/15
投稿数: 51
投稿日時: 2007-10-16 22:29
## 一時テーブル(テンポラリテーブル)じゃなくて
## テーブル変数なんですが。。

答えは出ていますが、
SELECT * FROM @tmpTOKUI
で通常のレコードセットが返されますので、
テーブル変数であるかどうかは特に意識せず
値の取得はできると思います。
一時テーブルであれば
SELECT * FROM #tmpTOKUI
SELECT * FROM ##tmpTOKUI
とかになりますね。

J.Jさんの仰るように、余計な出力が行われないように
してしまえば解決するんじゃないでしょうか。
一部のカーソルは使えない制限があった気はしますけれど。
adOpenDynamicとか指定しても無視されるかも。
前方読み取りカーソルしか使わないのでよく知りませんが。

adoRS.EOFとかでエラーが発生するのは、たいてい
レコードセットを吐かないクエリやストアドを実行
したときだったりします。

ちなみに、 SELECT * FROM @tmpTOKUI で返されるのは
テーブル型ではなかったと思います。
なんていう型なのか名前は忘れてしまいましたけれど。

蛇足ですが、ADO+MSSQLではPrepared Statementが使えますので、
ADO.Commandオブジェクトを使ってパラメータを与えて
ストアドを実行した方がいいかな、と思います。
手間は増えますが関数なりクラスなり作ってしまえば
あとは楽なもんですし。
nakaP
大ベテラン
会議室デビュー日: 2005/09/27
投稿数: 138
お住まい・勤務地: 高知
投稿日時: 2007-10-16 23:55
引用:

## 一時テーブル(テンポラリテーブル)じゃなくて
## テーブル変数なんですが。。


そうなんですねorz
両方とも使ったことないんで混同してました。
以下自分のために:
テーブル型
http://msdn2.microsoft.com/ja-jp/library/ms175010.aspx
一時テーブル(CREATE TABLE 解説部分)
http://msdn2.microsoft.com/ja-jp/library/ms174979.aspx

本題のほうですが、INSERT INTO 〜 SELECT文を挟むようにSET NOCOUNTを操作すれば
望む結果が得られると思います。

コード:
SET NOCOUNT ON
INSERT INTO @tmpTOKUI SELECT 〜
SET NOCOUNT OFF

SELECT * FROM @tmpTOKUI

GO


OakBow
ベテラン
会議室デビュー日: 2007/09/15
投稿数: 51
投稿日時: 2007-10-17 01:23
>本題のほうですが、INSERT INTO 〜 SELECT文を挟むようにSET NOCOUNTを操作すれば
>望む結果が得られると思います。

あ、書いてなかったですが。。
SET NOCOUNT ONはストアドの最初のあたりに書いてそのまんまにするのが
普通です。
SQL Server2000でも、ストアドを新規作成するとこれが入った状態で
雛形が生成されたと思うんですが、消しちゃったか例に含めてないだけかな?
CREATE PROCEDURE TEST
@kana AS varchar(20)
AS
の下あたりに書く感じ。
ストアド書くときの必須のおまじないみたいなもんです。MSSQLでは。

と言う訳で、SET NOCOUNT OFFは特にいらないです。
未記入
会議室デビュー日: 2007/10/16
投稿数: 3
投稿日時: 2007-10-17 08:29
多数のレスありがとうございます。

テンポラリーを作成してから、ストアドを実行する方法に
ついては、平行して検証し、望む結果を得られました。

SET NO COUNT...の方法にに付いて試してみたいと思います。

ありがとうございます。

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