开发者

Passing Anonymous Parameters into Oracle using ODP.net

开发者 https://www.devze.com 2023-03-25 10:39 出处:网络
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 d

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:

  1. 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)
  2. if the parameters are not named (ie you are relying on ordinal position) you must "cmd.BindByName = false;"
  3. 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

0

精彩评论

暂无评论...
验证码 换一张
取 消