从SSIS上的脚本任务执行时,Oracle过程不返回结果

时间:2015-07-13 10:14:39

标签: vb.net oracle stored-procedures ssis

我正在执行Oracle过程,该过程有三个OUTPUT参数,并以表类型变量返回结果。

这里的局限性是,我不应该使用ODBC,MSDAORA提供程序来调用该程序。所以我打算使用Oracle OLEDB提供程序。

我能够成功执行该程序,但是当我检查时(而dr.Read())它没有返回任何记录。但我知道根据存储过程的结果,它应该返回66条记录。

我怀疑我的Vb.net代码....请提出建议......提前致谢。

    Private Sub GetClients()

      Dim cmd As New OracleCommand("PKG_HOBS.PRC_HOBS_GET_CLIENTID", FPP1_Connection)
    cmd.CommandType = CommandType.StoredProcedure


    Dim p1 As New OracleParameter(":obus_grp_id", OracleDbType.Int32, ParameterDirection.Output)
    p1.CollectionType = OracleCollectionType.PLSQLAssociativeArray
    p1.Size = 100 ' This is the size of items in array in THIS case
    cmd.Parameters.Add(p1)

    Dim p2 As New OracleParameter(":ostat_c", OracleDbType.Int32, ParameterDirection.Output)
    p2.CollectionType = OracleCollectionType.PLSQLAssociativeArray
    p2.Size = 100 ' This is the size of items in array in THIS case
    cmd.Parameters.Add(p2)

    Dim p3 As New OracleParameter(":ostat_msg_x", OracleDbType.Varchar2, ParameterDirection.Output)
    p3.CollectionType = OracleCollectionType.PLSQLAssociativeArray
    p3.Size = 100 ' This is the size of items in array in THIS case
    p3.ArrayBindSize = Enumerable.Repeat(500, 100).ToArray 
    cmd.Parameters.Add(p3)

    cmd.ExecuteNonQuery()

    Dim oraNumbers1() As OracleDecimal = CType(p1.Value, OracleDecimal())
    Dim myobus_grp_idValues(oraNumbers1.Length - 1) As Integer
    For i As Integer = 0 To oraNumbers1.Length - 1
        myobus_grp_idValues(i) = Convert.ToInt32(oraNumbers1(i).Value)
    Next

    Dim oraNumbers2() As OracleDecimal = CType(p2.Value, OracleDecimal())
    Dim myostat_cValues(oraNumbers2.Length - 1) As Integer
    For i As Integer = 0 To oraNumbers2.Length - 1
        myostat_cValues(i) = Convert.ToInt32(oraNumbers2(i).Value)
    Next

    Dim oraStrings() As OracleString = CType(p3.Value, OracleString())
    Dim myostat_msg_xValues(oraStrings.Length - 1) As String
    For i As Integer = 0 To oraStrings.Length - 1
        myostat_msg_xValues(i) = oraStrings(i).Value
    Next

    Try

        MessageBox.Show(myobus_grp_idValues.ToString)

. . . . . 

包装定义

 TYPE Tnumber IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; 
 TYPE Tmsg_500 IS TABLE OF VARCHAR2(500) INDEX BY BINARY_INTEGER; 

 PROCEDURE prc_hobs_get_clientid (
     obus_grp_id OUT Tnumber, 
     ostat_c OUT Tnumber, 
     ostat_msg_x OUT Tmsg_500);

1 个答案:

答案 0 :(得分:2)

首先,不要使用OleDb,期间。 Microsoft告诉您使用特定于供应商的提供程序。使用Oracle的ODP.NET。

其次,要从Oracle SP检索记录集,您需要返回refCursor

编辑:此时我们知道您的参数是表格。要处理此问题,您需要将p.CollectionType = OracleCollectionType.PLSQLAssociativeArray添加到参数

您的代码基本上是这样的:

Declare 
    obus_grp_id PKG_HOBS.Tnumber; -- numeric table value
    ostat_c PKG_HOBS.Tnumber;     -- numeric table value
    ostat_msg_x PKG_HOBS.Tmsg_500; -- string table value
BEGIN  
    PKG_HOBS.PRC_HOBS_GET_CLIENTID(obus_grp_id, ostat_c, ostat_msg_x);
END;

我看到你执行匿名阻止 - 你不需要这样做,因为这会让你感到困惑。您需要做的是使用vb.net直接执行包。

  

底线:您当前的ORACLE代码无法将结果输出到.NET。删除匿名阻止,您就可以开展业务了。

以下是处理您的程序类型的代码(读入评论)

Dim cmd As New OracleCommand("PKG_HOBS.PRC_HOBS_GET_CLIENTID", conn)
cmd.CommandType = CommandType.StoredProcedure

Dim p1 As New OracleParameter(":p1", OracleDbType.Int64, ParameterDirection.Output)
p1.CollectionType = OracleCollectionType.PLSQLAssociativeArray
p1.Size = 100  ' Declare more than you expect
' This line below is not needed for numeric types (date too???)
' p1.ArrayBindSize = New Integer(99) {} 
cmd.Parameters.Add(p1)

' Add parameter 2 here - same as 1

Dim p3 As New OracleParameter(":p3", OracleDbType.Varchar2, ParameterDirection.Output)
p3.CollectionType = OracleCollectionType.PLSQLAssociativeArray
p3.Size = 100 ' Declare more than you expect
' for string data types you need to allocate space for each element
p3.ArrayBindSize = Enumerable.Repeat(500, 100).ToArray() ' get 100 elements of 500 - size of returning string
' I don't know why you have problems referencing System.Linq but if you do...
'Dim intA() As Integer = New Integer(99) {} 
'For i as integer = 0 to intA.Length -1
'    intA(i) = 500
'Next

cmd.Parameters.Add(p3)
conn.Open()
cmd.ExecuteNonQuery()

' Ora number is not compatible to .net types. for example integer is something 
' between number(9) and (10). So, if number(10) is the type - you get Long in 
' return. Therefore use "Convert" 

' Also, you return arrays, so you need to process them as arrays - NOTE CHANGES


Dim oraNumbers() As OracleDecimal = CType(p1.Value, OracleDecimal())
Dim myP1Values(oraNumbers.Length - 1) As Long
For i as Integer = 0 To oraNumbers.Length - 1
    myP1Values(i) = Convert.ToInt64(oraNumbers(i).Value)
Next

oraNumbers = CType(p2.Value, OracleDecimal())
Dim myP2Values(oraNumbers.Length - 1) As Long
For i as Integer = 0 To oraNumbers.Length - 1
    myP2Values(i) = Convert.ToInt64(oraNumbers(i).Value)
Next    

Dim oraStrings() As OracleString= CType(p3.Value, OracleString())
Dim myP3Values(oraStrings.Length - 1) As String
For i as Integer = 0 To oraStrings.Length - 1
    myP3Values(i) = oraStrings(i).Value
Next

这是最重要的部分

最重要的部分是如何填写声明的类型。让我们来看看

TYPE Tnumber IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
v_num Tnumber;

v_num(1) := 1234567890;
v_num(2) := 2345678901;
v_num(3) := 3456789012;

这(上)将起作用。但这会失败:

v_num(0) := 1234567890;
v_num(1) := 2345678901;
v_num(2) := 3456789012;

最后,这个,将适用于一个条件

v_num(2) := 1234567890;
v_num(3) := 2345678901;
v_num(4) := 3456789012;

在这里,我们将在p1.Value中获得4名成员,但在索引0下,您将拥有oracle null。所以,你需要在这里处理它(如果你有这样的条件)

' instead of this 
myP2Values(i) = Convert.ToInt64(oraNumbers(i).Value)
' you will need first to check 
If oraNumbers(i).IsNull Then 
. . . . 

所以,这里的主要内容是,你的pl / sql表的索引是什么?!它需要从大于0的内容开始,最好从1开始。如果您的索引包含跳过的数字,即2,4,6,8,则所有这些空格都将属于返回oracle数组,其中将有oracle null

Here is some reference