简体   繁体   中英

C# Oracle Stored Procedure Parameter Order

With this

PROCEDURE "ADD_BOOKMARK_GROUP" (
  "NAME" IN VARCHAR2, 
  "BOOKMARK_GROUP_ID" IN NUMBER, 
  "STAFF_ID" IN VARCHAR2,
  "MAX_NO" IN INT,
  "NUMFOUND" OUT INT, 
  "NEW_ID" OUT NUMBER) IS

BEGIN

NEW_ID := -1;

SELECT COUNT(*) INTO NUMFOUND FROM BOOKMARK_GROUP_TABLE WHERE STAFF_ID = STAFF_ID;

IF NUMFOUND < MAX_NO THEN
    INSERT INTO BOOKMARK_GROUP_TABLE (NAME, BOOKMARK_GROUP_ID, STAFF_ID) VALUES(NAME, BOOKMARK_GROUP_ID, STAFF_ID);
    SELECT BGT_SEQUENCE.currval INTO NEW_ID FROM dual;
END IF;
END;

I find it interesting that if I don't add parameters in the order they were defined in, eg

OracleCommand cmd = new OracleCommand("ADD_BOOKMARK_GROUP", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("NAME", name));
...
cmd.Parameters.Add(new OracleParameter("NEW_ID", OracleDbType.Decimal)).Direction = ParameterDirection.Output;
cmd.Parameters.Add(new OracleParameter("NUMFOUND", OracleDbType.Int32)).Direction = ParameterDirection.Output;

instead of

OracleCommand cmd = new OracleCommand("ADD_BOOKMARK_GROUP", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("NAME", name));
...
cmd.Parameters.Add(new OracleParameter("NUMFOUND", OracleDbType.Int32)).Direction = ParameterDirection.Output;
cmd.Parameters.Add(new OracleParameter("NEW_ID", OracleDbType.Decimal)).Direction = ParameterDirection.Output;

The values returned by

cmd.Parameters["NEW_ID"].Value.ToString()

and

cmd.Parameters["NUMFOUND"].Value.ToString()

get swapped, although running the procedure through the VS2008 Server Explorer returns correct data.

Why is this?

You can probably set the BindByName parameter on the OracleCommand object. This works for straight SQL queries with parameters, I've not tried it with stored procedures but it would be logical...

cmd.BindByName = true;

I'm not an Oracle buff, so I can't verify - but it sounds like they are being passed by position (rather than passed by name). The moral equivelent to:

EXEC SomeProc 'Foo', 'Bar'

instead of:

EXEC SomeProc @arg1='Foo', @arg2='Bar'

This isn't hugely uncommon - for years (in the COM days) a lot of my code had to work with a pass-by-position ADODB driver.

In this case, the name that you give serves only as a local key to lookup the value from the collection collection. You can verify easily by inventing a name:

cmd.Parameters.Add(new    OracleParameter("BANANA", ...
cmd.Parameters.Add(new    OracleParameter("GUITAR", ...
...
cmd.Parameters["BANANA"].Value.ToString()
cmd.Parameters["GUITAR"].Value.ToString()

If the above runs without error, it is passing by position. And it they are passed by position... then simply add them in the right order ;-p And never add new parameters except at the end...

Not an answer to the question but you can use 'insert ... returning ... into ' in stead of select bgt_sequence.currval from dual, for example:

begin
  insert into test (id)
  values(test_seq.nextval)
  returning id into p_id;
end;

See http://www.adp-gmbh.ch/ora/sql/insert_into_x_returning_y.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM