2

Oracleバックエンドを備えたWebサーバーに保存するためのパラメーターが.Netクライアントプログラムで設定され、Webサービスを介してデータセットとしてアップロードされるクライアントプログラムを構築しています。

Web サービス コードでは、データがデータセットから読み取られ、Web サーバー (Oracle バックエンド) 上の UPDATE ステートメントに追加されます。

サーバーはファイアウォールの背後にある顧客の LAN で実行され、関連するパラメーターの動的な性質のために、sproc は使用されていません。SQL 文字列はロジックに組み込まれています。

文字列の例を次に示します。

UPDATE WorkOrders 
   SET TravelTimeHours = :TravelTimeHours, 
       TravelTimeMinutes = :TravelTimeMinutes,  
       WorkTimeHours = :WorkTimeHours, 
       WorkTimeMinutes = :WorkTimeMinutes, 
       CompletedPersonID = :CompletedPersonID, 
       CompletedPersonName = :CompletedPersonName, 
       CompleteDate = :CompleteDate 
 WHERE WorkOrderNumber = :WorkOrderNumber

VS 2010 でコードをデバッグし、サーバー コードにステップインすると、次のエラーが表示されます。

ORA-01036: illegal variable name/number

宛先の oracle マシンで SQL コマンドを実行すると、上記のステートメントのバインド変数を入力するように求められ、正しい日付形式を使用している限り、UPDATE ステートメントは正しく機能しました。

質問:

1)月の形式が間違っていると、オラクルがORA-01036エラーをスローした可能性はありますか?

2) Oracle マシンで実行されている ASP.net Web サイトから日付形式を変換する必要がないのはなぜですか? Oracle には、バインド変数の入力画面を除外するデフォルトの変換ルーチンがありますか?

3) 日付形式が問題でなかった場合、ORA-1036 は正確には何を意味し、どの変数が不正な名前/番号を持っているかをどのように発見しますか?


これは、データセットのタイプ (WOName) を受け取り、適切な SQL 文字列を返す関数のスニペットです。多くのケースが存在しますが、読みやすくするために削除されています。

Private Function GetMainSQLString(ByVal WOName As String) As String
    Dim Result As String = ""
    Select Case WOName
        Case "Monthly Site Inspection"              
            Dim sb As New StringBuilder
            sb.Append("UPDATE WorkOrders SET ")
            sb.Append("CompletedPersonID = :CompletedPersonID, CompletedPersonName = :CompletedPersonName, CompleteDate = :CompleteDate, ")
            sb.Append("SupervisorID = :SupervisorID, SupervisorName = :SupervisorName ")
            sb.Append("WHERE WorkOrderNumber = :WorkOrderNumber")
            Result = sb.ToString
    End Select
    Return Result
End Function

これは、クライアント プログラムから受信した 15 種類のデータセット (WOName) のどれに応じて、Oracle コマンド オブジェクト byRef を取得し、それに必要なパラメーターを追加する関数のスニペットです。多くのケースが存在しますが、読みやすくするために削除されています。

更新された Cmd オブジェクトはメイン プログラム ロジックに返され、そこで ExecuteNonQuery() が呼び出されます。

以下の params のテスト値は次のとおりです。

dr.Item("CompletedPersonID")    21
dr.Item("CompletedPersonName")  Pers Name
dr.Item("CompleteDate")     #8/16/2010#
dr.Item("SupervisorID")     24
dr.Item("SupervisorName")   Sup Name
dr.Item("WorkOrderNumber")  100816101830


Private Function addMainCmdParams(ByVal WOName As String, ByRef cmd As OracleCommand, ByVal dr As DataRow) As OracleCommand
    Select Case WOName
        Case "Monthly Site Inspection"              
            cmd.Parameters.Add(":CompletedPersonID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("CompletedPersonID")
            cmd.Parameters.Add(":CompletedPersonName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("CompletedPersonName")
            cmd.Parameters.Add(":CompleteDate", Oracle.DataAccess.Client.OracleDbType.Date).Value = dr.Item("CompleteDate")
            cmd.Parameters.Add(":SupervisorID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("SupervisorID")
            cmd.Parameters.Add(":SupervisorName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("SupervisorName")
            cmd.Parameters.Add(":WorkOrderNumber", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("WorkOrderNumber")
    End Select
    Return cmd
End Function

今日これを実行している間、この正確なコードは成功しました。しかし、別の同様のケースはありませんでした。私はまだ、Oracle によって実行される暗黙の型キャスト (存在する場合) を信頼していません。特に、Oracle が dbNull.value で渡されるこれらのパラメーターをどのように処理するかについては疑いがあります。それが問題なら、私はそれを回避する必要があります。このシステムに渡された値を常に取得するとは限らないオプションのパラメーターと列が多すぎて、null で中断できません。

4

3 に答える 3

3

このエラーを引き起こす可能性のある Oracle の "落とし穴" の 1 つは、デフォルトで、Oracle が名前ではなくシーケンスによってクエリ内のパラメーター シンボルにパラメーターをマップするという事実です。パラメータの数/タイプが一致しない場合、次のようなエラーが発生します。

解決策は、Oracle に名前でバインドするように指示することです。

cmd.BindByName = true

コードの詳細を掘り下げることなく、これが特定の問題に対する答えになる場合とそうでない場合がありますが、この設定はデフォルトである必要があり、パラメーターを使用するコマンド設定の一部である必要があります。この 1 つのステートメントでいくつかのあいまいな問題が修正されるのを見るのは、かなり驚くべきことです。

編集: これは、Oracle のデータ アクセス プロバイダーを使用していることを前提としています。.NET では、Microsoft の Oracle プロバイダではなく、これを使用する必要があります。

于 2010-08-17T12:17:30.993 に答える
1

このエラーは日付形式とは関係ありません。ステートメント内の変数がバインドされていないことを意味します。

スペルミスと同じくらい簡単かもしれません(Oracleが変数名をエラーメッセージに含めていればいいでしょう)。

ステートメントを作成、バインド、および実行する周囲のコードで質問を更新できますか?

于 2010-08-16T02:10:13.600 に答える
-1

これは、データセットのタイプ (WOName) を受け取り、適切な SQL 文字列を返す関数のスニペットです。多くのケースが存在しますが、読みやすくするために削除されています。

Private Function GetMainSQLString(ByVal WOName As String) As String
    Dim Result As String = ""
    Select Case WOName
        Case "Monthly Site Inspection"              
            Dim sb As New StringBuilder
            sb.Append("UPDATE WorkOrders SET ")
            sb.Append("CompletedPersonID = :CompletedPersonID, CompletedPersonName = :CompletedPersonName, CompleteDate = :CompleteDate, ")
            sb.Append("SupervisorID = :SupervisorID, SupervisorName = :SupervisorName ")
            sb.Append("WHERE WorkOrderNumber = :WorkOrderNumber")
            Result = sb.ToString
    End Select
    Return Result
End Function

これは、クライアント プログラムから受信した 15 種類のデータセット (WOName) のどれに応じて、Oracle コマンド オブジェクト byRef を取得し、それに必要なパラメーターを追加する関数のスニペットです。多くのケースが存在しますが、読みやすくするために削除されています。

更新された Cmd オブジェクトはメイン プログラム ロジックに返され、そこで ExecuteNonQuery() が呼び出されます。

以下の params のテスト値は次のとおりです。

dr.Item("CompletedPersonID")    21
dr.Item("CompletedPersonName")  Pers Name
dr.Item("CompleteDate")     #8/16/2010#
dr.Item("SupervisorID")     24
dr.Item("SupervisorName")   Sup Name
dr.Item("WorkOrderNumber")  100816101830


Private Function addMainCmdParams(ByVal WOName As String, ByRef cmd As OracleCommand, ByVal dr As DataRow) As OracleCommand
    Select Case WOName
        Case "Monthly Site Inspection"              
            cmd.Parameters.Add(":CompletedPersonID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("CompletedPersonID")
            cmd.Parameters.Add(":CompletedPersonName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("CompletedPersonName")
            cmd.Parameters.Add(":CompleteDate", Oracle.DataAccess.Client.OracleDbType.Date).Value = dr.Item("CompleteDate")
            cmd.Parameters.Add(":SupervisorID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("SupervisorID")
            cmd.Parameters.Add(":SupervisorName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("SupervisorName")
            cmd.Parameters.Add(":WorkOrderNumber", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("WorkOrderNumber")
    End Select
    Return cmd
End Function

今日これを実行している間、この正確なコードは成功しました。しかし、別の同様のケースはありませんでした。私はまだ、Oracle によって実行される暗黙の型キャスト (存在する場合) を信頼していません。特に、Oracle が dbNull.value で渡されるこれらのパラメーターをどのように処理するかについては疑いがあります。それが問題なら、私はそれを回避する必要があります。このシステムに渡された値を常に取得するとは限らないオプションのパラメーターと列が多すぎて、null で中断できません。

于 2010-08-16T21:41:32.723 に答える