plsql:替换在 C# 中调用的第 15 行 SELECT 查询?

plsql: Replace 15 line SELECT query called in C#?

我的背景是sql server所以请多多包涵。

我有一段 C# 代码,它运行 15 行查询,return 是一个结果集。代码段如下所示:

public DataSet Oracle_LongComplexQuery()
{

    string oradb = "DATA SOURCE=OUR_SERVER:1521/XE;" +
        "PERSIST SECURITY INFO=True;USER ID=USER; password=PASS; Pooling=False;";

    string sql =
        "SELECT USERNAME, " +
        "USER_ID, " +
        "PASSWORD, " +
        "ACCOUNT_STATUS, " +
        "LOCK_DATE, " +
        "EXPIRY_DATE, " +
        "DEFAULT_TABLESPACE, " +
        "TEMPORARY_TABLESPACE, " +
        "CREATED, " +
        "PROFILE, " +
        "INITIAL_RSRC_CONSUMER_GROUP, " +
        "EXTERNAL_NAME, " +
        "PASSWORD_VERSIONS, " +
        "EDITIONS_ENABLED, " +
        "AUTHENTICATION_TYPE " +
        "from " +
        "dba_users";

    OracleConnection conn = new OracleConnection(oradb);
    conn.Open();
    OracleCommand cmd = conn.CreateCommand();
    cmd.CommandText = sql;
    cmd.CommandType = CommandType.Text;
    DataSet ds = new DataSet();
    OracleDataAdapter adapter = new OracleDataAdapter(cmd);
    try
    {
        adapter.Fill(ds);
    }
    catch (OracleException ex)
    {
        string er = ex.Message;
    }


    return ds;

}

我不想调用 15 行查询,而是想创建一个存储过程或函数来生成相同的 Select 而无需 15 行。在 tsql 中,这将是一个存储过程,我将其称为 exec usp_getUsersInfo.

因为我主要使用 tsql,所以我认为存储过程是可行的方法。但事实并非如此。只是为了 return 一个结果集,SP 需要一个 SYS_REFCURSOR 参数来存储数据和一个单独的 PRINT(至少在 SQL 开发人员中)来查看引用游标。

使用函数我不需要 PRINT 语句,但我仍然需要 SYS_REFCURSOR 存储数据。

SYS_REFCURSOR 的问题在于 1) 整个结果集存储在 refcursor 中,类似于数据集,然后显示在屏幕上(而不是立即显示结果)。 2) 有几次我得到一个包含大量数据的 GC Overhead Limit Exceeded Error

无论如何,我不想创建一个只需要参数来查看结果集的对象。我只是想将 15 行 select 语句替换为一行

感谢任何帮助。

我也是SQL服务器出身,之前也接触过Oracle,深感你的痛苦。 Oracle 有不同的语言环境(我相信有更好的方式来描述它),并不是像在 SQL Server.

中那样在每个环境中都可以完成所有事情

好消息是,虽然你必须做的才能让它在 SQL Developer 中工作,例如,可能涉及 PRINT 语句,但 Oracle.ManagedDataAccess 包的 ADO.NET 提供程序实施非常好,使 SYS_REFCURSOR 相当容易使用。

先从存储过程说起,很简单。打开 CUR 输出游标,让它读取你想要的查询结果。 (您可以 want/need 指定所有者 and/or 程序包名称。)

CREATE OR REPLACE PROCEDURE MY_GET_USERS
(
    CUR OUT SYS_REFCURSOR
)
IS
BEGIN
    OPEN CUR FOR
    SELECT
        USERNAME,
        USER_ID,
        PASSWORD,
        ACCOUNT_STATUS,
        LOCK_DATE,
        EXPIRY_DATE,
        DEFAULT_TABLESPACE,
        TEMPORARY_TABLESPACE,
        CREATED,
        PROFILE,
        INITIAL_RSRC_CONSUMER_GROUP,
        EXTERNAL_NAME,
        PASSWORD_VERSIONS,
        EDITIONS_ENABLED,
        AUTHENTICATION_TYPE
    from
        dba_users;
END;

在 C# 端,您只需向 OracleCommand 对象添加一个 RefCursor 参数,并指定正确的参数类型。

DataSet ds = new DataSet();

using (OracleCommand command = conn.CreateCommand())
{
    command.CommandText = "MY_GET_USERS";
    command.CommandType = CommandType.StoredProcedure;

    var curParameter = command.Parameters.Add(new OracleParameter()
    {
        ParameterName = "CUR",
        Direction = ParameterDirection.Output,
        OracleDbType = OracleDbType.RefCursor  // NOT OracleDbTypeEx
    });

    command.ExecuteNonQuery();

    OracleDataAdapter adapter = new OracleDataAdapter();
    adapter.Fill(ds, (OracleRefCursor)curParameter.Value);
}

使用 ExecuteNonQuery 获取结果集可能看起来很奇怪,但结果在输出参数中,与调用 ExecuteReader 获得的结果集不同使用 SQL 服务器。

注意有关 OracleDbTypeOracleDbTypeEx 属性的注释。如果设置 OracleDbTypeEx 属性,Value 属性 将设置为 OracleDataReader 对象。通过设置 OracleDbType 属性,Value 属性 将被设置为 OracleRefCursor 对象,adapter.Fill 在上面使用。如果您想获得一个 OracleDataReader 对象并自己读取结果,则可以使用两者之一。

// OracleDbType
using (var reader = ((OracleRefCursor)curParameter.Value).GetDataReader())

// OracleDbTypeEx
using (var reader = ((OracleDataReader)curParameter.Value))