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 服务器。
注意有关 OracleDbType
和 OracleDbTypeEx
属性的注释。如果设置 OracleDbTypeEx
属性,Value
属性 将设置为 OracleDataReader
对象。通过设置 OracleDbType
属性,Value
属性 将被设置为 OracleRefCursor
对象,adapter.Fill
在上面使用。如果您想获得一个 OracleDataReader
对象并自己读取结果,则可以使用两者之一。
// OracleDbType
using (var reader = ((OracleRefCursor)curParameter.Value).GetDataReader())
// OracleDbTypeEx
using (var reader = ((OracleDataReader)curParameter.Value))
我的背景是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 服务器。
注意有关 OracleDbType
和 OracleDbTypeEx
属性的注释。如果设置 OracleDbTypeEx
属性,Value
属性 将设置为 OracleDataReader
对象。通过设置 OracleDbType
属性,Value
属性 将被设置为 OracleRefCursor
对象,adapter.Fill
在上面使用。如果您想获得一个 OracleDataReader
对象并自己读取结果,则可以使用两者之一。
// OracleDbType
using (var reader = ((OracleRefCursor)curParameter.Value).GetDataReader())
// OracleDbTypeEx
using (var reader = ((OracleDataReader)curParameter.Value))