質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

PL/SQL

PL/SQL (Procedural Language/Structured Query Language) はOracle CorporationによるSQL(非手続き型言語)を手続き型言語に拡張させるために開発されたプログラミング言語です。

Q&A

解決済

2回答

3366閲覧

OraclePROCEDUREのOUTパラメータでTYPEを指定したとき、C#で受け渡しを行いたい

mShintani

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

PL/SQL

PL/SQL (Procedural Language/Structured Query Language) はOracle CorporationによるSQL(非手続き型言語)を手続き型言語に拡張させるために開発されたプログラミング言語です。

0グッド

0クリップ

投稿2020/11/13 05:26

編集2020/11/13 08:35

前提・実現したいこと

Oracle11gでPROCEDUREを作成しました。
OUTパラメータとして、TYPEをしていしております。
C#プログラムからこのPROCEDUREを呼び出したときにOUTパラメータを受け取り、
結果表示したいと考えております。

発生している問題・エラーメッセージ

PROCEDUREを呼び出した際にOUTパラメータの受け取り時にエラーが発生します。

「'TB_P_TEST'の呼出しで、引数の数または型が正しくありません。」

OUTパラメータを受け取り方がわかっておりません。

該当のソースコード

【Oracle側】
<TYPE>

CREATE OR REPLACE TYPE TB_T_KAIKOBI FORCE AS OBJECT ( sKaikobi VARCHAR2(8), iTeiinCheck NUMBER(1,0) ) /
CREATE OR REPLACE TYPE TB_T_KAIKOBI_A FORCE AS TABLE OF TB_T_KAIKOBI /

<PROCEDURE>

CREATE OR REPLACE PROCEDURE TB_P_TEST ( p_in_iBumon IN NUMBER , p_out_aKaikobi OUT TB_T_KAIKOBI_A ) IS infoKaikobi TB_T_KAIKOBI; BEGIN /* 返り値セット */ p_out_aKaikobi := TB_T_KAIKOBI_A(); p_out_aKaikobi.extend(2); --2コの配列 --開講日情報の1つ目の要素(1-1-1) infoKaikobi := TB_T_KAIKOBI('20201112',0); p_out_aKaikobi(1) := infoKaikobi; --開講日情報の2つ目の要素(1-1-2) infoKaikobi := TB_T_KAIKOBI('20201113',1); p_out_aKaikobi(2) := infoKaikobi; COMMIT; END; /

※INパラメータの「p_in_iBumon」は実際には使用しますが、
テストPROCEDUREでは使用しなくしております。

【C#側】

private void btnTest_Click(object sender, EventArgs e) { List<object> listValue = new List<object>(); listValue.Add(1); List<OleDbParameter> listInitOut = GetProcedure(listValue, "TB_P_TEST"); } /// <summary> /// プロシージャ情報の取得 /// </summary> public List<OleDbParameter> GetProcedure(List<object> listValue, string strProcedure) { //データベースの接続先を指定 using (OleDbConnection OraConn = new OleDbConnection(/*接続先文字列*/)) { using (OleDbCommand Cmd = new OleDbCommand()) { //データベース接続を開く OraConn.Open(); Cmd.Connection = OraConn; //コマンドタイプをストアドプロシージャにする Cmd.CommandType = CommandType.StoredProcedure; //実行するストアドプロシージャを指定 Cmd.CommandText = strProcedure; //ストアドプロシージャのin用パラメータ作成 List<string> listInName = new List<string>(); List<OleDbType> listInType = new List<OleDbType>(); listInName.Add("1"); listInType.Add(OleDbType.Decimal) //Inパラメータの追加 int intInPrameter = 0; foreach (string strName in listInName) { Cmd.Parameters.Add(strName, listInType[intInPrameter]).Value = listValue[intInPrameter]; intInPrameter++; } //ストアドプロシージャのout用パラメータ作成 List<OleDbParameter> listOutpara = new List<OleDbParameter>(); //リストのタイプを作成 List<string> listOutName = new List<string>(); List<OleDbType> listOutType = new List<OleDbType>(); OutParamInfo outInfo = new OutParamInfo(); listOutName.Add("開講日情報"); //←ここのセット方法がどのようにすればよいかがわかっておりません listOutType.Add(OleDbType.Binary); //←ここのセット方法がどのようにすればよいかがわかっておりません //Outパラメータの追加 int intOutPrameter = 0; foreach (string strName in listOutName) { OleDbParameter outPara = new OleDbParameter(strName, listOutType[intOutPrameter]); outPara.Direction = ParameterDirection.Output; outPara.Size = 40; listOutpara.Add(outPara); Cmd.Parameters.Add(outPara); intOutPrameter++; } //ストアドプロシージャの実行 Cmd.ExecuteNonQuery(); return listOutpara; } } }

上記からODP.NETを使用したソースに変更しました。
TYPEを使用しないPROCEDUREの場合、成功しました。

以下は配列をやめてみて、TYPEのみの受け渡しを記載しました。

実行すると「Cmd.ExecuteNonQuery(); 」の部分でエラーが発生します。
TYPEでない場合、成功するので、listOutType.Add(OracleDbType.Object); が
悪いのか、「listOutName.Add("p_out_Kaikobi"); 」の設定が悪いと思っております。

バインディングというのがピンときておりません。

CREATE OR REPLACE PROCEDURE TB_P_TEST2 ( p_in_iBumon IN NUMBER , p_out_Kaikobi OUT TB_T_KAIKOBI ) IS BEGIN /* 返り値セット */ p_out_Kaikobi := TB_T_KAIKOBI('20201112',0); COMMIT; END; /
private void btnTest_Click(object sender, EventArgs e) { List<object> listValue = new List<object>(); listValue.Add(1); List<OracleParameter> listInitOut = GetProcedure(listValue, "TB_P_TEST2"); } /// <summary> /// プロシージャ情報の取得 /// </summary> public List<OracleParameter> GetProcedure(List<object> listValue, string strProcedure) { //データベースの接続先を指定 OracleConnection OraConn = new OracleConnection(); OraConn.ConnectionString = /*接続先文字列*/; OraConn.Open(); OracleCommand Cmd = new OracleCommand(); //データベース接続を開く OraConn.Open(); Cmd.Connection = OraConn; //コマンドタイプをストアドプロシージャにする Cmd.CommandType = CommandType.StoredProcedure; //実行するストアドプロシージャを指定 Cmd.CommandText = strProcedure; //ストアドプロシージャのin用パラメータ作成 List<string> listInName = new List<string>(); List<OracleDbType> listInType = new List<OracleDbType>(); listInName.Add("1"); listInType.Add(OracleDbType.Decimal) //Inパラメータの追加 int intInPrameter = 0; foreach (string strName in listInName) { Cmd.Parameters.Add(strName, listInType[intInPrameter]).Value = listValue[intInPrameter]; intInPrameter++; } //ストアドプロシージャのout用パラメータ作成 List<OracleParameter> listOutpara = new List<OracleParameter>(); //リストのタイプを作成 List<string> listOutName = new List<string>(); List<OracleDbType> listOutType = new List<OracleDbType>(); OutParamInfo outInfo = new OutParamInfo(); listOutName.Add("p_out_Kaikobi"); //←ここのセット方法がどのようにすればよいかがわかっておりません listOutType.Add(OracleDbType.Object); //←Objectに変更したところ、型が正しくありませんは解消されました //Outパラメータの追加 int intOutPrameter = 0; foreach (string strName in listOutName) { OracleParameter outPara = new OracleParameter(strName, listOutType[intOutPrameter]); outPara.Direction = ParameterDirection.Output; outPara.Size = 40; listOutpara.Add(outPara); Cmd.Parameters.Add(outPara); intOutPrameter++; } //ストアドプロシージャの実行 Cmd.ExecuteNonQuery(); //←ここで「p_out_Kaikobi」バインディングが無効ですとなります。 return listOutpara; } } }

試したこと

「OleDbType」を「Binary」としておりますが、他の値でも一通り試してみました。
ネット調べてもC#で%TYPEの取得方法が見つからず、苦慮しております。

補足情報(FW/ツールのバージョンなど)

開発環境は以下の通り
C#
Oracle11g
.Net3.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mShintani

2020/11/13 05:53

ご指摘ありがとうございます。修正いたしました。
退会済みユーザー

退会済みユーザー

2020/11/13 07:00

ODP.NETを試してみてはどうでしょう。
mShintani

2020/11/13 07:25

情報ありがとうございます。 やはりODP.NETにしないと解決しませんか。 可能であればこの構造を少し修正して使用したかったのですが(前任者からの引継ぎであまりわかっていないもので) ODP.NETは初めて使用するので、よいサイトなどございましたら、教えていただけますと幸いです。 ODP.NETで実装を試みてみます。
退会済みユーザー

退会済みユーザー

2020/11/13 07:40 編集

接続文字列は変わるかもしれませんが、データ取得や実行の構文は基本的に他のデータプロバイダーと変わらないので、それほど迷うところは無いかと思います。ODP.NET以外の接続方法だとOracle固有の機能やデータ型が使えなかったりするらしいので、物は試しというやつですね。 いきなり本番のソースに組み込まずに、別プロジェクトで小さいサンプルを作って試してみた方がよいかと思います。
mShintani

2020/11/13 07:48

ありがとうございます。 >ODP.NET以外の接続方法だとOracle固有の機能やデータ型が使えなかったりするらしいので  ⇒そうなんですね。   大変参考になります。 一度、サンプルで実装してみます。
mShintani

2020/11/13 08:37

質問内容をODP.NETに変更した分を追記し、PROCEDUREも配列ではなく、まずはTYPEの受け渡しのみにしてみました。 前回のエラーは解消したのですが、別のエラーとなってしまいました。 自分でも調べてはいるのですが、納期の都合上、こちらに質問として載せさせていただきます。
guest

回答2

0

自己解決

今回は解決にはならなかったのですが、PROCEDUREの更新方法を大きく見直して、問題は解決しました。
実施したこととしては、OUTでもらうはずのものをPROCEDURE内でテーブルに更新して、更新後に結果(0:OK、1:NG)を返す。その後、OKが返ってきてから、更新したテーブルをSELECTするという方法にしました。

投稿2021/03/25 08:12

mShintani

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ユーザー定義型をInputパラメータで渡しているサンプルコードがありました、がOutputパラメータでも使用出来るかどうかは定かではありません。
ODP.NET/C# を使ってストアどプロシージャに一時BLOBデータを渡し方、およびユーザー定義型での受け渡し方のサンプル

ODP.NETには管理対象ドライバと管理対象外ドライバがありますが、管理対象ドライバではObject型は使用できないかもしれません。
OracleDbTypeの列挙

投稿2020/11/13 10:53

編集2020/11/13 10:56
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mShintani

2020/11/16 09:44

radianさん、KOZ6.0さん。ご回答ありがとうございます。 お二方のやり方を参考にしたのですが、OUTパラメータをUDTでもらうのはできませんでした。 今回は解決にはならなかったのですが、PROCEDUREの更新方法を大きく見直して、問題は解決しました。 実施したこととしては、OUTでもらうはずのものをPROCEDURE内でテーブルに更新して、更新後に結果(0:OK、1:NG)を返す。その後、OKが返ってきてから、更新したテーブルをSELECTするという方法にしました。
退会済みユーザー

退会済みユーザー

2020/11/17 01:21

なるほど、違う方法で解決したのですね。 解決したのであれば、それを自分で回答に記入してベストアンサーを付けて終了させてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問