我的 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 函数中出现“无效指令”错误