Оператор UPDATE в Oracle - PullRequest
       43

Оператор UPDATE в Oracle

2 голосов
/ 16 августа 2010

Мы создаем клиентскую программу, в которой параметры для хранения на веб-сервере с серверной частью Oracle задаются в клиентской программе .Net и загружаются в виде набора данных через веб-сервис.

В коде веб-службы данные считываются из набора данных и добавляются в операторы UPDATE на веб-сервере (серверная часть Oracle).

Поскольку сервер будет работать в локальной сети заказчика за брандмауэром и из-за динамической природы используемых параметров, sprocs не используются - строки 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

при выполнении команды SQL на компьютере-оракуле-получателе нам было предложено ввести привязку переменные для вышеприведенного оператора, и если мы использовали правильный формат даты, оператор UPDATE работал правильно.

Вопросы:

1) возможно, что оракул выдал ошибку ORA-01036, когда формат месяца был неправильным?

2) почему бы нам не преобразовать формат даты с веб-сайта ASP.net, работающего на компьютере Oracle? 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

Это фрагмент функции, которая принимает объект команды Oracle byRef и добавляет к нему необходимые параметры, в зависимости от того, какой из 15 возможных типов данных (WOName) получен из клиентской программы. Многие случаи существуют, но были удалены для удобства чтения.

Обновленный объект Cmd затем возвращается в основную логику программы, где вызывается ExecuteNonQuery ().

Тестовые значения параметров ниже:

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 - и я знаю, что это произойдет. так что если это проблема, мне придется обойти ее. Слишком много необязательных параметров и столбцов, которые не всегда передают значения для этой системы, чтобы разбить на нули.

Ответы [ 3 ]

3 голосов
/ 17 августа 2010

Одной «ошибкой» Oracle, которая может вызвать эту ошибку, является тот факт, что по умолчанию Oracle отображает параметры в символах параметров в запросе по последовательности, а не по имени.Если число / тип параметров не совпадают, вы получаете ошибку, подобную этой.

Решение состоит в том, чтобы сказать Oracle связывать по имени:

cmd.BindByName = true

Не вдаваясь в деталивашего кода, это может или не может быть ответом на вашу конкретную проблему, но этот параметр должен быть по умолчанию и должен быть частью любой настройки команды, которая использует параметры.Довольно удивительно наблюдать, как это одно утверждение исправляет некоторые неясные проблемы.

РЕДАКТИРОВАТЬ: Это предполагает, что вы используете поставщика доступа к данным Oracle.В .NET вы должны использовать это, а не поставщик Oracle от Microsoft.

1 голос
/ 16 августа 2010

Ошибка не имеет ничего общего с форматами даты, это означает, что переменная в выражении не была связана.

Может быть так же просто, как орфографическая ошибка (было бы неплохо, если бы Oracle включил имя переменной в сообщение об ошибке).

Можете ли вы обновить свой вопрос с помощью окружающего кода, который создает, связывает и выполняет инструкцию?

0 голосов
/ 17 августа 2010

Это фрагмент функции, которая принимает тип набора данных (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

Это фрагмент функции, которая принимает объект команды Oracle byRef и добавляет к нему необходимые параметры, в зависимости от того, какой из возможных 15 типовнабор данных (WOName) получен из клиентской программы.Многие Случаи существуют, но были удалены для удобства чтения.

Обновленный объект Cmd затем возвращается в основную логику программы, где вызывается ExecuteNonQuery ().

Ниже приведены значения тестов параметровследует:

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 - и я знаю, что это произойдет.так что если это проблема, мне придется обойти ее.Слишком много необязательных параметров и столбцов, которые не всегда передают значения для этой системы, чтобы разбить на нули.

...