【问题标题】:C# Oracle Stored Procedure Parameter OrderC# Oracle 存储过程参数顺序
【发布时间】:2010-10-31 20:22:22
【问题描述】:

有了这个

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;

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

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;

而不是

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;

返回的值

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

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

进行交换,尽管通过 VS2008 服务器资源管理器运行该过程会返回正确的数据。

这是为什么?

【问题讨论】:

    标签: c# oracle stored-procedures


    【解决方案1】:

    我不是 Oracle 爱好者,所以我无法验证 - 但它听起来就像他们是按位置传递的(而不是按名称传递)。道德等同于:

    EXEC SomeProc 'Foo', 'Bar'
    

    代替:

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

    这并不少见 - 多年来(在 COM 时代),我的许多代码都必须使用按位置传递的 ADODB 驱动程序。

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

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

    如果上面运行没有错误,它是按位置传递的。而且它们按位置传递的...然后只需按正确的顺序添加它们;-p 并且永远不要添加新参数,除非在末尾...

    【讨论】:

    • 所以它们是按位置传递的,尽管按名称传递会更有用。
    【解决方案2】:

    不是问题的答案,但您可以使用 'insert ... 返回 ... into ' 而不是 select bgt_sequence.currval from dual,例如:

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

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

    【讨论】:

      【解决方案3】:

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

      cmd.BindByName = true;
      

      【讨论】:

      • 我同意@JohnGietzen,这应该是公认的答案
      • 这让我不再秃顶。来自默认情况下执行此操作的 SQL Server 背景,我正在努力找出为什么带有参数的内联查询不起作用。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      • 2012-03-04
      相关资源
      最近更新 更多