C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Oracle Package呼出時エラー PLS-00306

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■100051 / inTopicNo.1)  Oracle Package呼出時エラー PLS-00306
  
□投稿者/ AS702 (1回)-(2022/06/30(Thu) 19:15:50)

分類:[C#] 

Oracle Package呼出時エラー PLS-00306

お世話になっております。
C#よりOracleのPackageを呼び出すコーディングを行っておりますが、以下のエラーとなりデータの取得ができませんでした。
どのようにしたら、データが取得できるかご教授願います。


**************エラー内容Start**************
ORA-06550: 行1、列7:
PLS-00306: '検索'の呼出しで、引数の数または型が正しくありません。
ORA-06550: 行1、列7:
PLS-00306: '検索'の呼出しで、引数の数または型が正しくありません。
ORA-06550: 行1、列7:
PL/SQL: Statement ignored
**************エラー内容End**************

**************OraclePackage定義Start**************
CREATE OR REPLACE PACKAGE P_顧客DB AS
type 入力情報 is table of VARCHAR2(60) index by BINARY_INTEGER;
type 出力情報 is table of VARCHAR2(60) index by BINARY_INTEGER;
PROCEDURE 検索( In_更新有無 IN NUMBER,
In_入力項目 IN 入力情報,    ← 本項目に店番(1)、顧客番号(123456)をセットして、該当レコードを取得します。
Out_出力項目 OUT 出力情報 ); ← 本項目にselect文で取得したデータが入ります。(配列項目数:160個)
END P_顧客DB;
/
**************OraclePackage定義End**************

**************C#コーディングStart**************
DataSet dSet = new DataSet();

//データベース接続を開く
OracleConnection conn = new OracleConnection(P.Default.conn_string);
conn.Open();

string [] p_In_入力項目 = new string[2];
string [] p_In_出力項目 = new string[160];
OracleCommand cmd = new OracleCommand();

cmd.Connection = conn;
cmd.BindByName = true;

p_In_入力項目[0] = "1";
p_In_入力項目[1] = "123456";

cmd.Parameters.Add("O_顧客検索", OracleDbType.Varchar2, 60, p_In_出力項目, ParameterDirection.ReturnValue);
cmd.Parameters.Add("int_更新有無", OracleDbType.Decimal, 0, ParameterDirection.Input);
cmd.Parameters.Add("I_顧客検索", OracleDbType.Varchar2, 60, p_In_入力項目, ParameterDirection.Input);
cmd.CommandText = "Begin P_顧客DB.検索(:int_更新有無,:I_顧客検索,:O_顧客検索);
END;";

cmd.ExecuteNonQuery(); ←ここでエラー発生

//データの取得方法もご教授願いたいです。

return dSet;
**************C#コーディングEnd**************

よろしくお願いいたします。
引用返信 編集キー/
■100052 / inTopicNo.2)  Re[1]: Oracle Package呼出時エラー PLS-00306
□投稿者/ KOZ (242回)-(2022/06/30(Thu) 19:33:26)
2022/06/30(Thu) 19:49:23 編集(投稿者)

No100051 (AS702 さん) に返信

連想配列を使うには、OracleParameter の CollectionType プロパティを OracleCollectionType.PLSQLAssociativeArray にする必要があります。
また、配列サイズを OracleParameter.Size にセットします。

「PL/SQL連想配列の使用」
https://www.oracle.com/jp/database/technologies/oramag/o17odp.html

配列を受け取るときは ArrayBindSize を設定する必要があったと思います。
cmd.Parameters("O_顧客検索").ArrayBindSize = Enumerable.Repeat<int>(60, 160).ToArray();
引用返信 編集キー/
■100053 / inTopicNo.3)  Re[2]: Oracle Package呼出時エラー PLS-00306
□投稿者/ KOZ (243回)-(2022/07/01(Fri) 00:30:47)
No100052 (KOZ) に返信

SELECT した結果を取得するなら、こういう方法もあります。

「Oracleでパイプライン表関数を利用して表データを返却する」
https://knkryo.blogspot.com/2013/12/oracle_24.html

こうして作成した PACKAGE は

SELECT * FROM TABLE(PKG_DATE_TABLE_UTIL.GET_YM_TABLE(202205, 202206))

のように使用できます。
引用返信 編集キー/
■100055 / inTopicNo.4)  Re[1]: Oracle Package呼出時エラー PLS-00306
□投稿者/ radian (58回)-(2022/07/01(Fri) 08:58:19)
2022/07/01(Fri) 09:07:44 編集(投稿者)

No100051 (AS702 さん) に返信

ストアドの場合、
OracleCommand.CommandText=プロシージャ名
OracleCommand.CommandType=CommandType.StoredProcedure
みたいな感じだった気が。

http://hiros-dot.net/VBNET2005/Other/ODPStored/ODPStored03.htm
引用返信 編集キー/
■100056 / inTopicNo.5)  Re[2]: Oracle Package呼出時エラー PLS-00306
□投稿者/ KOZ (244回)-(2022/07/01(Fri) 09:32:41)
No100055 (radian さん) に返信
> ストアドの場合、
> OracleCommand.CommandText=プロシージャ名
> OracleCommand.CommandType=CommandType.StoredProcedure
> みたいな感じだった気が。
>
> http://hiros-dot.net/VBNET2005/Other/ODPStored/ODPStored03.htm

たしかにそれでもいけますが、このような "BEGIN プロシジャ名(:引数); END;" の形でもオッケーです。





引用返信 編集キー/
■100058 / inTopicNo.6)  Re[3]: Oracle Package呼出時エラー PLS-00306
□投稿者/ radian (59回)-(2022/07/01(Fri) 10:15:13)
No100056 (KOZ さん) に返信
> ■No100055 (radian さん) に返信
>>ストアドの場合、
>>OracleCommand.CommandText=プロシージャ名
>>OracleCommand.CommandType=CommandType.StoredProcedure
>>みたいな感じだった気が。
>>
>>http://hiros-dot.net/VBNET2005/Other/ODPStored/ODPStored03.htm
>
> たしかにそれでもいけますが、このような "BEGIN プロシジャ名(:引数); END;" の形でもオッケーです。

なるほど、それは知りませんでした。
引用返信 編集キー/
■100088 / inTopicNo.7)  Re[3]: Oracle Package呼出時エラー PLS-00306
□投稿者/ KOZ (246回)-(2022/07/02(Sat) 08:44:40)
2022/07/04(Mon) 03:42:33 編集(投稿者)

No100056 (KOZ) に返信
自分のメモ代わりに書いておきます。
ストアドを呼ぶ際、引数の指定の仕方が2種類あります。

「位置表記法と名前表記法」
https://www.shift-the-oracle.com/plsql/positional-named-notation.html

(1) CommandType = Text の場合

位置表記法が使われ、CommandText に設定された SQL をそのままサーバーに送ります。

BGEIN HOGE(:FOO, :BAR); END;

(2) CommandType = StoredProcedure の場合

OracleParameter.ParameterName が、引数の変数名として使われ、

BEGIN HOGE(FOO=>:v0, BAR=>:v1); END;

のように名前表記法を使った SQL を組み立ててサーバーに送ります。
なので、ParameterName とストアドの引数名が一致している必要があります。
引用返信 編集キー/
■100115 / inTopicNo.8)  Re[2]: Oracle Package呼出時エラー PLS-00306
□投稿者/ AS702 (3回)-(2022/07/04(Mon) 17:32:07)
2022/07/04(Mon) 17:37:42 編集(投稿者)
No100052 (KOZ さん) に返信
> 2022/06/30(Thu) 19:49:23 編集(投稿者)
>
> ■No100051 (AS702 さん) に返信
>
> 連想配列を使うには、OracleParameter の CollectionType プロパティを OracleCollectionType.PLSQLAssociativeArray にする必要があります。
> また、配列サイズを OracleParameter.Size にセットします。
>
> 「PL/SQL連想配列の使用」
> https://www.oracle.com/jp/database/technologies/oramag/o17odp.html
>
> 配列を受け取るときは ArrayBindSize を設定する必要があったと思います。
> cmd.Parameters("O_顧客検索").ArrayBindSize = Enumerable.Repeat<int>(60, 160).ToArray();

お忙しい中、ご回答ありがとうございます。
以下のように修正してみました。
そこで、3つ質問させてください。

OracleConnection conn = new OracleConnection(P.Default.conn_string);
conn.Open();

OracleCommand cmd = conn.CreateCommand();
cmd.CommandText = "Begin P_顧客DB.検索(:int_更新有無,:I_顧客検索,:O_顧客検索);END;";
cmd.CommandType = CommandType.Text;

OracleParameter p_更新有無 = new OracleParameter();
OracleParameter p_In_入力項目 = new OracleParameter();
OracleParameter p_In_出力項目 = new OracleParameter();

p_更新有無.OracleDbType = OracleDbType.Decimal;
p_In_入力項目.OracleDbType = OracleDbType.Varchar2;
p_In_出力項目.OracleDbType = OracleDbType.Varchar2;

p_In_入力項目.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p_In_出力項目.CollectionType = OracleCollectionType.PLSQLAssociativeArray;

p_In_入力項目.Value = new string[2] {"1", "123456"};
p_更新有無.Value = 0;

p_In_入力項目.Size = 2;
p_In_出力項目.Size = 160;

cmd.Parameter.Add("int_更新有無", p_更新有無.Value);
cmd.Parameter.Add("I_顧客検索", p_In_入力項目.Value); @
cmd.Parameter.Add("O_顧客検索", p_In_出力項目.Value);

cmd.ExecuteNonQuery();

質問1
 上記@の部分でNullReferenceExceptionエラーとなってしまいます。
 配列の値の入れ方が間違っているのでしょうか。

質問2
 「ParameterDirection.ReturnValue」のような指定がどこにも見受けられないのですが、どこで行うのでしょうか。

質問3
ご指摘いただきました下記コーディングを入れたところ、コンパイルエラーとなりました。
「cmd.Parameters("O_顧客検索").ArrayBindSize = Enumerable.Repeat<int>(60, 160).ToArray();」
エラー内容「実行不可能なメンバー'Oracle.DataAccess.Client.OracleCommand.Parameters'をメソッドのように使用することはできません。」

重ね重ね申し訳ございませんが、よろしくお願いいたします。

引用返信 編集キー/
■100116 / inTopicNo.9)  Re[3]: Oracle Package呼出時エラー PLS-00306
□投稿者/ KOZ (252回)-(2022/07/04(Mon) 18:44:41)
No100115 (AS702 さん) に返信
> 質問1
>  上記@の部分でNullReferenceExceptionエラーとなってしまいます。
>  配列の値の入れ方が間違っているのでしょうか。

これは新しい OracleParameter を追加しようとしています。

> cmd.Parameter.Add("int_更新有無", p_更新有無.Value);
> cmd.Parameter.Add("I_顧客検索", p_In_入力項目.Value); @
> cmd.Parameter.Add("O_顧客検索", p_In_出力項目.Value);

cmd.Parameter.Add(p_更新有無);
cmd.Parameter.Add(p_In_入力項目);
cmd.Parameter.Add(p_In_出力項目);

としてください。

> 質問2
>  「ParameterDirection.ReturnValue」のような指定がどこにも見受けられないのですが、どこで行うのでしょうか。

Direction プロパティに設定します。
p_更新有無.Direction = ParameterDirection.Input;
p_In_入力項目.Direction = ParameterDirection.Input;
p_In_出力項目.Direction = ParameterDirection.Output;

ParameterDirection.ReturnValue は、CommandType = StoredProcedure の場合にストアドファンクションの戻り値として使います。

> 質問3
> ご指摘いただきました下記コーディングを入れたところ、コンパイルエラーとなりました。
> 「cmd.Parameters("O_顧客検索").ArrayBindSize = Enumerable.Repeat<int>(60, 160).ToArray();」
> エラー内容「実行不可能なメンバー'Oracle.DataAccess.Client.OracleCommand.Parameters'をメソッドのように使用することはできません。」

すみmせん、cmd.Parameters["O_顧客検索"] の間違いです。
引用返信 編集キー/
■100117 / inTopicNo.10)  Re[3]: Oracle Package呼出時エラー PLS-00306
□投稿者/ KOZ (253回)-(2022/07/04(Mon) 18:57:02)
No100115 (AS702 さん) に返信

見直してみると、ParameterName の設定を忘れていますね。
コンストラクタで複数のプロパティを指定しましょう、

OracleParameter p_更新有無 = new OracleParameter("int_更新有無", OracleDbType.Decimal, ParameterDirection.Input);
OracleParameter p_In_入力項目 = new OracleParameter("I_顧客検索", OracleDbType.Varchar2, ParameterDirection.Input);
OracleParameter p_In_出力項目 =  = new OracleParameter("O_顧客検索", OracleDbType.Varchar2, ParameterDirection.Output);

引用返信 編集キー/
■100118 / inTopicNo.11)  Re[4]: Oracle Package呼出時エラー PLS-00306
□投稿者/ AS702 (5回)-(2022/07/04(Mon) 19:17:14)
2022/07/04(Mon) 19:23:22 編集(投稿者)
2022/07/04(Mon) 19:22:52 編集(投稿者)

No100117 (KOZ さん) に返信
> ■No100115 (AS702 さん) に返信
>
> 見直してみると、ParameterName の設定を忘れていますね。
> コンストラクタで複数のプロパティを指定しましょう、
>
> OracleParameter p_更新有無 = new OracleParameter("int_更新有無", OracleDbType.Decimal, ParameterDirection.Input);
> OracleParameter p_In_入力項目 = new OracleParameter("I_顧客検索", OracleDbType.Varchar2, ParameterDirection.Input);
> OracleParameter p_In_出力項目 = = new OracleParameter("O_顧客検索", OracleDbType.Varchar2, ParameterDirection.Output);
>

ありがとうございます。
おかげさまでエラーが消えました。
アドバイスいただいた通り、修正したところ「p_In_出力項目」のValueの中に160個の値が入ったことを確認しました。

簡単なことで申し訳ないのですが、p_In_出力項目の配列[1]に格納されている値をstring型の変数にいれる方法もご教授いただけないでしょうか。

string test = p_In_出力項目.Value[0].ToString();
など色々試してみましたが、コンパイルエラーとなってしまいます。
引用返信 編集キー/
■100119 / inTopicNo.12)  Re[5]: Oracle Package呼出時エラー PLS-00306
□投稿者/ KOZ (254回)-(2022/07/04(Mon) 19:25:59)
No100118 (AS702 さん) に返信
> 簡単なことで申し訳ないのですが、p_In_出力項目の配列[1]に格納されている値をstring型の変数にいれる方法もご教授いただけないでしょうか。

OracleString[] になっているので、各要素を OracleString にキャストして Value プロパティを参照してください。

引用返信 編集キー/
■100120 / inTopicNo.13)  Re[6]: Oracle Package呼出時エラー PLS-00306
□投稿者/ AS702 (7回)-(2022/07/04(Mon) 20:12:54)
No100119 (KOZ さん) に返信
> ■No100118 (AS702 さん) に返信
>>簡単なことで申し訳ないのですが、p_In_出力項目の配列[1]に格納されている値をstring型の変数にいれる方法もご教授いただけないでしょうか。
>
> OracleString[] になっているので、各要素を OracleString にキャストして Value プロパティを参照してください。
>

ご指摘の修正を行うことで、目指していたことが実現できました。
本当にありがとうございました。

修正したC#コーディングを記載しておきます。


OracleConnection conn = new OracleConnection(P.Default.conn_string);
conn.Open();

OracleCommand cmd = conn.CreateCommand();
cmd.CommandText = "Begin P_顧客DB.検索(:int_更新有無,:I_顧客検索,:O_顧客検索);END;";
cmd.CommandType = CommandType.Text;

OracleParameter p_更新有無 = new OracleParameter("int_更新有無", OracleDbType.Decimal, ParameterDirection.Input);
OracleParameter p_In_入力項目 = new OracleParameter("I_顧客検索", OracleDbType.Varchar2, ParameterDirection.Input);
OracleParameter p_In_出力項目 = = new OracleParameter("O_顧客検索", OracleDbType.Varchar2, ParameterDirection.Output);

p_In_入力項目.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p_In_出力項目.CollectionType = OracleCollectionType.PLSQLAssociativeArray;

p_In_入力項目.Value = new string[2] {"1", "123456"}; //店番、顧客番号
p_更新有無.Value = 0;

p_In_入力項目.Size = 2;
p_In_出力項目.Size = 160;

p_In_出力項目.ArrayBindSize = Enumerable.Repeat<int>(60, 160).ToArray();

cmd.Parameter.Add(p_更新有無);
cmd.Parameter.Add(p_In_入力項目);
cmd.Parameter.Add(p_In_出力項目);

cmd.ExecuteNonQuery();

OracleString[] OraStr = (OracleString[])(p_In_出力項目.Value);
string[] arr = OraStr.Select(os => os.IsNull ? null : os.Value).ToArray();

string val = arr[1].ToString();
⇒valに2個目の値がセットされた。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ