最近公司上马了一个新的项目,用到的数据库是Oracle10g的
今天用到C#里调用Oralce包里的SP返回分页的记录集,在网上查了一下,都用的是MS提供的Oracle.Cient,而在Oracle.DataAccess.Client 里调用时(Ms的Oracle.Client 有问题,所以用的是Oracle官方提供的Oracle.DataAccess.Client ),输出的参数也要赋值后调用才能返回,否则返回的记录集是空的。即DbNull.Value要先赋值到参数上。本人用Oracle还不到三个星期,因此肯定有不对的地方,还望各位大虾们多多指教。
今天发现Oracle的Package确实不错,是我用的这几天里的我目前感觉到的一大亮点(可以重载,可以把相关的操作放到一个包里)。不知MSSQL2008里有没有。
闲话少说,上代码:
C#里调用的代码如下:
[Test]
public void Page1Test()
{
using(Database db = DBFactory.Create())
{
const string sql = " select * from test_temp where ID < 1000 order by id asc ";
OracleCommand cmd = new OracleCommand("PAGESPLIT_PKG.PAGESPLIT_SP",db.Connection);
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter p1 = new OracleParameter("pagesize", OracleDbType.Int32);
p1.Direction = ParameterDirection.Input;
p1.Value = 20;
OracleParameter p2 = new OracleParameter("pageindex", OracleDbType.Int32);
p2.Direction = ParameterDirection.Input;
p2.Value = 2;
OracleParameter p3 = new OracleParameter("sqltext", OracleDbType.Varchar2);
p3.Direction = ParameterDirection.Input;
p3.Value = sql;
OracleParameter p4 = new OracleParameter("Records_out", OracleDbType.Int32,DBNull. Value,ParameterDirection.Output); //就算是空值也要写,否则是会出错的
OracleParameter p5 = new OracleParameter("table_out", OracleDbType.RefCursor,DBNull.Value, ParameterDirection.Output);
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
cmd.Parameters.Add(p3);
cmd.Parameters.Add(p4);
cmd.Parameters.Add(p5);
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
Console.WriteLine(ds.Tables.Count);
Console.WriteLine(ds.Tables[0].TableName);
Console.WriteLine(ds.Tables[0].Rows.Count);
Console.WriteLine("结果:" + cmd.Parameters["Records_out"].Value.ToString());
foreach(DataRow row in ds.Tables[0].Rows)
{
Console.WriteLine(row[1]);
}
}
}
Oracle里分页包代码如下:
create or replace package PageSplit_PKG as
-----------------------------------------------------------------------
-- 分页模块PageSplitPackage4Oracle V0.01
-- Author : zhouyu Eamil:[email protected]
-- 2009-11-4
-----------------------------------------------------------------------/
type DataTable is REF CURSOR; --游标类型定义,用于返回数据集
procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,Records_out out int,Table_out out DataTable); --申明包里的SP1
procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,Records_out out int,Pages_out out int,Table_out out DataTable); --申明包里的SP2
procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,SqlTextCount string,Records_out out int,Table_out out DataTable); --申明包里的SP3
procedure PageSplit_SP(PageSize int,PageIndex int,SqlText string,Table_out out DataTable); --申明包里的SP3
end;
create or replace package body PageSplit_PKG as
-- 以下方法来自于网络修改
--------------------------------------------------------------------------------------------
--功能描述: 大数据量分页通用存储过程,超过100W数据的表,尽量加上索引上的条件
--创建时间: 2009-11-4
--------------------------------------------------------------------------------------------/
procedure PageSplit_SP
(
PageSize int, --每页记录数
PageIndex int, --当前页码,从 1 开始
SqlText string, --查询语句,含排序部分
Records_out out int,--返回总记录数
Table_out out DataTable ----返回当前页数据记录
) as --对包中定义的SP1的实现
v_sql varchar2(8000); -- 不要超过32767个字符,不可以使用nvarchar2型,下面用的是to_char()
v_count int;
v_maxRownum int;
v_minRownum int;
begin
--取记录总数
v_sql := 'select count(*) from (' || SqlText || ')'; --拼接统计Sql
execute immediate v_sql into v_count; --执行统计
Records_out := v_count;
--行位置判断
v_maxRownum := PageIndex * PageSize;
v_minRownum := v_maxRownum - PageSize + 1;
--拼接查询语句
v_sql := 'SELECT *
FROM (
SELECT A.*, rownum rn
FROM ('|| SqlText ||') A
WHERE rownum <= '|| to_char(v_maxRownum) || '
) B
WHERE rn >= ' || to_char(v_minRownum) ;
--注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn
open Table_out for v_sql;
end;
/*****************************************************************
*功能描述: 大数据量分页通用存储过程(重载1,直接返回分页数量)
*创建时间: 2009-11-3
*****************************************************************/
procedure PageSplit_SP
(
PageSize int, --每页记录数
PageIndex int, --当前页码,从 1 开始
SqlText string, --查询语句,含排序部分
Records_out out int,--返回总记录数
Pages_out out int, --返回分出的页数
Table_out out DataTable ----返回当前页数据记录
)
as
v_sql varchar2(8000);
v_count int;
v_maxRownum int;
v_minRownum int;
begin
----取记录总数
v_sql := 'select count(*) from (' || SqlText || ')'; --生成统计字符串
execute immediate v_sql into v_count; --执行统计
Records_out := v_count;
--行位置判断
v_maxRownum := PageIndex * PageSize;
v_minRownum := v_maxRownum - PageSize + 1;
--拼接查询语句
v_sql := 'SELECT *
FROM (
SELECT A.*, rownum rn
FROM ('|| SqlText ||') A
WHERE rownum <= '|| to_char(v_maxRownum) || '
) B
WHERE rn >= ' || to_char(v_minRownum) ;
--注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn
OPEN Table_out FOR v_sql;
end;
/*****************************************************************
*功能描述: 大数据量分页通用存储过程(重载2,自定义统计查询,推荐使用)
*创建时间: 2009-11-3
*****************************************************************/
procedure PageSplit_SP
(
PageSize int, --每页记录数
PageIndex int, --当前页码,从 1 开始
SqlText string, --查询语句,含排序部分
SqlTextCount string, --获取记录总数的查询语句
Records_out out int, --返回总记录数
Table_out out DataTable)
as
v_sql varchar2(8000);
v_count int;
v_maxRownum int;
v_minRownum int;
begin
----取记录总数
execute immediate SqlTextCount into v_count;
Records_out := v_count;
----执行分页查询
v_maxRownum := PageIndex * PageSize;
v_minRownum := v_maxRownum - PageSize + 1;
v_sql := 'SELECT *
FROM (
SELECT A.*, rownum rn
FROM ('|| SqlText ||') A
WHERE rownum <= '|| to_char(v_maxRownum) || '
) B
WHERE rn >= ' || to_char(v_minRownum) ;
--注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn
OPEN Table_out FOR v_sql;
end ;
/*****************************************************************
*功能描述: 大数据量分页通用存储过程(重载3,不输出总记录数,适用于外部分页计算,内部直选记录集,DB计算压力最小)
*创建时间: 2009-11-3
*****************************************************************/
procedure PageSplit_SP
(
PageSize int, --每页记录数
PageIndex int, --当前页码,从 1 开始
SqlText string, --查询语句,含排序部分
Table_out out DataTable
)
as
v_sql varchar2(8000);
v_maxRownum int;
v_minRownum int;
begin
----执行分页查询
v_maxRownum := PageIndex * PageSize;
v_minRownum := v_maxRownum - PageSize + 1;
v_sql := 'SELECT *
FROM (
SELECT A.*, rownum rn
FROM ('|| SqlText ||') A
WHERE rownum <= '|| to_char(v_maxRownum) || '
) B
WHERE rn >= ' || to_char(v_minRownum) ;
--注意对rownum别名的使用,第一次直接用rownum,第二次一定要用别名rn
OPEN Table_out FOR v_sql;
end;
end;
这儿有个怪问题,就是在Toad里编译能通过,PLSQL Developer里则有问题。不知啥原因!
转换自: https://www.cnblogs.com/atwind/archive/2009/11/04/1596202.html