次のコードでは、C#でOracleCommandを使用して、Oracleデータベースに対して_ALTER USER
_クエリを使用しようとしています。ユーザー名とパスワードの値が空の文字列でない場合、クエリを作成します。しかし、ExecuteNonQuery()
を実行するとエラー_"ORA-01036: illegal variable name/number"
_が発生します。
_ string updateQuery = "ALTER USER :user IDENTIFIED BY :password";
connection = new OracleConnection(LoginPage.connectionString);
connection.Open();
OracleCommand cmd = new OracleCommand(updateQuery, connection);
cmd.Connection = connection;
for(int i=0;i<usersList.Count;i++)
{
if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
{
OracleParameter userName = new OracleParameter();
userName.ParameterName = "user";
userName.Value = selectedUsersArray[i];
OracleParameter passwd = new OracleParameter();
passwd.ParameterName = "password";
passwd.Value = passwordArray[i];
cmd.Parameters.Add(userName);
cmd.Parameters.Add(passwd);
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
_
私の実装の何が問題なのか教えてください。
Oracleには、3種類のSQLステートメントがあります(さらに、PL/SQLブロックがあります)。
Oracleのバインド変数は、DMLおよびクエリステートメントのいくつかの特別な場所でのみ許可されます。許可されていない場所でバインド変数を使用しようとしています。したがって、エラー。
バインド変数なしでステートメントを作成します。代わりに、文字列連結を使用して完全なクエリ文字列を作成します。
文字列を連結する前に入力をサニタイズする場合は、 DBMS_ASSERT パッケージを使用します。
バインド変数は、Oracleが変数の値を知らなくてもクエリプランを作成できる場合にのみ使用できます。 DDLステートメントの場合、クエリプランはありません。したがって、バインド変数は許可されません。
DMLおよびクエリステートメントでは、バインド変数は、(基になる集合理論に関して)タプル内で使用される場合、つまり、値がテーブルの値と比較される場合、または値がテーブルに挿入される場合にのみ許可されます。実行計画の構造を変更することは許可されていません(たとえば、ターゲットテーブルを変更したり、比較の数を変更したりする)。
ストアドプロシージャに60を渡す必要があるため、パラメーターのチェックに数日費やしました。変数名の1つ(リストにロードし、作成したOracle Writeメソッドに渡す)の名前の最後にスペースが含まれていることがわかりました。ストアドプロシージャの変数と比較した場合、それらは同じでしたが、私がそれらを比較するために使用したエディターでは、余分なスペースに気付きませんでした。過去4日間、私が見つけたすべてのものを試してみて、.net Oracleドライバーさえも変えて夢中になりました。他の人を助けることができるように、ここでそれを捨てたかっただけです。文字に集中し、スペースを無視する傾向があります。 。 。
OracleCommandを1つ定義しましたが、「for」で使用しました。つまり、1つのOracleCommandに同じ名前のパラメーターを追加することを意味します。 cmd.Parameters.clear()
を使用してパラメーターを更新する必要があります。
for(int i=0;i<usersList.Count;i++)
{
if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
{
cmd.Parameters.clear();//Add this line
OracleParameter userName = new OracleParameter();
userName.ParameterName = "user";
userName.Value = selectedUsersArray[i];
OracleParameter passwd = new OracleParameter();
passwd.ParameterName = "password";
passwd.Value = passwordArray[i];
cmd.Parameters.Add(userName);
cmd.Parameters.Add(passwd);
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
Oracle erro ORA-01036は、クエリがどこかで未定義の変数を使用することを意味します。クエリから、どの変数が使用されているかを判断できます。すべての変数は@で始まります。ただし、これをadvacnedクエリに入力する場合、Oracleデータベースが大文字と小文字を区別する場合、変数名に同じ大文字と小文字を含め、すべての変数に一致する入力パラメーターがあることを確認することが重要です。
他の人がこのエラーを取得してその情報を探している場合、バインディングパラメータを渡して使用しない場合にもスローされます。私はそれがどこにもはっきりと述べられているのを本当に見つけることができませんでしたが、試行錯誤を通してそれを証明しなければなりませんでした。
cmd.Parameters.Add(new OracleParameter("GUSERID ", OracleType.VarChar)).Value = userId;
「GUSERID」の上記のコードに示すように、8つのパラメーターがあり、1つは最後にスペースがありました。スペースを削除すると、すべてが機能し始めました。
環境を準備するためのすべての調整の中で、メンテナンスしているアプリケーションで同じ問題が発生していましたが、このエラーで頭を叩くのに1時間近く費やしました"ORA-01036:無効な変数名/番号"アプリケーション接続が古いデータベースを指していることが判明するまで、アプリケーションはさらに2つのパラメーターをエラーの原因となった古いデータベースプロシージャに渡しました。
パラメータを使用してユーザー/テーブル名をpl/sqlに渡すことはできません。プロシージャを作成してsqlをビルドし、すぐに実行してそれを達成できます。
このエラーは、cmd.CommandType = System.Data.CommandType.StoredProcedure;