如何使用 Ref Cursor 和 return Visual Basic 上的值调用 Oracle 函数

How to call an Oracle function with a Ref Cursor and return the values on Visual Basic

我正在尝试从 VB 调用 return SYS_REFCURSOR 的 Oracle 函数。我能够使用存储过程检索数据。以同样的方式我试图调用 oracle 函数但它给出了一个错误。

如果有人能提供帮助,我将不胜感激?谢谢。如果需要,我会提供屏幕截图。

DB端函数

PKG BODY

FUNCTION GET_ALLCUST RETURN SYS_REFCURSOR AS 
  getallcursor SYS_REFCURSOR; 
BEGIN
    OPEN getallcursor FOR SELECT * FROM CUSTOMER; 
    RETURN getallcursor; 
CLOSE getallcursor;
END;

PKG Spec
==============

create or replace PACKAGE GetAllProdPckg AS
   PROCEDURE GetAllProd;
   PROCEDURE get_allprod_viasqldev;
   PROCEDURE get_allcust_viasqldev;
   FUNCTION get_allcust RETURN SYS_REFCURSOR;
   function GET_ALLPROD_FROM_DB RETURN SYS_REFCURSOR;
   
   END GetAllProdPckg;


我的代码=========================================== ==============================


Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
        Dim rvConn As Oracle.DataAccess.Client.OracleConnection
        rvConn = CreateConnection()
        Dim rvCmd As New Oracle.DataAccess.Client.OracleCommand
        '  Dim OracleRefCursor As New Oracle.DataAccess.Client.OracleDbType.RefCursor
        Dim ds As DataSet

        Dim oraDataAdapter As New Oracle.DataAccess.Client.OracleDataAdapter()


        Try
            rvCmd.Connection = rvConn
            rvConn.Open()

            Dim strSQL As String
            strSQL = "getallprodpckg.get_allcust"
            rvCmd.CommandType = CommandType.StoredProcedure
            rvCmd.CommandText = strSQL
            MsgBox("")

            Dim qrySerial3 As New Oracle.DataAccess.Client.OracleParameter("getallpcursor", OracleDbType.RefCursor) With {
            .Direction = ParameterDirection.ReturnValue}


            rvCmd.Parameters.Add(qrySerial3)


            Dim vStr As String
            Dim reader As OracleDataReader = rvCmd.ExecuteReader

            While reader.Read()
                Console.WriteLine("{0}", reader(0) & reader(1) & reader(2))
                MsgBox(vStr)
            End While


        Catch ex As Exception
            MessageBox.Show("ERROR OCCURRED" & ex.Message)

        Finally
            rvConn.Close()
        End Try

    End Sub

当我使用游标对象调用存储过程时,上面的代码会 return 一个值。 游标基本上 return 中的所有数据来自 table。 但是当我在一个函数上尝试它时它会抛出一个异常,我试过的代码如下。 ** 错误 ** System.NullReferenceException: '对象引用未设置到对象的实例。

Exception Thrown


    Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
        Dim rvConn As Oracle.DataAccess.Client.OracleConnection
        rvConn = CreateConnection()
        Dim rvCmd As New Oracle.DataAccess.Client.OracleCommand
        '  Dim OracleRefCursor As New Oracle.DataAccess.Client.OracleDbType.RefCursor
        Dim ds As DataSet

        Dim oraDataAdapter As New Oracle.DataAccess.Client.OracleDataAdapter()


        Try
            rvCmd.Connection = rvConn
            rvConn.Open()

            Dim strSQL As String
            strSQL = "select getallprodpckg.get_allcust() from dual"
            rvCmd.CommandType = CommandType.Text
            rvCmd.CommandText = strSQL
            MsgBox("")

            Dim qrySerial2 As New Oracle.DataAccess.Client.OracleParameter("getallpcursor", OracleDbType.RefCursor) With {
            .Direction = ParameterDirection.ReturnValue}


            rvCmd.Parameters.Add(qrySerial2)


            Dim vStr As String
            Dim reader As OracleDataReader = rvCmd.ExecuteReader

            While reader.Read()
                Console.WriteLine("{0}", reader(0) & reader(1) & reader(2))
                MsgBox(vStr)
            End While


        Catch ex As Exception
            MessageBox.Show("ERROR OCCURRED" & ex.Message)

        Finally
            rvConn.Close()
        End Try

    End Sub
End Class


** 数据库连接 class **


Public Class Form1 Private Sub TestOracleButton_Click(sender As Object, e As EventArgs) Handles TestOracleButton.Click TestOracleConnection() End Sub

Dim custID As Integer
Dim custID2 As Integer
Dim custName As String
Dim prodID As Integer
Dim prodName As String
Dim prodPrice As Integer
Dim prodAmount As Integer
Dim custAmount As Integer
Dim custStatus As String
Dim prodQuant As Integer

Public Sub TestOracleConnection()
    Dim rvConn As Oracle.DataAccess.Client.OracleConnection
    rvConn = CreateConnection()
    Try
        rvConn.Open()
        MessageBox.Show("Oracle Connection OK")
    Catch ex As Exception
        MessageBox.Show(ex.Message)
        MessageBox.Show("No Oracle Connection established")
    Finally
        rvConn.Close()
    End Try
End Sub
Public Function CreateConnection() As Oracle.DataAccess.Client.OracleConnection
    Dim rvConn As New Oracle.DataAccess.Client.OracleConnection With {
        .ConnectionString = GetConnectionString()
    }
    Return rvConn
End Function
Public Function GetConnectionString() As String
    Dim vConnStr As String
    vConnStr = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)"
    vConnStr = vConnStr & "(HOST=feenix-oracle.swin.edu.au)(PORT=1521))"
    vConnStr = vConnStr & "(CONNECT_DATA=(SERVICE_NAME=dms)));"
    vConnStr = vConnStr & "User Id=S1234564;"
    vConnStr = vConnStr & "Password=******;"
    Return vConnStr
End Function

您需要从参数而不是命令中获取 reader。

所以不用

Dim reader As OracleDataReader = rvCmd.ExecuteReader()

你需要:

rvCmd.CommandType = CommandType.StoredProcedure
rvCmd.CommandText = "getallprodpckg.get_allcust"

Dim qrySerial3 As New Oracle.DataAccess.Client.OracleParameter(
    None, OracleDbType.RefCursor, ParameterDirection.ReturnValue)

rvCmd.Parameters.Add(qrySerial3)

rvCmd.ExecuteNonQuery()

Dim cursor as OracleRefCursor = DirectCast(qrySerial3.Value, OracleRefCursor)

Dim reader As OracleDataReader = cursor.GetDataReader()