2013-09-24 25 views
2

我只是嘗試使用Oracle數據庫,並發現問題在分頁。 上次我在MySQL中使用它工作良好。PHP Oracle分頁無法使用ROWNUM顯示數據

見我的代碼:

<?php 
$page = $_POST['page']; 
$cur_page = $page; 
$page -= 1; 
$per_page = 3; 
$previous_btn = true; 
$next_btn = true; 
$first_btn = true; 
$last_btn = true; 
$start = $page * $per_page; 

$query_pag_data = "SELECT P.FORM_NO, P.MODEL_NO, P.PRODUCTION_STATUS, P.REMARKS, P.DATE_ADDED, P.TIME, P.QTY_PLAN, M.MODEL_NO, M.MODEL_NAME 
        FROM SEIAPPS_PRODUCTION_STATUS P, SEIAPPS_MODEL M 
        WHERE ROWNUM BETWEEN $start AND $per_page AND P.MODEL_NO = M.MODEL_NO ORDER BY P.DATE_ADDED DESC, P.TIME"; 

$result_pag_data = oci_parse($c1, $query_pag_data); 
oci_execute($result_pag_data); 

我用ROWNUM,但是當我想打開第2頁或下一頁,它不顯示任何數據。而表格中仍然有更多的數據。

任何人都請幫忙建議。 謝謝

+0

1)OCI具有['oci_bind_by_name'](http://www.php.net/manual/en/function.oci-bind-by-name.php),以便請請使用它而不是將所有內容填充到SQL查詢中; 2)每頁3頁,在第2頁中,你的SQL將是'3和3之間的rownum',第3頁,你的SQL將是'rownum在6和3之間'。 – Passerby

+0

@Passerby的任何例子? –

回答

2

ROWNUM在Oracle中不像LIMIT在MySQL中。

MySQL

LIMIT子句可以用來限制由SELECT語句返回的行數......有兩個參數,第一個參數指定偏移第一行的迴歸,第二個指定要返回的最大行數。的初始行的偏移量爲0(未1):

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15 

Oracle

對於查詢返回的每一行,ROWNUM虛列返回一個數字表示的順序Oracle從一個表或一組連接行中選擇行。所選的第一行具有1的ROWNUM,第二行具有2,依此類推。

SELECT * 
    FROM (SELECT * FROM employees ORDER BY employee_id) 
    WHERE ROWNUM < 11; 

在前面的例子中,ROWNUM值是頂層SELECT聲明的,所以各行已經由在子查詢EMPLOYEE_ID有序之後它們被生成的。

所以你的代碼的問題是:

  • WHERE ROWNUM BETWEEN :startrow AND :perpage是邏輯上不正確,因爲ROWNUM是行指數指標,而不是一個「行數」指標。 ROWNUM BETWEEN a AND b表示返回從a排序到b的行,例如行#1到行#3,不行行#1和3行向下。

    因此,即使ROWNUM BETWEEN a AND b有效(實際上沒有),爲了獲得查詢的「第2頁」,在邏輯上你想要ROWNUM BETWEEN :startrow AND :endrow,例如, ROWNUM BETWEEN 4 AND 6;

  • ROWNUM BETWEEN :startrow AND :endrow實際上不會爲開始行大於1的工作,因爲ROWNUM是表示該行的所選集合的順序虛列,

    所以當你執行如SELECT...WHERE ROWNUM BETWEEN 4 AND 6

    • 的第一場比賽,甲骨文認爲, 「請問ROWNUM在4到6?」因爲沒有選擇行,所以如果選擇,其ROWNUM將是1 ,所以Oracle放棄它;
    • 第二場比賽,「這將在4比6?」不,因爲沒有選擇行,所以這仍然是1;
    • 第三個匹配,相同;
    • ...

    會有根本沒有結果。

    爲了讓願望輸出,你就必須包裝在子查詢中查詢,外檢查行號,這樣的:

SELECT * FROM 
    (SELECT ROWNUM rn, t.* 
    FROM 
     (SELECT ... 
     FROM ... 
     WHERE ... 
     ORDER BY ...) t 
) 
    WHERE rn>=:startrow AND rn<=:endrow 

,以保證行排序的前檢查結算行順序。

  • 而關於編碼風格,OCI支持prepared statementvariable binding,你應該使用它:

    綁定允許數據庫重用的語句以前執行的語句的上下文和緩存,...綁定減少了SQL注入的關注,因爲與綁定變量關聯的數據永遠不會被視爲SQL語句的一部分。

$statement=oci_parse("... WHERE rn>=:start AND rn<=:end"); 
oci_bind_by_name($statement,":start",$start,-1,SQLT_INT); 
oci_bind_by_name($statement,":end",intval($start+$per_page-1),-1,SQLT_INT); 
oci_execute($statement);