3

Oracle 11g データベースからいくつかのレコードを選択しようとしています。ステートメントは、HTML テーブルのある種の「フィルター」機能を実装するために使用されます。

要件: ページングを制限し、フィルタリングされた結果を並べ替えます。

クエリはZend_Db_Selectで作成されます

*魔法のように機能します: *

$select->where('APPLICATIONS LIKE ?', '%MYAPP1%');
$select->where('APPLICATIONS NOT LIKE ?', '%GENESIS%');
$select->limit(20);

= 1 つの一致する結果 (これで問題ありません!)

フィルタリングされた結果を並べ替えようとすると、問題が発生します。

$select->order('PATH ASC');

= 3 件の一致結果 ??

Zend DB Select によって生成されたクエリと関係があると思います。次のようになります。

 SELECT z2.*
    FROM (
        SELECT z1.*, ROWNUM AS "zend_db_rownum"
        FROM (
            SELECT "APPS".* FROM "APPS" WHERE (APPLICATIONS LIKE '%MYAPP1%') AND (APPLICATIONS NOT LIKE '%GENESIS%') ORDER BY "PATH" ASC
        ) z1
    ) z2
    WHERE z2."zend_db_rownum" BETWEEN 1 AND 20
  • 順序なしでクエリを実行すると、すべて問題ありません。
  • 制限なしでクエリを実行すると、すべて問題ありません。
  • order + limit -> 間違った結果でクエリを実行すると。

私がステートメントを取り、「BETWEEN 1 AND 20」の後に注文すると、私が望むように機能します。しかし、Zend DB Select を変更するにはどうすればよいでしょうか。

重要: 私は Oracle VIEW に対してクエリを実行しています。「テーブル」に対してクエリを実行すると、それも機能します。

4

2 に答える 2

2

明らかに、Oracleによるクエリの解釈は、Zendフレームワークが意図しているものではありません。Oracleは、順序付け前にROWNUMを内部クエリの行番号カウントに関連付けているようです。そのため、エイリアスzend_db_rownumは、外部クエリのwhere句で間違った番号を配信します。

Zendフレームワークがlimit()命令に応答してSQLを生成する方法を制御していないため、考えられる唯一の回避策は、Zend limit()命令をスキップし、代わりに次の行に沿って何かを実行することです。

$select->where('APPLICATIONS LIKE ?', '%MYAPP1%');
$select->where('APPLICATIONS NOT LIKE ?', '%GENESIS%');
$select->order('PATH ASC');

$sql = $select->__toString();

$sql = "select * from (" . $sql . ") where ROWNUM between 1 and 20";

$stmt = $db->query( $sql, array());
$result = $stmt->fetchAll();

もちろん、この回避策は、クロスDBを開発していない場合にのみ正当であるため、コードがDBに依存しない必要はありません。つまり、提案された回避策を使用する場合は、ソリューションをOracleに制限します。

于 2013-02-27T14:16:46.213 に答える
0

SQL 生成にエラーがないこと、および WHERE 句に実際に異なる条件がないことを確認した場合は、Oracle サーバーのバグである可能性があります。確認するには、別の Oracle サーバー バージョンまたは別の Oracle サーバー パッチ レベルで試してください。

于 2013-02-23T23:24:32.323 に答える