C#Oracle存储过程参数顺序

JC.*_*JC. 12 c# oracle stored-procedures

有了这个

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;
Run Code Online (Sandbox Code Playgroud)

我觉得有趣的是,如果我不按照定义的顺序添加参数,例如

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;
Run Code Online (Sandbox Code Playgroud)

代替

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;
Run Code Online (Sandbox Code Playgroud)

返回的值

cmd.Parameters["NEW_ID"].Value.ToString()
Run Code Online (Sandbox Code Playgroud)

cmd.Parameters["NUMFOUND"].Value.ToString()
Run Code Online (Sandbox Code Playgroud)

虽然通过VS2008 Server Explorer运行该过程会返回正确的数据,但仍会进行交换.

为什么是这样?

Mar*_*rcE 31

您可以在OracleCommand对象上设置BindByName参数.这适用于带参数的直接SQL查询,我没有尝试使用存储过程,但它是合乎逻辑的......

cmd.BindByName = true;
Run Code Online (Sandbox Code Playgroud)

  • 这才是真正的答案.应该被接受. (8认同)
  • 这使我免于秃顶。来自默认情况下执行此操作的 SQL Server 背景,我正在努力弄清楚为什么带有参数的内联查询不起作用。谢谢! (3认同)

Mar*_*ell 10

我不是Oracle buff,所以我无法验证 - 但听起来它们是通过位置传递(而不是通过名称传递).道德等同于:

EXEC SomeProc 'Foo', 'Bar'
Run Code Online (Sandbox Code Playgroud)

代替:

EXEC SomeProc @arg1='Foo', @arg2='Bar'
Run Code Online (Sandbox Code Playgroud)

这并不是非常罕见 - 多年来(在COM时代),我的很多代码都必须使用按位传递的ADODB驱动程序.

在这种情况下,您提供的名称仅用作查找集合集合中的值的本地键.您可以通过发明名称轻松验证:

cmd.Parameters.Add(new    OracleParameter("BANANA", ...
cmd.Parameters.Add(new    OracleParameter("GUITAR", ...
...
cmd.Parameters["BANANA"].Value.ToString()
cmd.Parameters["GUITAR"].Value.ToString()
Run Code Online (Sandbox Code Playgroud)

如果上面运行没有错误,它就是通过位置.而且他们通过位置传递......然后简单地添加他们在正确的顺序;-p而且从来除了在结尾添加新的参数...