Top / TIPS / COBOL の START 命令

たとえば、COBOL で、ISAM ファイルに対して、START 命令を実行すると、カレントレコードが該当のレコードに位置付きます。 あとは、データが必要になったときは、そのつど、1件ずつ READ 命令で読んでいけばよいのですが、RDB の場合、「〜より大きいキーを持つデータ」、「〜より小さいキーを持つデータ」としてしまうと、複数の行が帰ってきてしまい、レスポンスがよくありません。

このようなときは、「〜より大きいキーを持つデータのうち、最小のキーを持つデータ」、「〜より小さいキーを持つデータのうち、最大のキーを持つデータ」というように指定し、一件ずつデータを読み込みます。もちろん、こういうときは、そのキーが、行ごとに、ユニークでなくてはなりません。

SELECT * FROM CTABLE
   WHERE
       CODE = (SELECT MIN(CODE) FROM CTABLE WHERE CODE > :CODE)
SELECT * FROM CTABLE
   WHERE
       CODE = (SELECT MAX(CODE) FROM CTABLE WHERE CODE < :CODE)

もちろん並べ替えたサブクエリの1件目。とするのも良いですね。

SELECT * FROM (SELECT * FROM CTABLE
                WHERE CODE > :CODE
                ORDER BY CODE)
WHERE ROWNUM = 1
SELECT * FROM (SELECT * FROM CTABLE
                WHERE CODE < :CODE
                ORDER BY CODE DESC)
WHERE ROWNUM = 1

キーが複数の項目からなる場合は、少々やっかいです。

SELECT * FROM (SELECT * FROM MULTIKEY_TBL
                WHERE (( KEY1 =  :KEY1 AND KEY2 > :KEY2) OR ( KEY1 > :KEY1 ))
              ORDER BY  KEY1, KEY2)
       WHERE ROWNUM  =   1
SELECT * FROM (SELECT * FROM MULTIKEY_TBL
                WHERE (( KEY1 =  :KEY1 AND KEY2 < :KEY2) OR ( KEY1 < :KEY1 ))
              ORDER BY  KEY1 DESC, KEY2 DESC)
       WHERE ROWNUM  =   1

以前は OR だとうまく PRIMARY KEY を使ってくれなかったのですが、ORACLE10.2G だとちゃんと使ってくれます。

下位バージョンでは USE_CONCAT ヒントを使えばいいのかな?

以前はこの方法を紹介してましたが、これだと FULLSCAN になってしまうので、あまりよくありませんね。

SELECT * FROM MULTIKEY_TBL
  WHERE
      KEY1 || KEY2 = (SELECT MAX(KEY1 || KEY2) FROM MULTIKEY_TBL
                         WHERE KEY1 || KEY2 < :KEY1 || :KEY2)



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2011-10-06 (木) 22:19:37 (2089d)