从 Oracle Sql 查询中返回一个 sql 变量的值给 .NET 代码

3
在过去的几个小时里,我一直在尝试在使用ADO.NET的.NET应用程序中对Oracle数据库执行最简单的操作(至少对于SQL SERVER来说是最简单的)。然而这似乎是不可能的。
对于SQL SERVER,如果我有一个SqlCommand对象,我会执行这样一个简单任务:
comm.CommandText = @"
   DECLARE @next_id INT
   SET @next_id = (SELECT ISNULL(MAX(id_col),0) FROM TABLE_1) + 1
   INSERT INTO TABLE_1 (id_col, col1, ...) VALUES (@next_id, val1, ...)
   SELECT @next_id";
int id = Convert.ToInt32(comm.ExecuteScalar());

这将向表TABLE_1插入一条新记录,我会在c#代码中使用"id"变量获取新的id。

四个简单的步骤:

  • 声明一个变量
  • 将它设置为下一个可用的id
  • 使用新变量插入记录
  • 返回变量的值

好的,我已经在Oracle查询中声明了这个变量。我也(认为)成功给它赋了一个值(使用SELECT INTO)。

如何在c#中获取这个变量的值?如何在Oracle SQL中将变量的值选择到输出流?

我知道有更好的方法来获取identity列,但这不是问题。它可能是一个完全不同的例子。问题很简单。 :我在一个从.net应用程序内部执行的oracle sql脚本中声明了一个变量。 如何从oracle查询中将变量的值返回到c#?以上代码在Oracle ADO.NET查询中的等效代码是什么?

1个回答

4
你需要使用ODP.NET(Oracle的Oracle数据访问组件):
以下是一个示例。请注意,在ODP.NET中,您可以建立参数方向(输入、输入输出、输出、返回值),以与您运行的过程或语句的参数相对应。在此示例中,我正在获取一个返回值,该返回值是通过序列和触发器由数据库生成的ID(对于.NET应用程序而言,它是自动创建的)。
int event_id = 0;
using (OracleConnection oraConn = new OracleConnection(connStr))
{
    string cmdText = @"insert into EVENT
        (EVENT_NAME, EVENT_DESC)
        values
        (:EVENT_NAME, :EVENT_DESC)
        RETURNING EVENT_ID INTO :EVENT_ID
        ";

    using (OracleCommand cmd = new OracleCommand(cmdText, oraConn))
    {
        oraConn.Open();
        OracleTransaction trans = oraConn.BeginTransaction();
        try
        {
            OracleParameter prm = new OracleParameter();
            cmd.BindByName = true;
            prm = new OracleParameter("EVENT_NAME", OracleDbType.Varchar2); 
            prm.Value = "SOME NAME"; cmd.Parameters.Add(prm);

            prm = new OracleParameter("EVENT_DESC", OracleDbType.Varchar2); 
            prm.Value = "SOME DESC"; cmd.Parameters.Add(prm);

            prm = new OracleParameter( "EVENT_ID"
                                     , OracleDbType.Int32
                                     , ParameterDirection.ReturnValue); 
            cmd.Parameters.Add(prm);

            cmd.ExecuteNonQuery();
            trans.Commit();
            // return value
            event_id = ConvertFromDB<int>(cmd.Parameters["EVENT_ID"].Value);
        }
        catch
        {
            trans.Rollback();
            throw;
        }
        finally
        {
            trans.Dispose();
        }
        oraConn.Close();
    }
} 

ConvertFromDB只是一个通用的类型转换器,将返回值转换为其.NET等效项(在此情况下为int)。
希望这可以帮助你。
编辑:
您可以在ODP.NET中轻松绑定值数组(并检索返回值数组)。
using (OracleConnection oraConn = new OracleConnection(connStr))
{
    string cmdText = @"insert into TEST_EVENT
        (EVENT_NAME, EVENT_DESC)
        values
        (:EVENT_NAME, :EVENT_DESC)
        RETURNING EVENT_ID INTO :EVENT_ID
        ";

    using (OracleCommand cmd = new OracleCommand(cmdText, oraConn))
    {
        oraConn.Open();
        OracleTransaction trans = oraConn.BeginTransaction();
        try
        {
            string[] event_names = new string[2];
            string[] event_descs = new string[2];
            int[] event_ids = new int[2];

            event_names[0] = "Event1";
            event_descs[0] = "Desc1";

            event_names[1] = "Event2";
            event_descs[1] = "Desc2";

            OracleParameter prm = new OracleParameter();
            cmd.Parameters.Clear();
            cmd.ArrayBindCount = 2;
            cmd.BindByName = true;

            prm = new OracleParameter("EVENT_NAME", OracleDbType.Varchar2); 
            prm.Value = event_names; cmd.Parameters.Add(prm);

            prm = new OracleParameter("EVENT_DESC", OracleDbType.Varchar2); 
            prm.Value = event_descs; cmd.Parameters.Add(prm);

            prm = new OracleParameter( "EVENT_ID"
                                     , OracleDbType.Int32
                                     , ParameterDirection.ReturnValue); 
            cmd.Parameters.Add(prm);


            cmd.ExecuteNonQuery();
            trans.Commit();
            // get return values

            event_ids = (int[])(cmd.Parameters["EVENT_ID"].Value);
        }
        catch
        {
            trans.Rollback();
            throw;
        }
        finally
        {
            trans.Dispose();
        }
        oraConn.Close();
    }
}

实际上,这并没有回答问题,尽管它很有帮助。问题是如何在c#代码中获取在sql脚本中声明和初始化的变量(不是参数)的值。但我想问你, 1)您提供的解决方案是否会更改DB的模式? 2)插入语句是否总是在返回参数中输出id? 3)如果脚本中有两个INSERT,那么哪一个id会被返回? - Thanasis Ioannidis
另外,对于没有自增策略(序列或其他)的表怎么办?在这种情况下,如何返回id?(假设一切都在事务的上下文中执行) - Thanasis Ioannidis
1
@Saysmaster,请查看我上面的编辑,了解绑定值数组(以及获取返回值数组)的方法。至于ID值,您需要在插入语句中提供ID值,或者通过触发器/序列方法让Oracle生成并返回它。 - tbone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接