PLSQLAssociativeArray
Hi,
I've found a sample code on http://download-uk.oracle.com/docs/html/B10961_01/features.htm#1024855
I modified the code a little.
OracleCommand cmd = new OracleCommand("begin MyPack.TestVarchar2(:1, :2, :3); end;", dbConn);
OracleParameter Param1 = new OracleParameter();
OracleParameter Param2 = new OracleParameter();
OracleParameter Param3 = new OracleParameter();
Param1.ParameterName = "1";
Param1.ParameterName = "2";
Param1.ParameterName = "3";
Param1.OracleDbType = OracleDbType.Varchar2;
Param2.OracleDbType = OracleDbType.Varchar2;
Param3.OracleDbType = OracleDbType.Varchar2;
Param1.Direction = ParameterDirection.Input;
Param2.Direction = ParameterDirection.InputOutput;
Param3.Direction = ParameterDirection.Output;
// Specify that we are binding PL/SQL Associative Array
Param1.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
Param2.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
Param3.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
// Setup the values for PL/SQL Associative Array
Param1.Value = new string[3]{"Papa",
"Mama",
"Gyerekek"};
Param2.Value = new string[3]{"First Element",
"Second Element",
"Third Element"};
Param3.Value = new string[3]{"1",
"2",
"3"};
// Specify the maximum number of elements in the PL/SQL Associative Array
Param1.Size = 3;
Param2.Size = 3;
Param3.Size = 3;
// Setup the ArrayBindSize for Param1
Param1.ArrayBindSize = new int[3]{13, 14, 13};
cmd.Parameters.Add(Param1);
cmd.Parameters.Add(Param2);
cmd.Parameters.Add(Param3);
// Setup the ArrayBindStatus for Param1
Param1.ArrayBindStatus = new OracleParameterStatus[3]{
OracleParameterStatus.Success,
OracleParameterStatus.Success,
OracleParameterStatus.Success};
// Setup the ArrayBindSize for Param2
Param2.ArrayBindSize = new int[3]{20, 20, 20};
// Setup the ArrayBindSize for Param3
Param3.ArrayBindSize = new int[3]{20, 20, 20};
// execute the cmd
cmd.ExecuteNonQuery();
//print out the parameter's values
Console.WriteLine(Param2.ToString());
Console.WriteLine(Param3.ToString());
In Oracle:
CREATE PACKAGE MYPACK AS
TYPE AssocArrayVarchar2_t is table of VARCHAR(20) index by BINARY_INTEGER;
PROCEDURE TestVarchar2(
Param1 IN AssocArrayVarchar2_t,
Param2 IN OUT AssocArrayVarchar2_t,
Param3 OUT AssocArrayVarchar2_t);
END MYPACK;
CREATE PACKAGE BODY MYPACK AS
PROCEDURE TestVarchar2(
Param1 IN AssocArrayVarchar2_t,
Param2 IN OUT AssocArrayVarchar2_t,
Param3 OUT AssocArrayVarchar2_t)
IS
i integer;
BEGIN
-- copy a few elements from y to z
Param3(1) := Param2(1);
Param3(2) := NULL;
Param3(3) := Param2(3);
-- copy all elements from x to y
Param2(1) := Param1(1);
Param2(2) := Param1(2);
Param2(3) := Param1(3);
FOR i IN 1..3 LOOP
insert into T1 values(i, Param2(i));
END LOOP;
FOR i IN 1..3 LOOP
select COL2 into Param2(i) from T2 where COL1 = i;
END LOOP;
END TestVarchar2;
END MYPACK;
But I don't get any character on console. WHY?
Hi,
From
http://download-west.oracle.com/docs/cd/B19306_01/win.102/b14307/featOraCommand.htm#BABBDHBB
<snippet>
// execute the cmd
cmd.ExecuteNonQuery();
//print out the parameter's values
Console.WriteLine("parameter values after executing the PL/SQL block");
for (int i = 0; i < 3; i++)
Console.WriteLine("Param2[{0}] = {1} ", i,
(cmd.Parameters[1].Value as Array).GetValue(i));
for (int i = 0; i < 3; i++)
Console.WriteLine("Param3[{0}] = {1} ", i,
(cmd.Parameters[2].Value as Array).GetValue(i));
</snippet>
Cheers,
Greg
Similar Messages
-
How can I pass an empty array to a parameter of type PLSQLAssociativeArray
How can I pass an empty array to a parameter of type PLSQLAssociativeArray in VB? I defined the parameter like this
Dim myArray() as String = new String() {}
Dim myPara as new Oracle.DataAccess.Client.OracleCollectionType.PLSQLAssociativeArray
myPara = 0
myPara.Value = myArray
When I execute my stored procedure giving the above parameter, I got error saying OracleParameter.Value is invalid.
I have tried to give it the DBNull.Value, but it doesn't work either.
Note: everything works fine as long as myArray has some item in there. I just wonder how I can make it works in case I have nothing.
Thank you,How can I pass an empty array to a parameter of type PLSQLAssociativeArray in VB? I defined the parameter like this
Dim myArray() as String = new String() {}
Dim myPara as new Oracle.DataAccess.Client.OracleCollectionType.PLSQLAssociativeArray
myPara = 0
myPara.Value = myArray
When I execute my stored procedure giving the above parameter, I got error saying OracleParameter.Value is invalid.
I have tried to give it the DBNull.Value, but it doesn't work either.
Note: everything works fine as long as myArray has some item in there. I just wonder how I can make it works in case I have nothing.
Thank you, -
ArrayBindSize and Size for PLSQLAssociativeArrays
Hey there,
I'm a complete newbie to ODP.NET and was hoping someone may be able to help with an issue. I basically need to call an SP from a VB.NET application and got as far as I could with the code below. The problem is that the parameters associates to this SP are all direction output. As a result, i'm having trouble trying to use the ArrayBindSize property and the Size property since I don't know what the number/size of the output from running the SP will exactly be? Does anyone see my predicament?
I'm also seeing the following errors when I try to compile my application:
Value of type '1-dimensional array of String' cannot be converted to '1-dimensional array of Integer' because 'String' is not derived from 'Integer'.
Thanks in advance!
Public Function RunSPReturnDS()
Try
Dim oraConnString As String = "Data Source=*****;User Id=******;Password=*****;"
Dim oraConnection As New OracleConnection(oraConnString)
oraConnection.Open()
MessageBox.Show("Connection works!", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
oracleCMD = oraConnection.CreateCommand
oracleCMD.CommandType = CommandType.StoredProcedure
oracleCMD.CommandText = "OCDI_UTILITIES.GET_EXISS_TODAY"
pStatus = New OracleParameter("P_STATUS", OracleDbType.Int32)
pStatusText = New OracleParameter("P_STATUS_TEXT", OracleDbType.Varchar2)
pRecReturned = New OracleParameter("P_RECORDS_RETURNED", OracleDbType.Int32)
pMsgSysNameList = New OracleParameter("P_MSG_SYSTEM_NAME_LIST", OracleDbType.Varchar2)
pMsgLastInDateTime = New OracleParameter("P_MSG_LAST_IN_DATETIME_LIST", OracleDbType.Date)
pMsgGoodIn = New OracleParameter("P_MSG_GOOD_IN_LIST", OracleDbType.Int32)
pMsgBadIn = New OracleParameter("P_MSG_BAD_IN_LIST", OracleDbType.Int32)
pMsgLastOutDateTime = New OracleParameter("P_MSG_LAST_OUT_DATETIME_LIST", OracleDbType.Date)
pMsgGoodOut = New OracleParameter("P_MSG_GOOD_OUT_LIST", OracleDbType.Int32)
pMsgBadOut = New OracleParameter("P_MSG_BAD_OUT_LIST", OracleDbType.Int32)
pStatus.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pStatusText.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pRecReturned.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pMsgSysNameList.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pMsgLastInDateTime.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pMsgGoodIn.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pMsgBadIn.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pMsgLastOutDateTime.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pMsgGoodOut.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pMsgBadOut.CollectionType = OracleCollectionType.PLSQLAssociativeArray
pStatus.Direction = ParameterDirection.Output
pStatusText.Direction = ParameterDirection.Output
pRecReturned.Direction = ParameterDirection.Output
pMsgSysNameList.Direction = ParameterDirection.Output
pMsgLastInDateTime.Direction = ParameterDirection.Output
pMsgGoodIn.Direction = ParameterDirection.Output
pMsgBadIn.Direction = ParameterDirection.Output
pMsgLastOutDateTime.Direction = ParameterDirection.Output
pMsgGoodOut.Direction = ParameterDirection.Output
pMsgBadOut.Direction = ParameterDirection.Output
pStatus.Size = 10
pStatusText.Size = 10
pRecReturned.Size = 10
pMsgSysNameList.Size = 10
pMsgLastInDateTime.Size = 10
pMsgGoodIn.Size = 10
pMsgBadIn.Size = 10
pMsgLastOutDateTime.Size = 10
pMsgGoodOut.Size = 10
pMsgBadOut.Size = 10
'pStatus.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pStatusText.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pRecReturned.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pMsgSysNameList.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pMsgLastInDateTime.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pMsgGoodIn.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pMsgBadIn.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pMsgLastOutDateTime.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pMsgGoodOut.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
'pMsgBadOut.ArrayBindSize = New Int32(10) {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
pStatus.ArrayBindSize = BindArraysToSizeInt()
pStatusText.ArrayBindSize = BindArraysToSizeStr()
pRecReturned.ArrayBindSize = BindArraysToSizeInt()
pMsgSysNameList.ArrayBindSize = BindArraysToSizeStr()
pMsgLastInDateTime.ArrayBindSize =
pMsgGoodIn.ArrayBindSize = BindArraysToSizeInt()
pMsgBadIn.ArrayBindSize = BindArraysToSizeInt()
pMsgLastOutDateTime.ArrayBindSize =
pMsgGoodOut.ArrayBindSize = BindArraysToSizeInt()
pMsgBadOut.ArrayBindSize = BindArraysToSizeInt()
oracleCMD.Parameters.Add(pStatus)
oracleCMD.Parameters.Add(pStatusText)
oracleCMD.Parameters.Add(pRecReturned)
oracleCMD.Parameters.Add(pMsgSysNameList)
oracleCMD.Parameters.Add(pMsgLastInDateTime)
oracleCMD.Parameters.Add(pMsgGoodIn)
oracleCMD.Parameters.Add(pMsgBadIn)
oracleCMD.Parameters.Add(pMsgLastOutDateTime)
oracleCMD.Parameters.Add(pMsgGoodOut)
oracleCMD.Parameters.Add(pMsgBadOut)
oracleCMD.ExecuteNonQuery()
For i As Integer = 0 To pStatus.Size - 1
Console.WriteLine(pStatus.Value(i))
Next
'ListView1.Items(3).SubItems.Add(P_STATUS)
pStatus.Dispose()
pStatusText.Dispose()
pRecReturned.Dispose()
pMsgSysNameList.Dispose()
pMsgLastInDateTime.Dispose()
pMsgGoodIn.Dispose()
pMsgBadIn.Dispose()
pMsgLastOutDateTime.Dispose()
pMsgGoodOut.Dispose()
pMsgBadOut.Dispose()
oracleCMD.Dispose()
oraConnection.Dispose()
Catch ex As Exception
MessageBox.Show(ex.Message.ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Function
Private Function BindArraysToSizeInt() As Integer()
Dim ArrBindSizeInt(collectionObjectsInt.Count - 1) As Integer
For i As Integer = 0 To collectionObjectsInt.Count - 1
ArrBindSizeInt(i) = collectionObjectsInt(i).ToString().Length
Next i
Return ArrBindSizeInt
End Function
Private Function BindArraysToSizeStr() As String()
Dim ArrBindSizeStr(collectionObjectsStr.Count - 1) As String
For i As Integer = 0 To collectionObjectsStr.Count - 1
ArrBindSizeStr(i) = collectionObjectsStr(i).ToString().Length
Next i
Return ArrBindSizeStr
End Function
End ClassWell - yes and no :-)
When it comes to desktop displays then historically the term resolution has been used to describe only the Pixel Dimensions of the physical display and not the pixels per unit of measurement. Typically we don't bother any more about the screen PPI because its usually high enough not to be a problem.
Projectors on the other hand display the image on varying screen sizes due to the distance from the screen. This makes resolution in terms of PPI important again. Yes, the projector has 'fixed' pixel dimensions but because the screen size varies the PPI will also vary. The further away the screen gets the larger the Pixels get and at some distance the image gets very 'pixellated' i.e you start to see the actual pixels.
The other thing to keep in mind is that projectors are typically driven from a PC ( I guess we should include the Mac folks in this :-) )which may have a resolution (pixel dimensions) much higher than the projector. This may mean that you have to change the display properties on your PC to match or you may be lucky that the projector can re-sample for you.
To answer the OP then the resolution in terms of PPI is more a question of controlling the distance between projector and screen and you need to check this visually although the venue may limit what you can actually do.
In terms of Image Size (Pixel Dimensions) then I would say it depends on how critical you and your audience are, but to be honest there are probably other factors like colour, brightness and contrast that are going to be bigger issues than image sharpness.
Colin #2 -
PLSQLAssociativeArray - ArraybindSize
Hello all,
Does anybody know the maximum size of an output parameter for ArrayBindSize when accessing a table of varchar2. And if so is their a way to set the limit?
Right now I can go to a maximium of 2000 characters.
thanks,
DhavalActually odp.net limits us:
"ArrayBindSize is used only for parameter types that have variable length such as Clob, Blob and Varchar2. The size is represented in bytes for binary datatypes and characters for the Unicode string types. The count for string types does not include the terminating character. The size is inferred from the actual size of the value, if it is not explicitly set. For an output parameter, the size of each value is set by ODP.NET. The ArrayBindSize property is ignored for fixed length datatypes. "
But the doc doesn't state what size and whether if we can change the size or not. I know Microsoft's driver supports 4000 bytes (so I don't know why oracle would lessen the # of bytes returned). -
How to define a output parameter in C# which maps to a PL/SQL table (odp)?
OracleConnection objconnection = new OracleConnection(connectionstring);
OracleCommand objcommand = objconnection.CreateCommand();
objcommand.Connection = objconnection;
objcommand.CommandText = "UBE_XSITE_PKG_V2.SP_DATAUPLOAD";
objcommand.CommandType = CommandType.StoredProcedure;
ListBox1.SelectedIndex = 0;
OracleParameter prm1 = new OracleParameter("PI_LOT", OracleDbType.Varchar2);
prm1.Direction = ParameterDirection.Input;
prm1.Value = ListBox1.SelectedValue.ToString();
objcommand.Parameters.Add(prm1);
OracleParameter prm2 = new OracleParameter("PI_WS_OP", OracleDbType.Int32);
prm2.Direction = ParameterDirection.Input;
prm2.Value = (float)Int32.Parse(TextBox3.Text);
objcommand.Parameters.Add(prm2);
OracleParameter prm3 = new OracleParameter("PI_SOURCE_SITE", OracleDbType.Varchar2);
prm3.Direction = ParameterDirection.Input;
prm3.Value = DropDownList1.SelectedValue.ToString();
objcommand.Parameters.Add(prm3);
OracleParameter prm4 = new OracleParameter("PI_WS_FLAG", OracleDbType.Varchar2);
prm4.Direction = ParameterDirection.Input;
prm4.Value = DropDownList5.SelectedValue.ToString();
objcommand.Parameters.Add(prm4);
OracleParameter prm5 = new OracleParameter("PI_WS_QTY", OracleDbType.Int32);
prm5.Direction = ParameterDirection.Input;
prm5.Value = (float)Int32.Parse(TextBox2.Text);
objcommand.Parameters.Add(prm5);
OracleParameter prm6 = new OracleParameter("PO_EXCEPTIONS", OracleDbType.Varchar2);
prm6.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
prm6.Direction = ParameterDirection.Output;
prm6.IsNullable = true;
prm6.Size = 4000;
objcommand.Parameters.Add(prm6);
objconnection.Open();
objcommand.ExecuteNonQuery();
objconnection.Close();Hi,
You'll need to provide more detail about what the plsql type is exactly.
However, you should check the ODP docs for examples, and it installs complete examples on your hard drive as well which will probably show you what you need to know.
As of 11.1.6.20, ODP.NET supports user defined types. Prior to that, it also supports Associative Arrays (Index-by tables).
Hope it helps
Greg -
PLS-00306:NET to call Oracle stored procedure,Use Array parameters
Development Environment:Windows 2003 SP2+Oracle 10g
. NET to call Oracle stored procedure, use an array of types of parameters
Step1:(In the Oracle database define an array of types)
CREATE OR REPLACE TYPE STRING_VARRAY AS VARRAY (1000) OF NVARCHAR2(255)
OR
CREATE OR REPLACE type string_array is table of nvarchar2(255)
Step2:
CREATE OR REPLACE PROCEDURE Test
(i_test in string_varray,o_result out int)
IS
BEGIN
o_result:=i_test.count;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
NULL;
WHEN OTHERS
THEN
o_result:=0;
END arraytest;
Step3:
ODP.NET(Oracle 10g)
OracleConnection conn = new OracleConnection("User Id=test;Password=test;Data Source=test");
OracleCommand cmd = new OracleCommand("Test", conn);
cmd.CommandType = CommandType.StoredProcedure;
string[] str = new string[2] { "11", "222" };
cmd.ArrayBindCount=2;
OracleParameter p1 = new OracleParameter("i_test", OracleDbType.NVarChar);
p1.Direction = ParameterDirection.Input;
p1.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p1.Value = str;
p1.ArrayBindSize=new int[2]{2,3};
p1.ArrayBindStatus = new OracleParameterStatus[2]{
OracleParameterStatus.Success,
OracleParameterStatus.Success
cmd.Parameters.Add(p1);
OracleParameter p2 = new OracleParameter("o_result", OracleDbType.Int32);
p2.Direction = ParameterDirection.Output;
P2.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p2.Value=0;
cmd.Parameters.Add(p2);
int i = 0;
try
conn.Open();
cmd.ExecuteNonQuery();
i =(int) p2.Value;
catch (Exception ex)
finally
conn.Close();
Error:
Execution Failed:ORA-06550:Line 1,Column 7:
PLS-00306:Test parameters when calling the number or types of errors
ORA-06550:Line 1,Column 7:
PL/SQL:Statement ignoredHi,
See the answer in [this thread|http://forums.oracle.com/forums/thread.jspa?threadID=909564&tstart=0]
Hope it helps,
Greg -
. NET to call Oracle stored procedure, use an array of types of parameters
. NET to call Oracle stored procedure, use an array of types of parameters
Step1:(In the Oracle database define an array of types)
CREATE OR REPLACE TYPE STRING_VARRAY AS VARRAY (1000) OF NVARCHAR2(255)
Step2:
CREATE OR REPLACE PROCEDURE Test
(i_test in string_varray,o_result out int)
IS
BEGIN
o_result:=i_test.count;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
NULL;
WHEN OTHERS
THEN
o_result:=0;
END arraytest;
Step3:
Use System.Data.OracleClient
C# Code:
OracleConnection conn = new OracleConnection("User Id=test;Password=test;Data Source=test");
OracleCommand cmd = new OracleCommand("Test", conn);
cmd.CommandType = CommandType.StoredProcedure;
string[] str = new string[] { "11", "22" };
OracleParameter p1 = new OracleParameter("i_test", OracleType.NVarChar);
p1.Direction = ParameterDirection.Input;
p1.Value = str;
cmd.Parameters.Add(p1);
OracleParameter p2 = new OracleParameter("o_result", OracleType.Int32);
p2.Direction = ParameterDirection.Output;
cmd.Parameters.Add(p2);
int i = 0;
try
conn.Open();
cmd.ExecuteNonQuery();
i =(int) p2.Value;
catch (Exception ex)
finally
conn.Close();
Error:
Execution Failed:ORA-06550:Line 1,Column 7:
PLS-00306:Test parameters when calling the number or types of errors
ORA-06550:Line 1,Column 7:
PL/SQL:Statement ignored
Edited by: user10133982 on Jun 4, 2009 7:13 AM. NET to call Oracle stored procedure, use an array of types of parameters
The use of ODP.net(Oracle 10g), the error is still the same
Step1:(In the Oracle database define an array of types)
CREATE OR REPLACE TYPE STRING_VARRAY AS VARRAY (1000) OF NVARCHAR2(255)
Step2:
CREATE OR REPLACE PROCEDURE Test
(i_test in string_varray,o_result out int)
IS
BEGIN
o_result:=i_test.count;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
NULL;
WHEN OTHERS
THEN
o_result:=0;
END arraytest;
Step3:
ODP.NET(Oracle 10g)
OracleConnection conn = new OracleConnection("User Id=test;Password=test;Data Source=test");
OracleCommand cmd = new OracleCommand("Test", conn);
cmd.CommandType = CommandType.StoredProcedure;
string[] str = new string[2] { "11", "222" };
cmd.ArrayBindCount=2;
OracleParameter p1 = new OracleParameter("i_test", OracleDbType.NVarChar);
p1.Direction = ParameterDirection.Input;
p1.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p1.Value = str;
p1.ArrayBindSize=new int[2]{2,3};
p1.ArrayBindStatus = new OracleParameterStatus[2]{
OracleParameterStatus.Success,
OracleParameterStatus.Success
cmd.Parameters.Add(p1);
OracleParameter p2 = new OracleParameter("o_result", OracleDbType.Int32);
p2.Direction = ParameterDirection.Output;
P2.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p2.Value=0;
cmd.Parameters.Add(p2);
int i = 0;
try
conn.Open();
cmd.ExecuteNonQuery();
i =(int) p2.Value;
catch (Exception ex)
finally
conn.Close();
Error:
Execution Failed:ORA-06550:Line 1,Column 7:
PLS-00306:Test parameters when calling the number or types of errors
ORA-06550:Line 1,Column 7:
PL/SQL:Statement ignored
Edited by: user10133982 on Jun 5, 2009 7:48 AM -
Problems binding array in C# to stored procedure.
I'm having trouble trying to pass an array of ID's to a stored procedure that is expecting an array (listed the procedure definition below). My current interface doesn't return an error, but it also doesn't insert the proper id's.
STORED PROCEDURE DEFINITION:
TYPE source_ids IS TABLE OF wweb.DM_ASSOCIATIONS.source_id%TYPE INDEX BY PLS_INTEGER;
PROCEDURE add_message_associations
(p_dm_message_id IN wweb.dm_messages.dm_message_id%TYPE
,p_association_type IN wweb.dm_associations.association_type%TYPE
,p_sources IN source_ids
,p_create_user IN wweb.dm_associations.create_user%TYPE)
.......variable definitions here...
v_source_id := p_sources.First;
WHILE v_source_id IS NOT NULL
LOOP
-- Check if this association already exists.
-- If not add them.
v_assoc_exists := 0;
FOR r_chk IN
(SELECT 1 AS assoc_exists_flag
FROM dm_associations a
WHERE a.dm_message_id = p_dm_message_id
AND a.association_type = p_association_type
AND a.source_id = v_source_id)
LOOP
v_assoc_exists := r_chk.assoc_exists_flag;
END LOOP;
IF v_assoc_exists = 0 THEN
-- Add the association
INSERT INTO wweb.dm_associations
(dm_association_id
,dm_message_id
,association_type
,source_id
,source_column_name
,active_flag
,create_date
,create_user
,last_update_date
,last_update_user)
VALUES
(wweb.dm_associations_s.NEXTVAL
,p_dm_message_id
,p_association_type
,v_source_id
,v_source_column_name
,1
,SYSDATE
,p_create_user
,SYSDATE
,p_create_user);
END IF;
.......error handling here...
C# CODE:
OracleParameter[] param = new OracleParameter[4];
param[0] = new OracleParameter("p_dm_message_id", OracleDbType.Long);
param[1] = new OracleParameter("p_association_type", OracleDbType.Varchar2, 5);
param[2] = new OracleParameter("p_sources", OracleDbType.Int32);
param[3] = new OracleParameter("p_create_user", OracleDbType.Varchar2, 25);
param[0].Value = 1;
param[1].Value = "ER";
param[2].Value = new Int32 [] {1, 172, 412, 7953};
param[3].Value = "SVC-GDESAI";
param[2].CollectionType = OracleCollectionType.PLSQLAssociativeArray;
param[2].Size = 4;
param[2].ArrayBindStatus = new OracleParameterStatus[4]{OracleParameterStatus.Success, OracleParameterStatus.Success, OracleParameterStatus.Success, OracleParameterStatus.Success};
cn = new OracleConnection(ConnectionString);
cn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = cn;
cmd.CommandText= "dynamic_messages_api.add_message_associations";
cmd.CommandType= CommandType.StoredProcedure;
foreach (OracleParameter p in param)
if ((p.Direction == ParameterDirection.InputOutput || p.Direction == ParameterDirection.Input) && (p.Value == null || p.Value.ToString() == ""))
p.Value = DBNull.Value;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
This ran fine, and created four rows in the table, but the source id's were (1, 2, 3, 4) instead of (1, 172, 412, 7953) which were the ones I passed in.
Does anyone know what I'm doing wrong here?
Thanks,
GaurangaHi,
I think you have a problem in you PL/SQL procedure. When you receive an array in the procedure, it is your responsibility to parse it explicitely with a loop or to bulk insert with a "forall" (implicit).
For instance, here is an example of a procedure of mine. I don't catch exceptions as I want the C# calling code to know about them:
The type t_* are defined like yours.
procedure UpdateDistribDates(p_bannerid in t_bannerid,
p_promonumber in t_promonumber,
p_datenumber in t_datenumber,
p_actualdate in t_actualdate ) is
BEGIN
-- First delete the existing dates in bulk
FORALL I IN P_BANNERID.FIRST..P_BANNERID.LAST
DELETE FROM PROMODISTRIBDATE
WHERE BANNERID = P_BANNERID(I)
AND PROMONUMBER = P_PROMONUMBER(I);
-- Then, insert the values passed in arrays.
FORALL I IN P_BANNERID.FIRST..P_BANNERID.LAST
INSERT INTO PROMODISTRIBDATE
(BANNERID,
PROMONUMBER,
DATENUMBER,
ACTUALDATE)
VALUES (P_BANNERID(I),
P_PROMONUMBER(I),
P_DATENUMBER(I),
P_ACTUALDATE(I));
END;
As you can see, the FORALL keyword will process the arrays passed as any other PL/SQL array in one chunk.
When you do the insert like:
INSERT INTO wweb.dm_associations
(dm_association_id
,dm_message_id
,association_type
,source_id
,source_column_name
,active_flag
,create_date
,create_user
,last_update_date
,last_update_user)
VALUES
(wweb.dm_associations_s.NEXTVAL
,p_dm_message_id
,p_association_type
,v_source_id
,v_source_column_name
,1
,SYSDATE
,p_create_user
,SYSDATE
,p_create_user);
In source_id, you insert the index of the table, not the value of the field.
I would suggest you completely rewrite this procedure by using the explicit loop like this:
1/ Explicit loop
FOR i IN 1 .. p_sources.COUNT LOOP
-- Check the existence
EXIST_FLAG := 0;
BEGIN
SELECT 1
INTO EXIST_FLAG
FROM ...
WHERE ...
AND a.source_id = p_source(i) <-- You are parsing here
AND ...
EXCEPTION
WHEN OTHERS THEN -- Nothing was found
EXIST_FLAG := 0;
END;
IF (EXIST_FLAG = 1)
INSERT INTO wweb.dm_associations
(dm_association_id
,dm_message_id
,association_type
,source_id
,source_column_name
,active_flag
,create_date
,create_user
,last_update_date
,last_update_user)
VALUES
(wweb.dm_associations_s.NEXTVAL
,p_dm_message_id
,p_association_type
,p_source(i) <-- You parse here
END IF;
END LOOP;
2/ Implicit loop and bulk insert
You would need to completely review the logic and build an array that maps exactly the row of the table you are trying to insert into. Parse the array and check for the existence of your entry, delete the row in memory when not found, then, after the loop do a bulk insert with a "forall".
Hope it helps,
Patrice -
PL/SQL function: using parameter of type PL/SQL record?
Hi,
Is it possible to call the following function from within c#:
CREATE FUNCTION myfunc (par1 table%ROWTYPE) RETURN <sometype>
IS ...
Can ODP.Net handle rowtype records? I have found no hints in the manuals.
thanks,
stephanHello Stephan,
Can ODP.Net handle rowtype records?ODP does not currently support %rowtype (or object) types.
PLSQLAssociativeArray is the only supported collection type at this time.
- Mark -
Pass values to Guid collection/array parameter for anonymous pl/sql block
The following code pops the System.ArgumentException: Invalid parameter binding
Parameter name: p_userguids
at Oracle.DataAccess.Client.OracleParameter.GetBindingSize_Raw(Int32 idx)
at Oracle.DataAccess.Client.OracleParameter.PreBind_Raw()
at Oracle.DataAccess.Client.OracleParameter.PreBind(OracleConnection conn, IntPtr errCtx, Int32 arraySize)
at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
Any help or advice ?
anonymous pl/sql block text:
DECLARE
TYPE t_guidtable IS TABLE OF RAW(16);
p_userguids t_guidtable;
BEGIN
DELETE testTable where groupname=:groupname;
INSERT INTO testTable (userguid, groupname)
SELECT column_value, :groupname FROM TABLE(p_userguids);
END;
c# code:
public static void SetGroupUsers(string group, List<Guid> users)
OracleConnection conn = Database.ConnectionEssentus;
try
conn.Open();
OracleCommand sqlCmd = new OracleCommand();
sqlCmd.CommandText = sqls["SetGroupUsers"]; // above anonymous block
sqlCmd.Connection = conn;
sqlCmd.BindByName = true;
OracleParameter p_guidCollection = sqlCmd.Parameters.Add("p_userguids", OracleDbType.Raw);
p_guidCollection.Size = users.Count;
p_guidCollection.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
p_guidCollection.UdtTypeName = "t_guidtable";
p_guidCollection.Value = users.ToArray();
sqlCmd.Parameters.Add("groupname", OracleDbType.Varchar2, 30).Value = group;
sqlCmd.ExecuteNonQuery();
catch(Exception ex)
System.Diagnostics.Debug.WriteLine(ex.ToString());
finally
conn.Close();
}New question,
How can I select records using "in" condition clause likes the following sentence?
SELECT userguid, firstname, lastname FROM UserTable WHERE userguid in (SELECT column_value FROM TABLE(p_userguids))
I tried using PIPE ROW like this, but ORACLE said "PLS-00629: PIPE statement cannot be used in non-pipelined functions"
FOR i in p_userguids.first .. p_userguids.last
LOOP
SELECT userguid, firstname, lastname INTO l_userrecord FROM UserTable WHERE userguid=p_userguids(i);
PIPE ROW(l_userrecord);
END LOOP; -
PL/SQL Associative Array as INPUT Parameter
Hi,
Just wondering if anyone out there has a good example of how to get VB.NET (using ODP.NET 9.2.0.4) to pass an Associative Array as an Input parameter to a stored procedure (not for bulk binds)? Specifically, I'm looking for an example of how a VB Strong Typed Collection would be passed through the PLSQLAssociativeArray Collection Type.
I've managed to get a test to work by passing a 1-D String Array through the ODP.NET layer to the PL/SQL AssociativeArray parameter. But I've had zero success trying to get the Collection from VB through ODP.NET.
Thanks in advance for any help.
Todd.For example, if I wanted to return a list of customer ids and names into A PLSQL Associative Array, how would I do it. I know how to return a list of customer ids into a PLSQL associative aray using the code below but I have to specify the maximum number of elements and the maximum size of each of the elements. Is there any way around this?
Dim prmOutCustomerIdList As New OracleParameter
With prmOutCustomerIdList
.ParameterName = "oCustomerIdList"
.CollectionType = OracleCollectionType.PLSQLAssociativeArray
.OracleDbType = OracleDbType.Varchar2
.Direction = ParameterDirection.Output
.Size = 5
.ArrayBindSize = New Integer(4) {10, 10, 10, 10, 10}
End With -
Return pl/sql array to C#
First of all, my goal is to return an array that I've defined back to C#.
Here is the type that I've defined:
create or replace type EMPARRAY is VARRAY(20) of VARCHAR2(30)here is the function I'm trying to call
create or replace function getEmpArray
Return EMPARRAY as
V_data EMPARRAY := EMPARRAY();
Cursor student_test is
SELECT student_id
FROM students;
Begin
For stu_rec In student_test
Loop
V_data.extend;
V_data(V_data.count) := stu_rec.student_id;
End loop;
Return V_data;
END;Now, I've installed the ODP.NET connector from oracle and am attempting to get that array returned but I'm having issues. Here is my c# code:
public void test_Click(Object obj, EventArgs ea)
//create connection string
String strConnection = "data source=foo;user id=foo;password=foo;";
using (OracleConnection conn = new OracleConnection(strConnection))
OracleCommand objCmd = new OracleCommand();
objCmd.Connection = conn;
objCmd.CommandText = "getEmpArray";
objCmd.CommandType = CommandType.StoredProcedure;
OracleParameter returnValue = new OracleParameter("retVal", OracleCollectionType.PLSQLAssociativeArray);
returnValue.Size = 100;
returnValue.Direction = ParameterDirection.ReturnValue;
objCmd.Parameters.Add(returnValue);
try
conn.Open();
Console.WriteLine("Connection Successful");
catch (OracleException e)
MessageBox.Show(e.Message, "Oracle Exception");
}//end using
}//end test ClickWhat I have compiles fine but when I fire the click event, it gives me an error saying that Object reference not set to an instance of an object. It points to this line:
OracleParameter returnValue = new OracleParameter("retVal", OracleCollectionType.PLSQLAssociativeArray);So any suggestions on how I should go about doing this? I'm probably completely off base here so any help would be appreciated.Hi,
You're using a User Defined Type (UDT), not a PLSLQ Associative Array.
ODP.NET has UDT support starting in version 11.1.0.6.21, and there are examples that install with it in your Oracle\odp.net\samples\2.x\UDT folder if you already have that version. It's generally easiest if you use Oracle Developer Tools to generate the class code, and you can get that in the same bundle as 11.1.0.6.21 odp.
Alternatively, since you're just returning an array of scalar types, you could switch to a PLSQL Associative Array for that which has been supported for quite a few versions now. You'd define the type inside the procedure instead.. type EMPARRAY is table of VARCHAR2(30) index by binary_integer . There is an example that installs with ODP in your Oracle\odp.net\samples\2.xx\AssocArray folder.
Hope it helps,
Greg
Edited by: gdarling on Jul 8, 2009 7:59 AM
However, since you already have a cursor in your stored procedure, why bother converting it to something else anyway? Just return a REF CURSOR. See your ODP.NET\samples\2.x\RefCursor folder for examples. -
Pass array to oracle stored procedure
I have such a problem: I have to pass array to stored procedure, so I declare type:
create type tNumberArray as table of number
and create procedure:
create or replace procedure proc_1 (in_param in tNumberArray) as
.... BODY OF PROCEDURE ...
when I call this procedure from C# like this:
int []pParam = new int[3] {1,2,3};
OracleCommand cmd = new OracleCommand("proc_1", dbConn);
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter param14 = new OracleParameter("param", OracleDbType.Decimal);
param14.Value = pParam;
param14.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
param14.Size = 3;
param14.Direction = ParameterDirection.Input;
cmd.Parameters.Add(param14);
cmd.ExecuteNonQuery();
an error occures. It say that there invalid number or type of parameters.
But when I declare both type and procedure in a package everything goes fine.
What is the matter? Did anybody have the same problem?Not I got next problem:
when I cannot pass parameter to stored procedure and get array fro it. In other words returning array from procedure and passing some input parameters to it does not word!
Does anybody know why it happens? -
Problem with OracleParameter.Clone()
I've found a strange behaviour in ODP.
I've created a parameter collection where i've added all the parameters.
then i simply create a copy of the collection in the command object:
//adds all parameters that existed in collection of parameters
foreach (OracleParameter oParam in oParamCol)
oCmd.Parameters.Add(oParam.Clone());
}//foreach
Everything worked ok until I create a parameter with:
CollectionType = OracleCollectionType.PLSQLAssociativeArray;
When i clone the object it looses this property value!!!
And i think it looses some more AssociativeArray properties that i've added to the parameter.
Is this a BUG in ODP.Net?
Can someone give me an explanation to this strage behaviour?For best chances of getting a reply, you may want to post it to ODP.NET forum (ODP.NET
-
Hi Guys,
I'm getting a very strange ORA-01044 error:
Oracle.DataAccess.Client.OracleException ORA-01044: size 87160000 of buffer bound to variable exceeds maximum 288212783965667328 at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx pOpoSqlValCtx, Object src, String procedure)*
at Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, String procedure, IntPtr opsErrCtx, OpoSqlValCtx pOpoSqlValCtx, Object src)*
at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
As you can see, the buffer size does not exceed the maximum stated, yet it is still causing an exception.
Some background.. A new parameter has been added to a stored proc that was originally working fine, this new parameter is an associative array of numbers.
On the ODP.Net side, I create a parameter that has a collection type of "*PLSQLAssociativeArray*" and Oracle DB Type of "*Int32*".
Any ideas as to what might be causing this problem?Hi,
What db version?
There is an older bug where this error would be raised if the requested buffer size exceeded the granule size of the SGA. That was from the 9.2 timeframe as I recall.
Regards,
Mark
Maybe you are looking for
-
Is it possible to use one apple ID for my two private MacBooks?
anybody there who can answer this question right now? Thanks
-
2 Macbook Pros don't see D-Link signal help please
Hoping someone might be able to help. I have two macbook pros, and at work both connect without problem to my Dlink DIR300 router (the second I power up it connects...) The problem begins when I get home, and both macbooks don't see the signal for th
-
How to make a single record datablock?
Hi all, I got a data-entry form (9i) that will input a record one at a time and commit before entering another record. I try to set the block as single-record to yes but it gives error, and after checking with help, I understand that it can not work
-
Selling PSE 8... New Owner Issues?
Hi - Ever since I got Lightroom 3 I found it does what I need so... what issues are there if I sell my PSE 8 to someone? The new owner can use the license key, yes? Is the new owner somehow limited? Thank-you
-
1. While working on one of the presentations, my ipad became slow. So I saved the presentation and restarted my IPAD. After the restart when I tried opening the presentation, i got an error message "Presentation cant be opened". I immediately went to