Home
About UsTechnologyMusicCharactersEconomyForum

ORACLE MASTER さくら 『さくらと知世のSQL講座(ビューUPDATE)』

前提知識解説

 本技術資料に登場するキャラクターは、CLAMP『カードキャプターさくら』(1996-2000)を元ネタとしている。この作品は伝統的な魔法少女モノに分類されるが、繊細で華麗な描画、主人公さくらの素直な性格、ブルジョワ的でかつほのぼのとした街並、そこはかとなく漂う同性愛的モチーフ……などにより漫画、アニメ共に大好評を博した。さくらと知世は小学四年生であるが、本技術資料では無理やり二人がIT機器の卸売業を経営しているという設定にしている。
参考リンク:
 NHKソフトウェア キャラクターページ カードキャプターさくら
 CLAMP-NET.COM|WORKS| 『カードキャプターさくら』



本編

「HPから仕入価格の値下げ情報が来たよ。今晩のうちに商品マスタを更新しなきゃ。」

「この頃はサーバの価格競争が盛んですわね。ついこの間IBMが行った値下げへに対抗しているのでしょうか…… では早速ローディングいたしますわ。」


HP社の新価格情報
商品名出精値引価格
ProLiant DL380328,000
ProLiant DL7407,780,000
designjet 1055cm plus1,056,000
………………

木之本IT卸問屋の商品マスタ
商品コード商品区分商品名メーカー仕入価格
002401ProLiant DL380HP410,000
002501ProLiant DL740HP9,000,000
002603CentreCOM 8748XLアライドテレシス348,000
002713SANRISE 1200日立135,000,000
002804designjet 1055cm plusHP1,200,000
002904VSP4960富士通18,000,000
003008Super Visual Formade翼システム595,000
………………………………………

「『商品マスタ』の『仕入価格』を同じ商品名の『出精値引価格』で上書きすればいいのね……
 闇の力を秘めし鍵よ、真の姿を我の前に示せ。 レリーズ!」


C:\> sqlplus sakura/kinomoto@CCS.tomoeda.local

SQL*Plus: Release 9.2.0.1.0 - Production on 月 Nov 3 14:41:46 2003

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.


Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning option
JServer Release 9.2.0.1.0 - Production
に接続されました。
SQL>

「ローディングは完了していますわ。いつでもどうぞ。」

「トランザクションの型となる商品レコードよ、我がクエリに応じ、その値を変えよ!」


SQL> UPDATE 商品マスタ a
  2     SET 仕入価格 =
  3         (SELECT b.出精値引価格
  4            FROM HP新価格情報 b
  5           WHERE a.商品名 = b.商品名
  6             AND a.メーカー = 'HP'
  7         )
  8  ;

368行が更新されました。


「あ、あれ……なんか更新された行が多すぎるような…… 中身を見てみよ。」


SQL> SELECT 商品コード,
  2         商品区分,
  3         商品名,
  4         メーカー,
  5         仕入価格
  6    FROM 商品マスタ
  7   WHERE 商品コード BETWEEN '0024' AND '0030'
  8   ORDER BY 商品コード
  9  ;

商品コード 商品区分 商品名                    メーカー           仕入価格
---------- -------- ------------------------- ---------------- ----------
0024       01       ProLiant DL380            HP                   328000
0025       01       ProLiant DL740            HP                  7780000
0026       03       CentreCOM 8748XL          アライドテレシス
0027       13       SANRISE 1200              日立
0028       04       designjet 1055cm plus     HP                  1056000
0029       04       VSP4960                   富士通
0030       08       Super Visual Formade      翼システム

SQL>


「ほえ……ほかのメーカーさんの仕入価格が消えちゃった……ちゃんと結合したのに……」

「どうされたのですか?……
 あら、さくらちゃん、このSQLではいけませんわ。SET句の内側の結合条件で結合できないレコードはNULL更新されてしまいますから。」

「どうしよう……たいへんなことになっちゃったよ。」

「まだロールバックすれば大丈夫ですわ。コンソールを貸していただけますか?」


SQL> ROLLBACK;

ロールバックが完了しました。

SQL> -- Ex.1 SET句の外側にWHERE条件を入れる
  2  UPDATE 商品マスタ a
  3     SET 仕入価格 =
  4         (SELECT b.出精値引価格
  5            FROM HP新価格情報 b
  6           WHERE a.商品名 = b.商品名
  7         )
  8   WHERE a.メーカー = 'HP'
  9  ;

84行が更新されました。

SQL> ROLLBACK;

ロールバックが完了しました。

SQL> -- Ex.2 ビューUPDATEを用いる
  2  UPDATE
  3         (
  4          SELECT /*+ BYPASS_UJVC */
  5                 a.仕入価格,
  6                 b.出精値引価格
  7            FROM 商品マスタ a,
  8                 HP新価格情報 b
  9           WHERE a.商品名 = b.商品名
 10             AND a.メーカー = 'HP'
 11         )
 12     SET a.仕入価格 = b.出精値引価格
 13  ;

84行が更新されました。

SQL> SELECT 商品コード,
  2         商品区分,
  3         商品名,
  4         メーカー,
  5         仕入価格
  6    FROM 商品マスタ
  7   WHERE 商品コード BETWEEN '0024' AND '0030'
  8   ORDER BY 商品コード
  9  ;

商品コード 商品区分 商品名                    メーカー           仕入価格
---------- -------- ------------------------- ---------------- ----------
0024       01       ProLiant DL380            HP                   328000
0025       01       ProLiant DL740            HP                  7780000
0026       03       CentreCOM 8748XL          アライドテレシス     348000
0027       13       SANRISE 1200              日立              135000000
0028       04       designjet 1055cm plus     HP                  1056000
0029       04       VSP4960                   富士通             18000000
0030       08       Super Visual Formade      翼システム           595000

SQL>

「"Ex.1"はSET句の外側にWHERE条件を入れて、HPさん以外のメーカーの商品の仕入価格が更新されないようにしたものですわ。でもこのやり方の欠点は、『HP新価格情報』に含まれていないHPさんの商品が『商品マスタ』に含まれている場合、そのレコードはやはりNULLになってしまうことですわ。今回は幸いそんなことはなかったみたいですが……
 安全のためには"Ex.2"のようにビューUPDATEのテクニックを使うのがよろしいかと思いますわ。この方法ならば、たとえ『HP新価格情報』に含まれていないHPさんの商品が『商品マスタ』に含まれていても、そのレコードは更新されませんから。」

「へえぇ……さすが知世ちゃん、よく知ってるね。"Ex.2"の"/*+ BYPASS_UJVC */"っていうのは何?」

「ビューUPDATEを高速化するためにOracle内部のキーチェック機構をバイパスするヒント句ですわ。
 ……でも更新先のレコード1行に更新元のレコードが複数行対応するケースがある場合、『ORA-01779 キー保存されていない表にマップする列は変更できません』エラーが発生せず、更新元のレコードがデータベース内部で物理的に並んでいる順に更新先のレコードが複数回更新されてしまいます。
 ですから更新先のレコード1行に更新元のレコードが複数行対応するおそれがある場合、使ってはいけませんわ。」

「……うぅん、難しくてよく分からないよ……」

「今は分からなくても気になさることはありませんわ。さくらちゃんがもうちょっと大人になれば、分かる時が来ますから。」