gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 04:49:12 32 4
gpt4 key购买 nike

我正在执行 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);

最佳答案

首先,不要使用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;

我看到你正在执行匿名 block - 你不需要这样做,因为这会让事情变得复杂。您需要做的是使用vb.net直接执行包。

Bottom line: your current ORACLE code does nothing to output results to .NET. Remove anonymous block and you're in business.

这是处理您的过程类型的代码(在注释中阅读)

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

关于vb.net - 从 SSIS 上的脚本任务执行时,Oracle 过程不返回结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31380644/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com