[seasar-dev:1066] S2JDBC での Oracle のページングについて

Shinsuke SUGAYA [E-MAIL ADDRESS DELETED]
2009年 3月 6日 (金) 15:43:43 JST


菅谷です。

S2JDBC での Oracle のページングについて、
ご相談させてください。

現状の対象の処理では OracleDialect の
convertLimitSql メソッド内で offset によって、
以下のような SQL 文が生成されます。

例: offset=0 のとき
select * from (
    <<対象のSQL文>>
) where rownum <= 最大値


例: offset!=0 のとき
select * from (
    select temp_.*, rownum rownumber_ from (
        <<対象のSQL文>>
    ) temp_ where rownum <= 最大値
) where rownumber_ > 最小値

上記を踏まえて、次の状況を考えたときに、
例えば、以下の 2 つの select 文で、対象の
SQL 文が順序を確定していない場合(例えば、重複する
値のデータが多々あるカラムでソートとか)、上位 
5 行を見ると結果が異なる可能性があります。

select * from (
    <<対象のSQL文>>
) where rownum <= 5

select * from (
    <<対象のSQL文>>
) where rownum <= 10

ですので、対象の SQL文 で order by によって順序が
確定しない場合は、「rownum <= 値」の値によって、
得られる上位 5 行の結果が異なっていました(値が同じで
あれば、insert とか何か変更が起こらなければ順序的に
同じ結果が返ってきてます)。

ですので、順序が確定されないような問い合わせでは
S2JDBC の Oracle のページングで返ってくる結果が
怪しいものとなってしまいます(順序が確定してなければ、
順序が保証されていないのは仕方がないというのも
ありますが…)

現状ですと、順序が確定されないような select では
ページングですべてのページを表示させていっても
重複したデータや表示されないデータが存在して
しまいます。仕様論的なところですと、すべてにおいて
order by で一意に決まるキーとかで(例えば rowid)
順序を確定させるべきかもしれませんが、現実的な
ところ(開発現場とか)では、insert とかで変更とか
加えず、単純に select している分には、順序が確定
していない select でも重複や欠落なくページング
したい場合が多いかと思います。

そこで、その対応方法なのですが、OracleDialect が
以下のような sql を話してくれたりすると、重複や
欠落を回避することができます。

例: offset=0 のとき
select * from (
    select temp_.*, rownum as rownumber_ from (
        <<対象のSQL文>>
    ) temp_
) where rownumber_ <= 最大値

例: offset!=0 のとき
select * from (
    select temp_.*, rownum as rownumber_ from (
        <<対象のSQL文>>
    ) temp_
) where rownumber_ > 最小値 and rownumber_ <= 最大値

別な方法としては、対象の SQL 文の order by を
確認して、rowid を付加するとかもありえるかも
しれませんが、何らかの良い対応方法で解決できると、
開発者(私も含めて)は大変助かります。

ご検討をよろしくお願いいたします。

shinsuke



--------------------------------------
Power up the Internet with Yahoo! Toolbar.
http://pr.mail.yahoo.co.jp/toolbar/


Seasar-dev メーリングリストの案内