Personal tools
You are here: Home ブログ 井上 マスターオブオー
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent entries
Apache2.4のリリース予定は来年(2011年)初め(あくまで予定) inoue 2010-12-23
Herokuの発音 inoue 2010-12-20
雑誌記事「ソフトウェア・テストPRESS Vol.9」の原稿公開 inoue 2010-12-18
IPA未踏のニュース inoue 2010-12-15
労基法とチキンゲーム inoue 2010-12-06
フロントエンドエンジニア inoue 2010-12-03
ASCII.technologies誌にMapReduceの記事を書きました inoue 2010-11-25
技術評論社パーフェクトシリーズ絶賛発売中 inoue 2010-11-24
雑誌連載「Emacsのトラノマキ」の原稿(part8)公開 inoue 2010-11-22
RESTの当惑 inoue 2010-11-22
「プログラマのためのUXチートシート」を作りました inoue 2010-11-19
「ビューティフルコード」を読みました inoue 2010-11-16
Categories
カテゴリなし
 
Document Actions

マスターオブオー

アリエルはどちらかと言うとLAMP派が多いですが、最近はOracleマスターもいます。多様性は良いことです。 Oracleで感心することがふたつあったので、報告します。

ひとつめ。 少し単純化していますが、次のようなテーブルがありました。baseとderivedの列はどちらも同じ名前空間に属する値を参照しています。

SQL> SELECT * FROM xtable;
      BASE,   DERIVED
----------,----------
         1,         2
         3,         6
         4,         8
         2,         4
         4,         9

baseに変化があった場合、derivedにも影響が波及します。 上で例で言えば、1の指す対象(以下obj-1)に変化があれば、obj-2に変化が波及します。その変化はobj-4に波及し、更にobj-8とobj-9にも波及します。 SELECTを繰り返し呼ぶコードを書いた場合、SELECT derived FROM xtable WHERE base=1;の戻り値を使って、SELECT derived FROM xtable WHERE base IN (戻り値);を呼び、またその戻り値を使ってWHERE .. IN ..を呼ぶ再帰コードになります。

こういうテーブル設計が正しいか否かはともかく、ひとつのSQLで書けることをOracleマスターに教えてもらいました。

base=1から始めて波及の全てを知りたい場合、次のように書きます。

SQL> SELECT base,derived FROM xtable START WITH base=1 CONNECT BY PRIOR derived=base;
      BASE,   DERIVED
----------,----------
         1,         2
         2,         4
         4,         8
         4,         9

levelを表示すると、再帰コードと同じことが内部で起きていることが分かりやすくなります。

SQL> SELECT base,derived,level FROM xtable START WITH base=1 CONNECT BY PRIOR derived=base;
      BASE,   DERIVED,     LEVEL
----------,----------,----------
         1,         2,         1
         2,         4,         2
         4,         8,         3
         4,         9,         3

levelを使って、再帰を打ち切ることもできます。

SQL> SELECT base,derived,level FROM xtable WHERE level<=2 START WITH base=1 CONNECT BY PRIOR derived=base;
      BASE,   DERIVED,     LEVEL
----------,----------,----------
         1,         2,         1
         2,         4,         2

再帰が循環して終わらない場合、次のようなエラーになります。

SQL> INSERT INTO xtable values (4,1);
SQL> SELECT * FROM xtable;

      BASE,   DERIVED
----------,----------
         1,         2
         3,         6
         4,         8
         2,         4
         4,         9
         4,         1
  
SQL> SELECT base,derived,level FROM xtable START WITH base=1 CONNECT BY PRIOR derived=base;
ERROR:
ORA-01436: CONNECT BY loop in user data

次のようにnocycleをつけると、循環があっても終わります。

SQL> SELECT base,derived,level FROM xtable START WITH base=1 CONNECT BY NOCYCLE PRIOR derived=base;

      BASE,   DERIVED,     LEVEL
----------,----------,----------
         1,         2,         1
         2,         4,         2
         4,         8,         3
         4,         9,         3
         4,         1,         3

ふたつめ。 次のようなテーブルがありました。

SQL> SELECT * FROM ytable;
   ID,       VAL
-----,----------
    1,       100
    2,       200
    3,       300

ある値のidの行が存在すればその行を書き換え、存在しない場合は新しい行を挿入したくなりました。 こういうテーブル設計が正しいか否かはともかく、mergeでできます。

次のようにid=4,val=400でmergeすると、行が存在しないのでinsertが走って新しい行を挿入します。

SQL> MERGE INTO ytable USING dual ON (ytable.id=4) WHEN MATCHED THEN UPDATE SET val=400 WHEN NOT MATCHED THEN INSERT VALUES (4, 400);
SQL> SELECT * FROM ytable;
   ID,       VAL
-----,----------
    1,       100
    2,       200
    3,       300
    4,       400

この後、id=4,val=450でmergeすると行が存在するので、updateが走って既存行を変更します。

SQL> MERGE INTO ytable USING dual ON (ytable.id=4) WHEN MATCHED THEN UPDATE SET val=450 WHEN NOT MATCHED THEN INSERT VALUES (4, 450);
SQL> SELECT * FROM ytable;
   ID,       VAL
-----,----------
    1,       100
    2,       200
    3,       300
    4,       450

アリエルには、ボラクルとか言ってOracleをバカにする人が多いですが、マスターの言葉に耳を傾けることも必要なようです。

話は飛びますが、「標準技術は良いことだ」と言う人がいます。この言葉自体に異論はありませんが、だからと言って、「独自技術や独自拡張は悪い」と言うのは短絡的過ぎます。 更に、標準技術の対極としてMSを持ち出して、MSの独自技術はけしからん、と言う主張には同意できません。 良い技術もあれば悪い技術もあります。それだけです。第一、MSの独自拡張なんてかわいいもので、GNUの独自拡張の方がずっと過激だったりします。

標準技術に従うことは良いことですが、MSやGNUのような過激派もいないと技術が進歩しない側面があります。Oracleにもそういう側面がありそうです。

独自技術をなんでも受け入れる態度は、独自技術を全否定する態度と変わりません。技術の善し悪しを判断するのは個人の責任です。その結果、残る技術もあれば消える技術もあります。ただ、ぼくは絶対的な価値観の元、残る技術と消える技術が決まるとは思っていません。結果は微妙な歴史の帰結です。ある価値観で残る技術が決まるのはなく、残った技術で価値観が決まると思っています。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/oracle-boracle/tbping

Re:マスターオブオー

Posted by jian at 2006-10-05 14:17
ちょうど、上記のような再帰的な処理を実装していた。
助かりました、サンキューです。

ちなみに元気ですか?近いうちに遊びにいきたいと思いますが、
なかなか日を決められなくて。 :)
10月の三連休に会社にいますか?

Re:マスターオブオー

Posted by inoue at 2006-10-06 00:12
ここで予定の調整をするのも変なので、メールください。
ちなみに、平日なら、約束無しでいきなり来ても、別に問題ありません。
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.