我的 VB.Net 代码中出现 PL SQL 错误,但无法在 SQL Developer 中重现

Posted

技术标签:

【中文标题】我的 VB.Net 代码中出现 PL SQL 错误,但无法在 SQL Developer 中重现【英文标题】:PL SQL error in my VB.Net code but can't reproduce in SQL Developer 【发布时间】:2020-02-18 20:30:25 【问题描述】:

ORA-06502:PL/SQL:数字或值错误 ORA-06512:在“JOHN.GET_USERS_EMAIL”,第 7 行 ORA-06512: 在第 1 行

当我在 SQL Developer 中运行我的过程并在我的应用程序中使用这些值时,它可以正常工作。当我运行我的 VB.Net 代码时,我得到了异常(如上所示)

我不知道我做错了什么。 (Oracle 程序不是我写的。是另一个不再在这里工作的人写的)。

Oracle 中的过程

create or replace PROCEDURE "GET_USERS_EMAIL" (
User_Email_P OUT VARCHAR,
Employee_P IN VARCHAR
)
As 
Begin
SELECT USER_EMAIL INTO User_Email_P FROM
EMPLOYEE
WHERE
USER_ID = Employee_P;
end; 

VB.Net 中的代码

Public Function Get_A_Users_Email(ByVal strEmpId As String) As String
    Try
        Dim rValue As String = ""
        Dim strSQL As String = "JOHN.GET_USERS_EMAIL"
        Dim cmd As OracleCommand = dba.CreateStoredProcCommand(strSQL)
        cmd.BindByName = True
        Dim oracleParameter(1) As OracleParameter
        oracleParameter(0) = New OracleParameter()
        oracleParameter(1) = New OracleParameter()
        strEmpId = UCase(strEmpId.Trim())

        With cmd
            oracleParameter(0) = cmd.Parameters.Add(name:="User_Email_P", dbType:=OracleDbType.Varchar2, direction:=ParameterDirection.Output)
            oracleParameter(1) = cmd.Parameters.Add(name:="Employee_P", dbType:=OracleDbType.Varchar2, val:=strEmpId, ParameterDirection.Input)

        End With

        dba.ExecuteScaler(cmd)

        If String.IsNullOrEmpty(cmd.Parameters("User_Email_P").Value.ToString) = True Then
            rValue = 0
        Else
            rValue = cmd.Parameters("User_Email_P").Value.ToString
        End If

        Return rValue
    Catch ex As Exception
        Dim Err As New App_Errors("App_Users", "Get_A_Users_Email", ex)
        Return Nothing
    End Try
End Function

Public Function ExecuteScaler(ByVal cmd As OracleCommand) As String
    ' the value tobe return ...
    Dim value As String = ""
    Dim oValue As Object
    Dim bValue As Boolean = False
    ' execute command ...
    Try
        ' open connection ...
        cmd.Connection.Open()
    Catch ex As Exception
        MsgBox("Unable to establish a connection to CFR database." & ex.ToString, MsgBoxStyle.Critical)
        Return value = ""
        Exit Function
    End Try
    Try

        ' execute command ... convert type in the case of return value null ...
        oValue = cmd.ExecuteScalar
        bValue = Convert.IsDBNull(oValue)
        If Not (bValue) Then
            value = CType(oValue, String)
        Else
            value = ""
        End If
    Catch ex As Exception
        ' rethrow error ...
        ' Dim Err As New App_Errors("Data_Access_Class", "ExecuteScalar", ex)
        Throw New Exception(ex.InnerException.ToString, ex)
    Finally
        cmd.Connection.Close()
    End Try
    Return value
End Function

Public Function CreateStoredProcCommand(ByVal cmdtext As String) As OracleCommand
    Dim Cmd As New OracleCommand        ' command object ...
    ' create command ...
    With Cmd
        .Connection = Conn
        .CommandText = cmdtext
        .CommandType = CommandType.StoredProcedure
    End With
    Return Cmd
End Function

这是表的 DDL。

CREATE TABLE "JOHN"."EMPLOYEE" 
   (    "EMPLOYEE_NUMBER" NUMBER(9,0), 
    "LOCATION_CODE" VARCHAR2(4 BYTE), 
    "SECURITY_LEVEL" NUMBER(2,0), 
    "DATE_LAST_UPDATE" DATE, 
    "DATE_SECURITY_ASSIGNED" DATE, 
    "LAST_PASSWORD_DATE" DATE, 
    "CURRENT_PASSWORD" VARCHAR2(8 BYTE), 
    "FIRST_NAME" VARCHAR2(20 BYTE), 
    "MIDDLE_INITIAL" VARCHAR2(1 BYTE), 
    "LAST_NAME" VARCHAR2(30 BYTE), 
    "USER_ID" VARCHAR2(8 BYTE), 
    "USER_TYPE" CHAR(1 BYTE), 
    "INACTIVE_DATE" DATE, 
    "SECURITY_ASSIGNED_BY" VARCHAR2(8 BYTE), 
    "PASSWORD_EXPIRATION_DATE" DATE, 
    "STATUS_CODE" NUMBER(2,0), 
    "ACCOUNT_LOCKED" VARCHAR2(1 BYTE), 
    "UPDATE_PASS_ON_SIGNON" VARCHAR2(1 BYTE), 
    "USER_EMAIL" VARCHAR2(30 BYTE))

请注意,DDL、存储过程和 VB.Net 代码是由以前的开发人员留下的。我正在将 Microsoft 的 Oracle 驱动程序实现替换为 ODP.Net。除此之外,代码实际上没有任何变化。

【问题讨论】:

感谢@djv 重新格式化。你能帮忙吗? 数据库中 USER_ID 字段的类型是什么?该错误表明它是数字的,但在您将其作为 varchar 发送的参数中 @softwareisfun 我希望正确的语法着色能帮助其他人帮助你......我根本不处理 Oracle。我知道ExecuteScaler 应该拼写为ExecuteScalar,但这不是很有帮助。过去我知道的不多。祝你好运! :) User_ID 是 VARCHAR2 【参考方案1】:

将您的数据库对象保留在使用它们的方法的本地。这样您就可以控制它们何时关闭和处置。连接和命令可能包含需要通过它们各自的.Dispose 方法释放的非托管代码。在此示例中,即使出现错误,Using...End Using 块也会为您处理此问题。

当您声明存储过程已经在 Oracle 中时,我不确定您为什么要再次创建该存储过程。

您在创建参数数组然后将值分配给数组元素的参数方面做得相当不错。 Parameter.Add 方法自动将参数添加到参数集合。您正在使用命名参数,但您没有使用正确的名称。为了避免这个问题,只需使用位置参数。

现在我们进入实际的 .Execute。 .ExecuteScalar 返回结果集第一行的第一列。我认为您不能在这种情况下参考您的 Out 参数。如果存储过程中没有游标,我不确定是否返回任何结果集。

尝试.ExecuteNonQuery,然后检索参数值。请注意,在我开始检查返回值之前,我的数据库对象已由 End Using 关闭和处置。

我无法对此进行测试,因为我没有安装 Oracle。

Public Function Get_A_Users_Email(ByVal strEmpId As String) As String
    Dim retVal As Object
    Using cn As New OracleConnection("Your connection string"),
            cmd As New OracleCommand("JOHN.GET_USERS_EMAIL", cn)
        cmd.BindByName = True
        cmd.CommandType = CommandType.StoredProcedure
        cmd.Parameters.Add("User_Email_P", OracleDbType.Varchar2, ParameterDirection.Output)
        cmd.Parameters.Add("Employee_P", OracleDbType.Varchar2, UCase(strEmpId.Trim()), ParameterDirection.Input)
        cn.Open()
        cmd.ExecuteNonQuery()
        retVal = cmd.Parameters("User_Email_P").Value
    End Using
    Dim returnString As String
    If retVal Is Nothing Then
        returnString = ""
    Else
        returnString = retVal.ToString
    End If
    Return returnString
End Function

【讨论】:

我没有创建它。它已经在那里了。我正在使用它。即使我复制并粘贴您的代码,我也会收到相同的错误(尽管代码看起来与我的非常相似)

以上是关于我的 VB.Net 代码中出现 PL SQL 错误,但无法在 SQL Developer 中重现的主要内容,如果未能解决你的问题,请参考以下文章

使用 Oracle 的 PL/SQL 函数中出现“无效指令”错误

SQL插入语句语法错误VB.net

为啥我在使用 PL/SQL 的 Oauth 2 访问令牌代码中出现此错误?

尝试在 PL/SQL 中创建类型体,但不断出现错误

VB.net更新SQL命令

如何使用 vb.net 将 excel 文件导入 sql server