在 oracle 中使用存储过程进行分页和排序
Posted
技术标签:
【中文标题】在 oracle 中使用存储过程进行分页和排序【英文标题】:Paging and sorting using a stored procedure in oracle 【发布时间】:2014-09-10 03:49:32 【问题描述】:我创建了一个用于分页的存储过程。现在我正在寻找列排序。
我的工作分页存储过程:
PROCEDURE paging (PageSize IN INT,
PageIndex IN INT,
SortColumn IN VARCHAR,
PageData OUT Page) AS
FirstIndex INT;
LastIndex INT;
SortCol VARCHAR;
BEGIN
LastIndex := PageSize * (PageIndex + 1);
FirstIndex := LastIndex - PageSize + 1;
SortCol := SortColumn;
OPEN PageData FOR
SELECT *
FROM (SELECT a.*, ROWNUM AS rnum
FROM ( SELECT *
FROM table_name
ORDER BY SortCol) a
WHERE ROWNUM <= LastIndex)
WHERE rnum >= FirstIndex;
END paging;
/
【问题讨论】:
将您的 ORDER BY 子句添加到最里面的子查询,即(SELECT * form table)
将变为(SELECT * form table ORDER BY transactionDate)
您能否修复您的示例代码:在Open PageData ....
中,您有三个右括号。但只有两个开口。
@cha 如何在 oracle 中使 ORDER BY transactionDate DESC 参数化那些是我们必须传递其值的输入参数
【参考方案1】:
我建议您使用名为 Dynamic SQL (Oracle Docs) 的绝妙功能。
我还修改了您的 SQL 查询并使用 ROW_NUMBER()
而不是 rownum
。与后者相比,它是一种对输出行进行排序和编号的更稳健的方法。
我还从您的 PL/SQL 中删除了一些我认为不需要的变量:
PROCEDURE paging (PageSize IN INT,
PageIndex IN INT,
SortColumn IN VARCHAR2, -- Assuming this always contains
-- the ordering column name
PageData OUT Page) AS
FirstIndex INT;
LastIndex INT;
v_sql VARCHAR2(4000);
BEGIN
LastIndex := PageSize * (PageIndex + 1);
FirstIndex := LastIndex - PageSize + 1;
v_sql := 'SELECT *'
||' FROM (SELECT a.*,'
||' ROW_NUMBER() '
||' OVER (ORDER BY ' || SortColumn || ') AS rnum'
||' FROM table_name a)'
||' WHERE rnum BETWEEN FirstIndex AND LastIndex';
OPEN PageData FOR v_sql;
END paging;
/
【讨论】:
很好的答案。ORDER BY SortColumn
是否需要动态 SQL ?
是的。否则您将如何传递列的名称?对列的索引进行投标在 Oracle 中不起作用(我怀疑,在其他数据库中也是如此)。因此,您需要将列名传递给查询,因此您需要动态 SQL,将列名连接到查询中(而不是像占位符那样绑定)。
我就是这么想的。但由于 OP 没有使用动态 SQL,我认为可能有一些技巧可以做其他事情。感谢您的回复。【参考方案2】:
这个 SP 独自完成了 Oracle 中的所有三件事,Paging, Sorting and Filtering
的记录。
create or replace procedure GetResults
(
p_userId In Number,
p_dueDateFrom In Date,
p_dueDateTo in Date,
p_durationMax in Number,
p_durationMin in Number,
p_sortColumn In Varchar2,
p_sortOrder In Varchar2,
p_pageSize In Number,
p_pageIndex in number,
cv_1 OUT SYS_REFCURSOR
)
as
v_FirstIndex NUMBER;
v_LastIndex NUMBER;
begin
-- Paging
v_LastIndex := p_pageSize * (p_pageIndex + 1);
v_FirstIndex := v_LastIndex - p_pageSize + 1;
OPEN cv_1 FOR
SELECT * FROM (SELECT a.*, ROWNUM AS rnum
FROM (Select * From Newjob nj Where nj.userId = p_userId
-- Filtering
And ((p_dueDateFrom IS NULL AND p_dueDateTo Is NULL) OR
(nj.Due_Date >= p_dueDateFrom and nj.Due_Date <= p_dueDateTo)
)
And ((p_durationMax IS NULL AND p_durationMin Is NULL) OR
(nj.Duration >= p_durationMax and nj.Duration <= p_durationMin)
)
-- Sorting
order by
Case when p_sortOrder = 'Ascending' And p_sortColumn = 'DUE_DATE' then nj.Due_Date End,
Case When p_sortOrder = 'Ascending' And p_sortColumn = 'DURATION' then nj.DURATION end,
Case when p_sortOrder = 'Descending' And p_sortColumn = 'DUE_DATE' then nj.Due_Date End desc,
Case When p_sortOrder = 'Descending' And p_sortColumn = 'DURATION' then nj.DURATION end desc)a
WHERE ROWNUM <= v_LastIndex)
WHERE rnum >= v_FirstIndex;
end;
【讨论】:
以上是关于在 oracle 中使用存储过程进行分页和排序的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式在 ASP.NET 4.0 GridView 上启用分页和排序?
使用Oracle的rownum或者存储过程分页的详细例子(jsp)~新手