Passing Anonymous Parameters into Oracle using ODP.net
Somehow or the other, I learned that I can simply pass in parameters into an Oracle stored proc and it would be able to convert the parameters into the appropriate type. Well I am running into issues dealing with that. I am getting an "ORA-00900: invalid SQL statement" returned to me... I am guessing it is because I am attempting to pass in strings... That is what I read somewhere anyway... "http://www.dba-oracle.com/sf_ora_00900_invalid_sql_statement.htm"
What is the technique for inputing Oracle parameters into a stored proc and then executing that stored proc using .net Variables? Will I have to convert the .net strings into ODP data types? I hope not...
Here is what my code generall does...
XmlAttribute xAttribute;
using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["ACODBConnectionString"].ConnectionString))
{
using (OracleCommand cmd = new OracleCommand(sProc, conn))
{
int i = 0;
foreach (string path in paths)
{
string OracleParam;
xAttribute = AcoXMLDoc.SelectSingleNode(string.Format("//dataTemplateSpecification/templates/template/elements/element[@name='{0}']", path)).Attributes["value"];
if ((xAttribute.Value == null))
{
OracleParam = "";
cmd.Parameters.Add(colName[i], OracleParam);
}
开发者_JS百科 else
{
OracleParam = xAttribute.Value;
cmd.Parameters.Add(colName[i], OracleParam);
}
i++;
}
conn.Open();
outcome = cmd.ExecuteNonQuery();
}
}
As you can see, I am pulling the values out of an XML document so naturally the values are going to be strings... It is going to suck so much a$$ if I have to figure out how to change the strings into the appropriate data type...
The cmd.Parameters.Add() expects an object that is a parameter (not the value of the parameter)
so this is doable, with a few caveats but here is a test case:
set up the Oracle bit:
create table testParam(aa number, bb varchar2(50) , cc date)
/
create or replace procedure testProcParam(
p_aa IN TESTPARAM.AA%TYPE , --usage of tableName.ColumnName%Type has this "scoped" to the table.column AA (here it is number)
p_BB IN TESTPARAM.BB%TYPE , --The usage of TYPE here has it defined as VARCHAR2
p_CC IN TESTPARAM.CC%TYPE --this is DATE
) is
BEGIN
INSERT INTO testParam (AA, BB, CC) VALUES(P_AA, P_BB, P_CC);
END testProcParam ;
/
now for the .net bit:
OracleConnection con = Connect(constr);
// Set the command
OracleCommand cmd = new OracleCommand("testProcParam", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = false; /*mark this false to bind by position*/
string AA = "123456" ;
OracleParameter oparamAA = new OracleParameter() ;
oparamAA.Value = AA;
cmd.Parameters.Add(oparamAA);
string BB = "abcdefghijklmnopqrst" ;
OracleParameter oparamBB = new OracleParameter() ;
oparamBB.Value = BB;
cmd.Parameters.Add(oparamBB);
string CC = "01-AUG-11" ; /*we rely on the nls date parameter to 'cast' this*/
OracleParameter oparamCC = new OracleParameter() ;
oparamCC.Value = CC;
cmd.Parameters.Add(oparamCC);
cmd.ExecuteNonQuery ();
con.Close();
con.Dispose();
Now things to take note of:
- Notice how I create the parameter and assign the "string" value to it (http://download.oracle.com/docs/cd/B19306_01/win.102/b14307/OracleParameterClass.htm#i1011127 you will see that the constructors are either no dbtype or you must explicitly state it, this gets around that)
- if the parameters are not named (ie you are relying on ordinal position) you must "cmd.BindByName = false;"
- For dates, the NLS format comes into play here (thus you are opening yourself up to date issues if you change date formats etc)
then you will have your data:
SELECT * FROM testParam;
AA BB CC
---------------------- -------------------------------------------------- -------------------------
123456 abcdefghijklmnopqrst 01/08/11 00:00:00
/* --now to clean up
DROP procedure testProcParam ;
DROP table testParam ;
*/
EDIT
Per your comment; in the parameters in PL/SQL when you use
tableName.ColumnName%Type
you are actually just tying that datatype to the column's data type in the table (this allows the column to be changed and it won't break the package).
for the example I provided:
p_aa IN TESTPARAM.AA%TYPE ,
p_BB IN TESTPARAM.BB%TYPE ,
p_CC IN TESTPARAM.CC%TYPE
is the same as
p_aa IN NUMBER,
p_BB IN VARCHAR2 ,
p_CC IN DATE
Not sure of an 'anonymous/generic datatype' that you can pass in
精彩评论