Comments
Transcript
IBM Informix SQL ガイド: チュートリアル (日本語版) (PDF:2.8MB)
IBM Informix SQL ガイド: チュートリアル バージョン 9.4 GB88-8633-00 (英文原典:G251-1244-00) IBM Informix SQL ガイド: チュートリアル バージョン 9.4 GB88-8633-00 (英文原典:G251-1244-00) お願い 本書および本書で紹介する製品をご使用になる前に、349 ページの『特記事項』に記載されている情報をお読みください。 本書には、IBM の専有情報が含まれています。その情報は、使用許諾条件に基づき提供され、著作権により保護され ています。本書に記載される情報には、いかなる製品の保証も含まれていません。また、本書で提供されるいかなる 記述も、製品保証として解釈すべきではありません。 IBM は、お客様が提供するいかなる情報も、お客様に対してなんら義務も負うことのない、自ら適切と信ずる方法 で、使用もしくは配布することができるものとします。 本書には、IBM の専有情報が含まれています。その情報は、使用許諾条件に基づき提供され、著作権により保護され ています。本書に記載される情報には、いかなる製品の保証も含まれていません。また、本書で提供されるいかなる 記述も、製品保証として解釈すべきではありません。 IBM は、お客様が提供するいかなる情報も、お客様に対してなんら義務も負うことのない、自ら適切と信ずる方法 で、使用もしくは配布することができるものとします。 本マニュアルに関するご意見やご感想は、次の URL からお送りください。今後の参考にさせていただきます。 http://www.ibm.com/jp/manuals/main/mail.html なお、日本 IBM 発行のマニュアルはインターネット経由でもご購入いただけます。詳しくは http://www.ibm.com/jp/manuals/ の「ご注文について」をご覧ください。 (URL は、変更になる場合があります) お客様の環境によっては、資料中の円記号がバックスラッシュと表示されたり、バックスラッシュが円記号と表示さ れたりする場合があります。 原 典: G251–1244–00 IBM Informix Guide to SQL Tutorial Version 9.4 発 行: 日本アイ・ビー・エム株式会社 担 当: ナショナル・ランゲージ・サポート 第1刷 2003.5 この文書では、平成明朝体™W3、平成明朝体™W9、平成角ゴシック体™W3、平成角ゴシック体™W5、および平成角 ゴシック体™W7を使用しています。この(書体*)は、 (財)日本規格協会と使用契約を締結し使用しているものです。 フォントとして無断複製することは禁止されています。 注* 平成明朝体™W3、平成明朝体™W9、平成角ゴシック体™W3、 平成角ゴシック体™W5、平成角ゴシック体™W7 © Copyright International Business Machines Corporation 1996, 2003. All rights reserved. © Copyright IBM Japan 2003 目次 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii 本書について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv 対象ユーザ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv ソフトウェア要件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv ロケールについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv デモンストレーション データベース . . . . . . . . . . . . . . . . . . . . . . . . . . xv Dynamic Server バージョン 9.4 の新機能 . . . . . . . . . . . . . . . . . . . . . . . . . xv 表記規則 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi 文字の表記 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi その他の規則 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi コメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii 機能、製品、およびプラットフォーム . . . . . . . . . . . . . . . . . . . . . . . . xvii 構文ダイヤグラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii 構文ダイヤグラムの読み方. . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii キーワードおよび句読点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx 識別子と名前 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx コード例の表記 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx 関連マニュアル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi 関連資料 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxii 業界標準への準拠 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxii 第 1 章 データベースの概念 . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 データ モデルによる説明 . . . . . . . . . . データの格納 . . . . . . . . . . . . . データの問合せ . . . . . . . . . . . . データの変更 . . . . . . . . . . . . . 複数のユーザによる同時利用とセキュリティ. . . . データベース利用の制御 . . . . . . . . . 集中管理. . . . . . . . . . . . . . . 重要なデータベース用語 . . . . . . . . . . リレーショナル データベース モデル (IDS のみ) . 表 . . . . . . . . . . . . . . . . . 列 . . . . . . . . . . . . . . . . . 行 . . . . . . . . . . . . . . . . . ビュー . . . . . . . . . . . . . . . シーケンス . . . . . . . . . . . . . . 表の操作. . . . . . . . . . . . . . . オブジェクト リレーショナル モデル (IDS のみ) . 構造化照会言語 (SQL) . . . . . . . . . . . 標準 SQL . . . . . . . . . . . . . . Informix SQL と ANSI 標準 SQL . . . . . . 対話型 SQL . . . . . . . . . . . . . 一般的なプログラミング . . . . . . . . . ANSI 標準準拠データベース. . . . . . . . 広域言語サポート (GLS) . . . . . . . . . サマリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . 2 . 3 . 4 . 5 . 5 . 5 . 6 . 6 . 6 . 7 . 7 . 7 . 8 . 8 . 9 . 10 . 10 . 10 . 11 . 11 . 11 . 12 . 12 第 2 章 SELECT 文の作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 SELECT 文について . SELECT 文の出力 . . . . . . . © Copyright IBM Corp. 1996, 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 . 17 iii ラージ オブジェクト データ型の出力 . . . . ユーザ定義 (user-defined) 型の出力 . . . . . 非デフォルト コード セットの出力 (GLS のみ) . 基本的な概念 . . . . . . . . . . . . . . アクセス権 . . . . . . . . . . . . . 関係演算 . . . . . . . . . . . . . . 選択と射影 . . . . . . . . . . . . . 結合 . . . . . . . . . . . . . . . . 単一表 SELECT 文 . . . . . . . . . . . . . アスタリスク記号 (*) の使用方法 . . . . . . . 列の再配列 . . . . . . . . . . . . . ORDER BY 節を使用した行のソート . . . . . . 昇順 . . . . . . . . . . . . . . . . 降順 . . . . . . . . . . . . . . . . 複数の列を基にしたソート . . . . . . . . 特定の列の選択 . . . . . . . . . . . . . サブ文字列の選択 . . . . . . . . . . . ORDER BY と英語以外のデータ (GLS のみ) . . WHERE 節の使用方法 . . . . . . . . . . . 比較条件の作成 . . . . . . . . . . . . . 行のインクルード . . . . . . . . . . . 行の除外 . . . . . . . . . . . . . . 行範囲の指定 . . . . . . . . . . . . . 特定範囲の行の除外 . . . . . . . . . . WHERE 節を使用した値のサブセットの検索 . . NULL 値の識別 . . . . . . . . . . . . 複合条件の作成 . . . . . . . . . . . . 正確なテキスト比較の使用 . . . . . . . . 変数テキスト検索の使用 . . . . . . . . . 単一文字ワイルドカードの使用 . . . . . . . MATCHES と非デフォルト ロケール (GLS のみ) 特殊文字のプロテクト . . . . . . . . . . WHERE 節でのサブスクリプトの使用方法 . . . 特定の行を選択するためのFIRST節の使用 . . . . ORDER BY 節を使用しない FIRST 節 . . . . ORDER BY 節を使用する FIRST 節 . . . . . 式と導出値 . . . . . . . . . . . . . . 算術式 . . . . . . . . . . . . . . . CASE 式 . . . . . . . . . . . . . . 導出列のソート . . . . . . . . . . . . SELECT 文での行 ID 値の使用. . . . . . . . 複数表の SELECT 文 . . . . . . . . . . . . デカルト積の作成 . . . . . . . . . . . . 結合の作成 . . . . . . . . . . . . . . 交差結合 (IDS のみ) . . . . . . . . . . 等価結合 . . . . . . . . . . . . . . 自然結合 . . . . . . . . . . . . . . 複数表結合 . . . . . . . . . . . . . 問合せのショートカット . . . . . . . . . . 別名の使用 . . . . . . . . . . . . . INTO TEMP 節 . . . . . . . . . . . . サマリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 17 17 18 18 18 18 20 22 22 23 24 24 24 25 27 31 32 33 34 35 35 36 37 38 39 40 40 41 42 45 46 46 47 47 48 49 49 53 54 55 56 56 57 57 58 60 62 64 64 66 67 第 3 章 複合 (Complex) 型データの選択 . . . . . . . . . . . . . . . . . . . . . 69 行 (ROW) 型データの選択 . 型付き表の列の選択 . . iv . . . . . . . . . . IBM Informix: SQL ガイド: チュートリアル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 . 71 行 (ROW) 型データが格納されている列の選択 . . . . . . . . . . フィールド射影 . . . . . . . . . . . . . . . . . . . . フィールド射影を使用した、入れ子になったフィールドの選択 . . . . アスタリスク表記による行 (ROW) 型のすべてのフィールドへのアクセス コレクション (COLLECTION) 型の選択 . . . . . . . . . . . . . . 入れ子コレクション (COLLECTION) 型の選択 . . . . . . . . . . キーワード IN でコレクション (COLLECTION) 型データ内の要素を検索 . 表階層にある行の選択 . . . . . . . . . . . . . . . . . . . . キーワード ONLY を使用しない上位表の行の選択 . . . . . . . . . キーワード ONLY を使用した上位表の行の選択 . . . . . . . . . . 上位表に別名を使用 . . . . . . . . . . . . . . . . . . . サマリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 73 73 74 75 76 77 78 80 80 81 81 第 4 章 SELECT 文での関数の使用. . . . . . . . . . . . . . . . . . . . . . . . 83 SELECT 文での関数の使用 . . . . . . . . . . 集計関数 . . . . . . . . . . . . . . . COUNT 関数の使用 . . . . . . . . . . AVG 関数の使用 . . . . . . . . . . . MAX 関数と MIN 関数の使用 . . . . . . . SUM 関数の使用 . . . . . . . . . . . RANGE 関数の使用 . . . . . . . . . . STDEV 関数の使用 . . . . . . . . . . . VARIANCE 関数の使用 . . . . . . . . . 式への関数の適用 . . . . . . . . . . . 時刻関数 . . . . . . . . . . . . . . . DAY 関数と CURRENT 関数の使用 . . . . . MONTH 関数の使用 . . . . . . . . . . WEEKDAY 関数の使用 . . . . . . . . . YEAR 関数の使用 . . . . . . . . . . . 日時 (DATETIME) 型値の形式 . . . . . . . 日付変換関数 (IDS のみ) . . . . . . . . . . DATE 関数の使用 . . . . . . . . . . . TO_CHAR 関数の使用 . . . . . . . . . . TO_DATE 関数の使用 . . . . . . . . . . 計数関数 (IDS のみ) . . . . . . . . . . . スマート ラージ オブジェクト関数 (IDS のみ) . . 文字列操作関数 (IDS のみ) . . . . . . . . . LOWER 関数の使用 . . . . . . . . . . UPPER 関数の使用 . . . . . . . . . . . INITCAP 関数の使用 . . . . . . . . . . REPLACE 関数の使用 . . . . . . . . . SUBSTRING 関数と SUBSTR 関数の使用 . . . SUBSTRING 関数の使用. . . . . . . . . SUBSTR 関数の使用 . . . . . . . . . . LPAD 関数の使用 . . . . . . . . . . . RPAD 関数の使用 . . . . . . . . . . . その他の関数 . . . . . . . . . . . . . LENGTH 関数の使用 . . . . . . . . . . USER 関数の使用 . . . . . . . . . . . TODAY 関数の使用 . . . . . . . . . . DBSERVERNAME 関数と SITENAME 関数の使用 HEX 関数の使用 . . . . . . . . . . . DBINFO 関数の使用 . . . . . . . . . . DECODE 関数の使用 . . . . . . . . . . NVL 関数の使用 (IDS のみ) . . . . . . . SELECT 文での SPL ルーチンの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 . 84 . 85 . 86 . 86 . 87 . 87 . 88 . 88 . 89 . 89 . 89 . 91 . 91 . 92 . 93 . 93 . 93 . 94 . 95 . 96 . 97 . 98 . 99 . 99 . 100 . 100 . 101 . 101 . 102 . 103 . 104 . 104 . 105 . 105 . 106 . 107 . 107 . 108 . 108 . 110 . 110 目次 v サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 第 5 章 高度な SELECT 文の作成. . . . . . . . . . . . . . . . . . . . . . . . 113 GROUP BY 節と HAVING 節の使用 . . . . . . . . . . . . . . . GROUP BY 節の使用方法 . . . . . . . . . . . . . . . . . . HAVING 節の使用方法 . . . . . . . . . . . . . . . . . . . 高度な結合の作成 . . . . . . . . . . . . . . . . . . . . . . セルフ結合 . . . . . . . . . . . . . . . . . . . . . . . 外部結合 . . . . . . . . . . . . . . . . . . . . . . . . 外部結合構文の Informix 拡張 . . . . . . . . . . . . . . . . ANSI 結合構文 . . . . . . . . . . . . . . . . . . . . . 左外部結合 . . . . . . . . . . . . . . . . . . . . . . 右外部結合 (IDS のみ) . . . . . . . . . . . . . . . . . . 単純結合 . . . . . . . . . . . . . . . . . . . . . . . 2 つの表の単純な外部結合 . . . . . . . . . . . . . . . . . 第 3 の表に対する単純結合との外部結合 . . . . . . . . . . . . 第 3 の表に対する 2 つの表の外部結合 . . . . . . . . . . . . 外部結合を組み合わせる結合 . . . . . . . . . . . . . . . . SELECT 文の副問合せ . . . . . . . . . . . . . . . . . . . . 選択リストの副問合せ . . . . . . . . . . . . . . . . . . . WHERE 節の中の副問合せ . . . . . . . . . . . . . . . . . . ALL の使用 . . . . . . . . . . . . . . . . . . . . . . ANY の使用. . . . . . . . . . . . . . . . . . . . . . 一価副問合せ . . . . . . . . . . . . . . . . . . . . . 相関副問合せ . . . . . . . . . . . . . . . . . . . . . EXISTS の使用 . . . . . . . . . . . . . . . . . . . . . SELECT 文でのコレクションの処理 (IDS のみ) . . . . . . . . . . . . コレクション (COLLECTION) 型副問合せ . . . . . . . . . . . . . コレクション (COLLECTION) 型の副問合せでのキーワード ITEM の省略 . コレクション (COLLECTION) 型の副問合せでのキーワード ITEM の指定 . コレクション (COLLECTION) 型導出表 . . . . . . . . . . . . . 集合演算 . . . . . . . . . . . . . . . . . . . . . . . . . 和集合. . . . . . . . . . . . . . . . . . . . . . . . . UNION と ORDER BY の使用 . . . . . . . . . . . . . . . UNION ALL の使用 . . . . . . . . . . . . . . . . . . . 異なる列名の使用 . . . . . . . . . . . . . . . . . . . . 複数の表に対する UNION の使用 . . . . . . . . . . . . . . 選択リスト内でのリテラルの使用. . . . . . . . . . . . . . . FIRST 節の使用 . . . . . . . . . . . . . . . . . . . . 積 . . . . . . . . . . . . . . . . . . . . . . . . . . 差 . . . . . . . . . . . . . . . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 114 117 119 120 123 124 124 124 126 126 127 128 129 130 130 131 132 132 133 134 135 136 138 139 139 140 140 142 142 144 144 145 146 147 147 148 149 150 第 6 章 データの変更 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 データベースの変更 . . . . . . . . . . . . . . . 行の削除 . . . . . . . . . . . . . . . . . . . 表のすべての行の削除 . . . . . . . . . . . . . TRUNCATE TABLE を使用したすべての行の削除 . . . . TRUNCATE TABLE を使用した上位表からの行の削除 . 指定された行の削除 . . . . . . . . . . . . . . 選択された行の削除 . . . . . . . . . . . . . . 行 (ROW) 型を含む行の削除 (IDS のみ) . . . . . . . コレクション (COLLECTION) 型を含む行の削除 (IDS のみ) 上位表からの行の削除 (IDS のみ) . . . . . . . . . 複雑な削除条件. . . . . . . . . . . . . . . . 削除結合の使用 (XPS のみ) . . . . . . . . . . . vi IBM Informix: SQL ガイド: チュートリアル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 153 153 154 154 154 154 155 156 156 156 157 行の挿入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 単一行. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . VALUES 節に指定できる値 . . . . . . . . . . . . . . . . . . . . . . 列値の制約事項. . . . . . . . . . . . . . . . . . . . . . . . . . . シリアル (SERIAL) 型 . . . . . . . . . . . . . . . . . . . . . . . . 特定の列名と値の指定 . . . . . . . . . . . . . . . . . . . . . . . . 型付き表への行の挿入 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型への挿入 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . 名前付き行 (named row) 型を含む行. . . . . . . . . . . . . . . . . . . . 名前なし行 (unnamed row) 型を含む行 . . . . . . . . . . . . . . . . . . . 行 (ROW) 型への NULL 値の指定 . . . . . . . . . . . . . . . . . . . . 上位表への行の挿入 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . 列へのコレクション (COLLECTION) 型値の挿入 (IDS のみ) . . . . . . . . . . . . 単純コレクション (COLLECTION) 型および入れ子コレクション (COLLECTION) 型への挿入 行 (ROW) 型を含むコレクション (COLLECTION) 型への NULL 値の挿入 . . . . . . . スマート ラージ オブジェクトの挿入 (IDS のみ) . . . . . . . . . . . . . . . . 複数の行の挿入および式の使用 . . . . . . . . . . . . . . . . . . . . . . INSERT 文に SELECT 文を使用する場合の制約. . . . . . . . . . . . . . . . . 行の更新 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 更新対象の行の選択 . . . . . . . . . . . . . . . . . . . . . . . . . . 一様値を使用する更新 . . . . . . . . . . . . . . . . . . . . . . . . . 更新の制限 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 選択値を使用する更新 . . . . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型の更新 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . 名前付き行 (named row) 型を含む行の更新 . . . . . . . . . . . . . . . . . 名前なし行 (unnamed row) 型を含む行の更新. . . . . . . . . . . . . . . . . 行 (ROW) 型のフィールドに対する NULL 値の指定 . . . . . . . . . . . . . . コレクション (COLLECTION) 型の更新 (IDS のみ) . . . . . . . . . . . . . . . 上位表の行の更新 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . . CASE 式による列の更新. . . . . . . . . . . . . . . . . . . . . . . . . SQL 関数を使用したスマート ラージ オブジェクトの更新 (IDS のみ) . . . . . . . . . 結合を使用した列の更新. . . . . . . . . . . . . . . . . . . . . . . . . データベースでのアクセス権 . . . . . . . . . . . . . . . . . . . . . . . . データベース レベル アクセス権. . . . . . . . . . . . . . . . . . . . . . 表レベル アクセス権 . . . . . . . . . . . . . . . . . . . . . . . . . . 表アクセス権の表示 . . . . . . . . . . . . . . . . . . . . . . . . . . データ整合性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . エンティティ保全性 . . . . . . . . . . . . . . . . . . . . . . . . . . 意味整合性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 参照整合性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ON DELETE CASCADE オプションの使用 . . . . . . . . . . . . . . . . . カスケード削除の例 . . . . . . . . . . . . . . . . . . . . . . . . . カスケード削除に対する制約 . . . . . . . . . . . . . . . . . . . . . . オブジェクトモードと違反の検出. . . . . . . . . . . . . . . . . . . . . . オブジェクト モードの定義 . . . . . . . . . . . . . . . . . . . . . . データ操作ステートメントのモード例 . . . . . . . . . . . . . . . . . . . 違反表と診断表. . . . . . . . . . . . . . . . . . . . . . . . . . . 中断された変更. . . . . . . . . . . . . . . . . . . . . . . . . . . . . トランザクション . . . . . . . . . . . . . . . . . . . . . . . . . . . トランザクション ログ . . . . . . . . . . . . . . . . . . . . . . . . . Extended Parallel Server のトランザクション ログ機能 . . . . . . . . . . . . . ロギングおよびカスケード削除 . . . . . . . . . . . . . . . . . . . . . トランザクションの指定. . . . . . . . . . . . . . . . . . . . . . . . . Informix データベース サーバを使用したバックアップとログ . . . . . . . . . . . . . 並行性およびロック . . . . . . . . . . . . . . . . . . . . . . . . . . . IBM Informix データ レプリケーション (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 目次 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 157 158 158 158 159 159 160 160 160 161 162 162 162 163 163 164 164 166 166 166 167 168 168 168 169 169 169 170 171 171 172 172 172 172 173 174 174 175 175 176 177 177 178 178 179 181 184 185 185 186 187 187 188 189 190 vii サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 第 7 章 外部データベースのデータへのアクセスおよび修正 . . . . . . . . . . . . . 193 他のデータベース サーバへのアクセス . . . . ANSI データベースへのアクセス . . . . . 外部データベース サーバ間の結合の作成 . . 外部ルーチンへのアクセス . . . . . . . リモート データベース アクセスの制約事項 . . SQL 文およびロギング モード . . . . . 外部データベース オブジェクトへのアクセス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 193 194 194 194 194 195 第 8 章 SQL を使用したプログラミング . . . . . . . . . . . . . . . . . . . . . 197 プログラム中の SQL . . . . . . . . . . . . . SQL API 中の SQL . . . . . . . . . . . . アプリケーション言語の SQL . . . . . . . . . 静的埋込み . . . . . . . . . . . . . . . 動的文. . . . . . . . . . . . . . . . . プログラム変数とホスト変数 . . . . . . . . . データベース サーバの呼出し . . . . . . . . . . SQL 通信領域 . . . . . . . . . . . . . . SQLCODE フィールド . . . . . . . . . . . データの終わり. . . . . . . . . . . . . 負数コード . . . . . . . . . . . . . . SQLERRD 配列. . . . . . . . . . . . . . SQLWARN 配列 . . . . . . . . . . . . . SQLERRM 文字列 . . . . . . . . . . . . . SQLSTATE 値 . . . . . . . . . . . . . . 単一行の抽出 . . . . . . . . . . . . . . . データ型の変換. . . . . . . . . . . . . . NULL データの処理 . . . . . . . . . . . . エラーの処理 . . . . . . . . . . . . . . データの終わり. . . . . . . . . . . . . ANSI 標準準拠でないデータベースのデータの終り . 重大なエラー . . . . . . . . . . . . . 集計関数とデータの終り. . . . . . . . . . デフォルト値の使用 . . . . . . . . . . . 複数行の抽出 . . . . . . . . . . . . . . . カーソルの宣言. . . . . . . . . . . . . . カーソルのオープン . . . . . . . . . . . . 行の取出し . . . . . . . . . . . . . . . データの終りの検出 . . . . . . . . . . . INTO 節の位置決め . . . . . . . . . . . カーソル入力モード . . . . . . . . . . . . カーソルのアクティブ セット . . . . . . . . . アクティブ セットの作成 . . . . . . . . . 順カーソルのアクティブ セット . . . . . . . スクロール カーソルのアクティブ セット. . . . アクティブ セットと並行性 . . . . . . . . カーソルの使用: 部品展開 . . . . . . . . . . 動的 SQL. . . . . . . . . . . . . . . . . 文の PREPARE 文による処理 . . . . . . . . . PREPARE 文で処理された SQL 文の実行 . . . . . 動的ホスト変数. . . . . . . . . . . . . . PREPARE 文で処理された文の解放 . . . . . . . 実行の高速化 . . . . . . . . . . . . . . データ定義文の埋込み . . . . . . . . . . . . viii IBM Informix: SQL ガイド: チュートリアル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 198 199 199 200 200 201 201 202 202 203 203 204 205 205 206 206 207 208 208 208 208 208 209 209 210 210 211 211 211 212 213 213 213 214 214 215 216 217 218 218 219 219 219 GRANT 文と EVOKE 文の埋込み サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 . 222 第 9 章 SQL プログラムによるデータの更新 . . . . . . . . . . . . . . . . . . . 223 DELETE の使用 . . . . . . . . . . . 直接的な削除 . . . . . . . . . . . 直接的な削除の途中で発生するエラー . . トランザクション ログの使用 . . . . . 整合性がある削除 . . . . . . . . . カーソルを使用した削除. . . . . . . . INSERT の使用. . . . . . . . . . . . INSERT カーソルの使用方法 . . . . . . INSERT カーソルの宣言. . . . . . . カーソルを使用した挿入. . . . . . . PUT 文と FLUSH 文の実行後の状態コード 定数の行 . . . . . . . . . . . . . 挿入の例 . . . . . . . . . . . . . UPDATE 文の使用 . . . . . . . . . . UPDATE カーソルの使用方法 . . . . . . キーワード UPDATE の目的 . . . . . 特定の列の更新. . . . . . . . . . 常に必要とされないキーワード UPDATE . 表の仕上げ . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 224 224 224 225 226 227 227 227 228 228 229 229 231 232 232 232 233 233 234 第 10 章 マルチユーザ環境のためのプログラミング. . . . . . . . . . . . . . . . . 235 並行性およびパフォーマンス . . . . . . . . . . . . . . . . . ロックおよび整合性 . . . . . . . . . . . . . . . . . . . . ロックおよびパフォーマンス . . . . . . . . . . . . . . . . . 並行性の問題 . . . . . . . . . . . . . . . . . . . . . . ロックの動作 . . . . . . . . . . . . . . . . . . . . . . ロックの種類 . . . . . . . . . . . . . . . . . . . . . ロック範囲 . . . . . . . . . . . . . . . . . . . . . . データベース ロック . . . . . . . . . . . . . . . . . . 表ロック . . . . . . . . . . . . . . . . . . . . . . 行とキーのロック . . . . . . . . . . . . . . . . . . . ページ ロック . . . . . . . . . . . . . . . . . . . . コアース インデックス ロック . . . . . . . . . . . . . . スマート ラージ オブジェクト ロック (IDS のみ) . . . . . . . . ロックの継続期間 . . . . . . . . . . . . . . . . . . . . データ修正中のロック . . . . . . . . . . . . . . . . . . SELECT 文でのロック . . . . . . . . . . . . . . . . . . . 排他レベルの設定 . . . . . . . . . . . . . . . . . . . . SET TRANSACTION 文と SET ISOLATION 文の比較 . . . . . . 排他レベルの非確定読込み (ANSI) と単純読込み (Informix) . . . . . 排他レベルの確定読込み (ANSI) および確定読込み (Informix) . . . . 排他レベルのカーソル安定性 (Informix). . . . . . . . . . . . 直列化可能 (ANSI)、繰返し可能読込み (ANSI)、および繰返し可能読込み UPDATE カーソル . . . . . . . . . . . . . . . . . . . 更新ロックの保存 . . . . . . . . . . . . . . . . . . . . . INSERT 文、UPDATE 文、および DELETE 文により設定するロック . . . ロック タイプの動作の理解 . . . . . . . . . . . . . . . . . アクセス モードによるデータ変更の制御 . . . . . . . . . . . . . ロック モードの設定 . . . . . . . . . . . . . . . . . . . . ロックの待機 . . . . . . . . . . . . . . . . . . . . . ロックの解除を待機しない . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (Informix) 排他レベル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 目次 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 236 236 237 238 238 239 239 239 241 242 243 243 244 244 245 245 245 246 246 247 249 249 250 251 251 252 253 253 253 ix 一定時間ロックの解除を待機する. デッドロックの処理 . . . . . 外部デッドロックの処理. . . . 単純な並行性 . . . . . . . . HOLD カーソル . . . . . . . SQL 文キャッシュの使用 . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 254 254 254 255 256 257 第 11 章 SPL ルーチンの作成と使用. . . . . . . . . . . . . . . . . . . . . . . 259 SPL ルーチンの概要 . . . . . . . . . . . . . . . . . . . . SPL ルーチンの機能 . . . . . . . . . . . . . . . . . . . Extended Parallel Server での SPL ルーチンの動作 . . . . . . . . . SPL ルーチンの作成 . . . . . . . . . . . . . . . . . . . . CREATE PROCEDURE 文または CREATE FUNCTION 文の使用 . . . . ルーチンの開始と終了 . . . . . . . . . . . . . . . . . ルーチン名の指定 . . . . . . . . . . . . . . . . . . . 固有名の追加 (IDS のみ) . . . . . . . . . . . . . . . . パラメータ リストの追加 . . . . . . . . . . . . . . . . RETURN 節の追加 . . . . . . . . . . . . . . . . . . 表示ラベルの追加 (IDS のみ) . . . . . . . . . . . . . . . SPL 関数がバリアントであるかどうかの指定 . . . . . . . . . . 修飾子の追加 (IDS のみ) . . . . . . . . . . . . . . . . DOCUMENT 節の指定 . . . . . . . . . . . . . . . . . リスト ファイルの指定 . . . . . . . . . . . . . . . . . コメントの追加. . . . . . . . . . . . . . . . . . . . 完全なルーチンの例 . . . . . . . . . . . . . . . . . . . プログラム内の SPL ルーチンの作成 . . . . . . . . . . . . . SPL ルーチンの削除 . . . . . . . . . . . . . . . . . . . 変数の定義と使用 . . . . . . . . . . . . . . . . . . . . . 局所変数の宣言. . . . . . . . . . . . . . . . . . . . . 局所変数の範囲. . . . . . . . . . . . . . . . . . . . 組込み型変数の宣言 . . . . . . . . . . . . . . . . . . スマート ラージ オブジェクト用の変数の宣言 (IDS のみ) . . . . . シンプル ラージ オブジェクト用の変数の宣言 . . . . . . . . . コレクション (COLLECTION) 型変数の宣言 (IDS のみ) . . . . . . 行 (ROW) 型変数の宣言 (IDS のみ) . . . . . . . . . . . . . 不透明 (OPAQUE) 型およびディスティンクト (DISTINCT) 型変数の宣言 LIKE 節による列データ用変数の宣言 . . . . . . . . . . . . PROCEDURE 型変数の宣言 . . . . . . . . . . . . . . . 変数とサブスクリプトの使用 . . . . . . . . . . . . . . . 変数およびキーワードのあいまいさ . . . . . . . . . . . . . 広域変数の宣言. . . . . . . . . . . . . . . . . . . . . 変数への値の代入 . . . . . . . . . . . . . . . . . . . . LET 文 . . . . . . . . . . . . . . . . . . . . . . 変数に値を代入する他の方法 . . . . . . . . . . . . . . . SPL ルーチンの式 . . . . . . . . . . . . . . . . . . . . . 文ブロックの記述 . . . . . . . . . . . . . . . . . . . . . 暗黙的および明示的文ブロック . . . . . . . . . . . . . . . カーソルの使用. . . . . . . . . . . . . . . . . . . . . FOREACH ループを使用したカーソルの定義 . . . . . . . . . . . IF - ELIF - ELSE 構造の使用 . . . . . . . . . . . . . . . . WHILE ループと FOR ループの追加 . . . . . . . . . . . . . ループの終了 . . . . . . . . . . . . . . . . . . . . . SPL 関数からの値の戻り . . . . . . . . . . . . . . . . . . 単一値の戻り . . . . . . . . . . . . . . . . . . . . . 複数値の戻り . . . . . . . . . . . . . . . . . . . . . x IBM Informix: SQL ガイド: チュートリアル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 261 262 262 263 263 264 264 265 267 267 268 268 270 270 271 271 272 272 273 274 274 275 275 275 276 277 278 278 279 279 280 281 282 282 284 284 284 285 285 286 288 289 291 291 292 292 行 (ROW) 型データの処理 (IDS のみ) . . . . . . . . . . . . . . . . . . . ピリオド表記の優先順位. . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型式の更新 . . . . . . . . . . . . . . . . . . . . . . . コレクションの処理 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型の使用 . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型の準備 . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型変数の宣言 . . . . . . . . . . . . . . . 要素変数の宣言. . . . . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型変数へのコレクション (COLLECTION) 型データの選択 コレクション (COLLECTION) 型変数への要素の挿入 . . . . . . . . . . . . . セット (SET) 型データまたはマルチセット (MULTISET) 型データへの挿入 . . . . リスト (LIST) 型データへの挿入 . . . . . . . . . . . . . . . . . . . リスト (LIST) 型のコレクションの基数検査 . . . . . . . . . . . . . . . VALUES 節の構文 . . . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型データからの要素の選択 . . . . . . . . . . . コレクション (COLLECTION) 型データ問合せ . . . . . . . . . . . . . . コレクション (COLLECTION) 型データ問合せの SPL ルーチンへの追加 . . . . . コレクション (COLLECTION) 型要素の削除 . . . . . . . . . . . . . . . . データベース内のコレクション (COLLECTION) 型データの更新 . . . . . . . . コレクション全体の削除. . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型要素の更新 . . . . . . . . . . . . . . . . 変数によるコレクション (COLLECTION) 型データの更新 . . . . . . . . . . コレクション全体の更新. . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型のコレクション (COLLECTION) 型データの更新 . . . . . . . . . 入れ子コレクション (COLLECTION) 型データの更新 . . . . . . . . . . . . コレクション (COLLECTION) 型データへの挿入 . . . . . . . . . . . . . . 入れ子コレクションへの挿入 . . . . . . . . . . . . . . . . . . . . ルーチンの実行. . . . . . . . . . . . . . . . . . . . . . . . . . . EXECUTE 文の使用 . . . . . . . . . . . . . . . . . . . . . . . . CALL 文の使用 . . . . . . . . . . . . . . . . . . . . . . . . . 式の中のルーチンの実行. . . . . . . . . . . . . . . . . . . . . . . RETURN 文による外部関数の実行 . . . . . . . . . . . . . . . . . . . SPL ルーチンからのカーソル関数の実行 . . . . . . . . . . . . . . . . . 動的ルーチン名の指定 . . . . . . . . . . . . . . . . . . . . . . . ルーチンのアクセス権 . . . . . . . . . . . . . . . . . . . . . . . . ルーチンを登録する権限. . . . . . . . . . . . . . . . . . . . . . . ルーチンを実行する権限. . . . . . . . . . . . . . . . . . . . . . . Execute アクセス権の付与と取消し . . . . . . . . . . . . . . . . . . COMMUTATOR 関数と NEGATOR 関数をともなう Execute アクセス権 (IDS のみ) . ルーチンに関連付けられたオブジェクトのアクセス権 . . . . . . . . . . . . . ルーチンを実行するための DBA アクセス権 . . . . . . . . . . . . . . . . SPL ルーチンのエラー検出 . . . . . . . . . . . . . . . . . . . . . . . コンパイル時の警告の表示 . . . . . . . . . . . . . . . . . . . . . . ルーチンのテキストの生成 . . . . . . . . . . . . . . . . . . . . . . SPL ルーチンのデバッグ . . . . . . . . . . . . . . . . . . . . . . . 例外処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . エラー トラッピングと復旧 . . . . . . . . . . . . . . . . . . . . . ON EXCEPTION 文の制御の有効範囲 . . . . . . . . . . . . . . . . . . ユーザが生成する例外 . . . . . . . . . . . . . . . . . . . . . . . SQL エラーのシミュレート. . . . . . . . . . . . . . . . . . . . . 入れ子コードを終了する RAISE EXCEPTION の使用 . . . . . . . . . . . . SPL ルーチンで処理される行数のチェック . . . . . . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 294 294 295 295 296 297 297 297 298 298 299 300 300 301 301 302 303 304 305 306 307 308 309 310 311 312 315 315 317 317 318 318 319 320 320 321 321 322 322 323 324 325 325 326 328 328 329 329 330 330 331 331 第 12 章 トリガの作成と使用 . . . . . . . . . . . . . . . . . . . . . . . . . . 333 トリガを使用するタイミング . . . . . . . . . . . . . . . . . . . . . . . . . . . . 目次 . 334 xi トリガの作成方法 . . . . . . . . . . . . . . . . . トリガ名の割当て . . . . . . . . . . . . . . . . トリガ イベントの指定 . . . . . . . . . . . . . . トリガ アクションの定義 . . . . . . . . . . . . . 完全な構成の CREATE TRIGGER 文 . . . . . . . . . トリガ アクションの使用方法 . . . . . . . . . . . . . BEFORE および AFTER トリガ アクションの使用方法 . . . FOR EACH ROW トリガ アクションの使用方法 . . . . . REFERENCING 節の使用方法 . . . . . . . . . . . WHEN 条件の使用方法 . . . . . . . . . . . . . トリガ アクションとしての SPL ルーチンの使用方法 . . . . SPL ルーチンへのデータ引き渡し . . . . . . . . . SPL の使用 . . . . . . . . . . . . . . . . . SPL ルーチンからのデータによる非トリガ列の更新 . . . 表階層のトリガ (IDS のみ) . . . . . . . . . . . . . . 選択トリガの使用 (IDS のみ) . . . . . . . . . . . . . トリガ アクションを実行する SELECT 文 . . . . . . . スタンドアロン SELECT 文 . . . . . . . . . . . SELECT 文の選択リストにあるコレクション (COLLECTION) ユーザ定義ルーチンに埋め込まれた SELECT 文. . . . . ビュー. . . . . . . . . . . . . . . . . . . 選択トリガの実行についての制限. . . . . . . . . . . 表階層の表に対する選択トリガ . . . . . . . . . . . リエントラント トリガ . . . . . . . . . . . . . . . ビューの INSTEAD OF トリガ (IDS のみ) . . . . . . . . INSTEAD OF トリガを使用してビュー上で更新 . . . . . . トリガ アクションのトレース . . . . . . . . . . . . . SPL ルーチン内の TRACE 文の例 . . . . . . . . . . TRACE 出力の例 . . . . . . . . . . . . . . . . エラー メッセージの生成 . . . . . . . . . . . . . . 固定エラー メッセージの適用 . . . . . . . . . . . . 可変エラー メッセージの生成 . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 型副問合せ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 335 335 336 336 337 337 338 338 339 339 340 340 340 340 341 341 341 341 341 342 342 342 342 343 343 344 344 344 345 345 346 347 特記事項. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 商標 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 xii IBM Informix: SQL ガイド: チュートリアル はじめに 本書について . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv 対象ユーザ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv ソフトウェア要件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv ロケールについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv デモンストレーション データベース . . . . . . . . . . . . . . . . . . . . . . . . . . xv Dynamic Server バージョン 9.4 の新機能 . . . . . . . . . . . . . . . . . . . . . . . . . xv 表記規則 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi 文字の表記 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi その他の規則 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi コメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii 機能、製品、およびプラットフォーム . . . . . . . . . . . . . . . . . . . . . . . . xvii 構文ダイヤグラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii 構文ダイヤグラムの読み方. . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii キーワードおよび句読点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx 識別子と名前 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx コード例の表記 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx 関連マニュアル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi 関連資料 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxii 業界標準への準拠 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxii 第 1 章 データベースの概念 . . . . . . . . . データ モデルによる説明 . . . . . . . . . . データの格納 . . . . . . . . . . . . . データの問合せ . . . . . . . . . . . . データの変更 . . . . . . . . . . . . . 複数のユーザによる同時利用とセキュリティ. . . . データベース利用の制御 . . . . . . . . . 集中管理. . . . . . . . . . . . . . . 重要なデータベース用語 . . . . . . . . . . リレーショナル データベース モデル (IDS のみ) . 表 . . . . . . . . . . . . . . . . . 列 . . . . . . . . . . . . . . . . . 行 . . . . . . . . . . . . . . . . . ビュー . . . . . . . . . . . . . . . シーケンス . . . . . . . . . . . . . . 表の操作. . . . . . . . . . . . . . . オブジェクト リレーショナル モデル (IDS のみ) . 構造化照会言語 (SQL) . . . . . . . . . . . 標準 SQL . . . . . . . . . . . . . . Informix SQL と ANSI 標準 SQL . . . . . . 対話型 SQL . . . . . . . . . . . . . 一般的なプログラミング . . . . . . . . . ANSI 標準準拠データベース. . . . . . . . 広域言語サポート (GLS) . . . . . . . . . サマリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . 1 . 2 . 3 . 4 . 5 . 5 . 5 . 6 . 6 . 6 . 7 . 7 . 7 . 8 . 8 . 9 . 10 . 10 . 10 . 11 . 11 . 11 . 12 . 12 序章について この序では、本書に記載された情報の概要を示し、使用する表記規則について説明 します。 © Copyright IBM Corp. 1996, 2003 xiii 本書について 本書では、データベース内のデータにアクセスし操作するための、構造化照会言語 (SQL) の基本的および高度な使用方法について説明します。データ操作言語 (DML) 文、トリガ、および DML 文が通常使用するストアド プロシジャ言語 (SPL) ルー チンについて記載します。 本書は、Informix の SQL インプリメンテーションに関する一連の資料のうちの一 冊です。「IBM Informix: SQL ガイド: 構文」には、SQL と SPL の構文記述につい て記載されています。「IBM Informix: SQL ガイド: 参照」には、SQL の、言語ス テートメントを除いた事項に関する参照情報が記載されています。そして、 「IBM Informix: データベース設計および実装 ガイド」には、SQL を使用してデー タベースを実装し、管理する方法について記載されています。 対象ユーザ 本書は、以下のユーザを対象としています。 v データベース ユーザ v データベース管理者 v データベース アプリケーション プログラマ 本書は、ユーザが以下の知識、または経験を持っていることを前提としています。 v コンピュータ、オペレーティング システム、およびオペレーティング システム が提供するユーティリティの実際的な知識 v リレーショナル データベース操作の経験、またはデータベースの概念の理解 v コンピュータ プログラミングの経験 リレーショナル データベース、SQL、またはご使用のオペレーティング システム に関する補足情報が必要な場合は、「IBM Informix: スタートアップ ガイド」の、 ご使用のデータベース サーバの項目を参照してください。 ソフトウェア要件 本書では、使用するデータベース サーバが、以下のいずれかであることを前提とし ています。 v IBM Informix Extended Parallel Server、バージョン 8.40 v IBM Informix Dynamic Server、バージョン 9.40 ロケールについて IBM Informix 製品は、多くの言語、地域特有の情報、およびコード セットをサポ ートします。文字セット、照合、数値データの表記、通貨、日付、および時刻に関 する情報はすべて、広域言語サポート (GLS) ロケールと呼ばれる 1 つの環境にま とめられています。 本書に記載する例は、デフォルト ロケール en_us.8859-1 を使用することを前提と しています。このロケールでは、日付、時刻、および通貨について、米国英語形式 規則をサポートします。さらにこのロケールでは、ASCII コード セットと、é、è、 および ñ などの多くの 8 ビット文字を含む ISO 8859-1 コード セットをサポート します。 xiv IBM Informix: SQL ガイド: チュートリアル データ、または SQL 識別子でデフォルト以外の文字を使用する場合、または文字 データをデフォルト以外の順序で照合する場合、適切なロケールを指定する必要が あります。 デフォルトでないロケールの指定方法、その他の構文、そして GLS に関連するそ の他の考慮事項については、「IBM Informix: GLS ユーザーズ ガイド」を参照して ください。 デモンストレーション データベース データベース サーバ製品に付属する DB–Access ユーティリティには、以下のデモ ンストレーション データベースが 1 つ以上含まれます。 v stores_demo データベースでは、架空のスポーツ用品卸売り業者の例を使用し て、関係スキーマについて説明します。 IBM Informix の資料に記載されている 例の多くは、 stores_demo データベースを基にしています。 Extended Parallel Server v sales_demo データベースは、データ ウェアハウジング アプリケーションの次 元スキーマを説明します。次元データ モデリングの概念情報については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。 Extended Parallel Server の終り Dynamic Server v superstores_demo データベースはオブジェクト リレーショナル スキーマにつ いて説明します。 superstores_demo データベースには、拡張 (extended) 型、 型および表の継承、およびユーザ定義ルーチンの例が含まれます。 Dynamic Server の終り デモンストレーション データベースの作成およびデータの追加については、 「IBM Informix: DB-Access ユーザーズ ガイド」を参照してください。それぞれの データベースおよびその内容の説明については、「IBM Informix: SQL ガイド: 参 照」を参照してください。 デモンストレーション データベースのインストールに使用するスクリプトは、 UNIX プラットフォームの場合は $INFORMIXDIR/bin ディレクトリ、Windows 環 境の場合は %INFORMIXDIR%¥bin ディレクトリにあります。 Dynamic Server バージョン 9.4 の新機能 このセクションでは、本書に記載する新機能をリストします。本書では、新機能を 記載すると同時に、旧バージョン以降に確認された誤記を修正しています。 本書には、以下の新機能について記載しています。 v CREATE TRIGGER 文を使用して、ビュー上に INSTEAD OF トリガを作成でき ます。この INSTEAD OF トリガを使用することで、ビューを更新できます。こ れは、旧リリースでは UPDATE 操作をサポートしていませんでした。 はじめに xv v SPL 機能で指定の表示ラベルを宣言できます。 v 交差結合と右外部結合がサポートされます。 データベース サーバの新機能のリストは、「IBM Informix: スタートアップ ガイ ド」を参照してください。 表記規則 ここでは、本書で使用する以下の表記規則について説明します。表記規則を覚えて おくと、本書、および他のマニュアルの内容を理解するのに役に立ちます。 以下のような表記規則があります。 v 文字の表記 v その他の表記 v 構文ダイヤグラム v コマンド行の表記 v コード例の表記 文字の表記 本書では、新しい用語、画面表示、コマンド構文などを表記するのに、以下の規則 を使用します。 表記規則 意味 KEYWORD プログラム言語の文中では、主要な要素 (キーワード) は、すべて大文字 のセリフ フォントで表記されます。 イタリック体 イタリック体 イタリック体 本文中では、新しい用語および強調語がイタリック体で表記されます。構 文とコードの例では、ユーザが指定する変数値は、イタリック体で表示さ れます。 太文字 太文字 プログラム エンティティの名前 (クラス、イベント、および表) 、環境 変数、ファイルやパス名、およびインターフェイス要素 (アイコン、メニ ュー項目、およびボタンなど) が太文字で表示されます。 モノスペース モノスペース 製品が表示する情報、およびユーザが入力する情報は、モノスペース タ イプフェイスで表記されます。 KEYSTROKE ユーザが押すキーは、大文字のサンセリフ フォントで表記されます ” この記号は、メニュー項目を表します。例えば「ツール」”「オプショ ン」は、「ツール」メニューから「オプション」項目を選択する、という 意味です。 ヒント: 文字を「入力」したり、コマンドを「実行」するように指示された場合 は、入力直後に RETURN を押してください。ただし、テキストを「入 力」、または他のキーを「押す」ように指示された場合は、RETURN を押す 必要はありません。 その他の規則 本書の本文では、いくつかの異なるマークアップにより、情報が識別されていま す。 xvi IBM Informix: SQL ガイド: チュートリアル コメント コメントは、以下の例に示す 3 種類の情報を示します。 警告: 重要な指示、注意、または情報を示します。 重要: 説明されている機能、または操作に関する重要な情報を示します。 ヒント: 説明されている機能の詳細、またはショートカットを示します。 機能、製品、およびプラットフォーム 機能、製品、およびプラットフォームのマークアップは、機能、製品、またはプラ ットフォームに特有な情報を表します。マークアップの例を以下に示します。 Dynamic Server IBM Informix Dynamic Server に固有な情報を示します。 Dynamic Server の終り UNIX のみ UNIX プラットフォームに固有な情報を示します。 UNIX のみ の終り Windows のみ Windows 環境に固有な情報を示します。 Windows のみ の終り これらのマークアップは、セクション内の 1 つ以上のパラグラフに適用される場合 があります。セクション全体が特定の製品またはプラットフォームに適用する場合 は、次のように見出しテキストで示します。 表のソート (Windows のみ) 構文ダイヤグラム 本書で使用するダイヤグラムは、以下のコンポーネントで構成されます。このダイ ヤグラムは、システム レベルのコマンドを除くすべてのコマンドと、文の構文を表 します。 注: バージョン 9.4 以降、構文ダイヤグラムは IBM 標準に準拠する形に再フォー マットされました。 SQL 文およびコマンド行文を表す構文ダイヤグラムは、以下のように変更されまし た。 v 文の最初と最後には、終端の縦線に代わり、二重矢印が使用されます。 v 構文サブダイヤグラムの最初と最後には、矢印の代わりに、縦線が使用されま す。 はじめに xvii v ループを繰り戻す回数を示す数字は、ゲート記号に代わり、大括弧に入れられま す。 v 1 行を超えた構文は、連続した行にループされるのではなく、次の行に示されま す。 v 製品または条件固有のパスは、アイコンではなく、括弧付きの肩文字でマークさ れるようになりました。 次の表に、構文ダイヤグラムのコンポーネントを示します。 コンポーネント 意味 文の開始を示します。 文が次行に続くことを示します。完結した文以外の構文 要素は、この記号で終わります。 文が前行からの続きであることを示します。完結した文 以外の構文要素は、この記号で始まります。 文の終端を示します。 必須項目。 オプショナル項目。 選択項目のある必須項目。1 つの必須項目とその選択項 目のみ、表示されます。 選択項目のあるオプショナル項目。デフォルト値がある 場合は、太文字で示されます。 オプショナル項目。複数の項目を使用できます。繰り返 す場合は、前にカンマを挿入します。 構文フラグメントの開始を示します。 構文フラグメントの終了を示します。 構文ダイヤグラムの読み方 以下の構文ダイヤグラムでは、前セクションの表にリストした要素をいくつか使用 しています。 xviii IBM Informix: SQL ガイド: チュートリアル No-Conversion ジョブの作成 onpladm create job job -n -d -p device -D database project -t table Run Mode -S server -T target このダイヤグラムの 2 行目には、Setting the Run Mode という名前のフラグメント があります。このフラグメントを、次のダイヤグラムで示します (ダイヤグラムに はフラグメント開始と終了のコンポーネントを使用します)。 Setting the Run Mode: l c -f d p a u n N このダイヤグラムを使用してコマンドを正確に構築するには、左上から開始しま す。次に、右方向にダイアグラムを読み、必要な要素を使用して進みます。このダ イヤグラム内の要素は、大文字と小文字の区別があります。 「No-Conversion ジョブの作成」ダイヤグラムは、以下の手順を示しています。 1. onpladm create job を入力し、次にジョブ名を入力します。 2. 必要な場合は -p を入力し、次にプロジェクト名を入力します。 3. 以下の必須要素を入力します。 v -n v -d およびデバイス名 v -D およびデータベース名 v -t および表名 4. オプションで、以下の中から 1 つ以上の要素を選択し、任意の回数繰り返すこ とができます。 5. v -S およびサーバ名 v -T およびターゲット サーバ名 v run mode。run mode を設定するには、Setting the Run Mode フラグメント ダ イヤグラムに従います。まず -f を入力し、次に d、p、または a をオプショ ンで入力し、最後に l または u をオプションで入力します。 6. 終端記号までダイヤグラムを読み進めます。 これで、ダイヤグラムが終了します。 はじめに xix キーワードおよび句読点 システム レベルのコマンドを除き、すべてのコマンドおよび文に予約された単語で す。構文ダイヤグラム内のキーワードは、大文字で表記されます。コマンド内のキ ーワードには、大文字と小文字の両方を使用できます。ただし、構文ダイヤグラム 内のキーワードとまったく同じスペルにしてください。 また、構文やコマンド内の句読点も、構文ダイヤグラム内とまったく同様に使用し なければなりません。 識別子と名前 変数は、構文ダイヤグラムや例の中で、識別子や名前の代わりに使用されます。変 数はコンテキストによって、任意の名前、識別子、リテラルに置き換えられます。 また、変数は、追加構文ダイヤグラムで拡張される、複合構文要素を表すためにも 使用されます。構文ダイヤグラム、例、またはテキスト内で使用される変数は、小 文字のイタリック体 で表記されます。 次の構文ダイヤグラムでは、変数を使用して、単純な SELECT 文の一般的な形を示 しています。 SELECT column_name FROM table_name この形の SELECT 文を作成する場合は、変数 column_name および table_name を、特定の列名と表名に置き換えます。 コード例の表記 本書では、多くの SQL コード例を記載しています。特に明記されていない限り、 記載されるコードは、特定の IBM Informix アプリケーション開発ツール専用では ありません。 例の中に含まれるのが、複数の SQL 文のみの場合、それらはセミコロン (;) で区 切られません。例えば、以下のようなコード例が使用されます。 CONNECT TO stores_demo ... DELETE FROM customer WHERE customer_num = 121 ... COMMIT WORK DISCONNECT CURRENT この SQL コードを特定の製品で使用する場合は、その製品の構文規則を適用する 必要があります。例えば DB–Access を使用する場合、文と文の間はセミコロン (;) で区切る必要があります。 SQL API を使用している場合、各文の先頭に EXEC SQL を、文末にセミコロン (;) (または他の適切な区切り記号) を使用する必要があ ります。 ヒント: コード例内の省略記号は、フル アプリケーションではそこにコードが追加 されることを示します。概念の説明には必要ないため、それらのコードは 省略されています。 特定のアプリケーション開発ツールや SQL API における、SQL 文の使用に関する 詳細は、その製品のマニュアルを参照してください。 xx IBM Informix: SQL ガイド: チュートリアル 関連マニュアル 関連マニュアルが様々な形式で提供されています。 v オンライン マニュアル。 http://www-3.ibm.com/software/data/informix/pubs/library/ の IBM Informix オンライン マニュアル サイトで、使用できるマニュアルを参 照できます。この Web サイトでは、章ごと、または資料全体を印刷できます。 v オンライン ヘルプ。 それぞれのグラフィカル ユーザ インターフェイス (GUI) には、そのインターフェイスについての情報および機能を表示するオンライン ヘ ルプが提供されています。オンライン ヘルプを表示するには、それぞれの GUI のヘルプ機能を使用してください。 この機能を使用して、詳細ヘルプ、エラー メッセージ解説、言語構文などを参照 することができます。 v ドキュメント ノートおよびリリース ノート。 マニュアルに対する追加や修正を 記載したドキュメント ノートおよびリリース ノートは、製品をインストールし たディレクトリにあります。 これらのファイルには、アプリケーション、およびパフォーマンスに関する重要 な情報が含まれているため、必ず確認するようにしてください。 次の表で、上記のファイルについて説明します。 UNIX のみ UNIX プラットフォームでは、以下のオンライン ファイルが $INFORMIXDIR/release/en_us/0333 ディレクトリにあります。 オンライン ファイル 内容 ids_sqlt_docnotes_9.40.html xps_sqlt_docnotes_8.40.html これは、このマニュアルのバージョン用のドキ ュメント ノート ファイルであり、マニュアル に含まれていない項目、またはマニュアルが出 版されてから変更された項目について説明しま す。 ids_unix_release_notes_9.40.html ids_unix_release_notes_9.40.txt xps_release_notes_8.40.html xps_release_notes_8.40.txt これはリリース ノート ファイルであり、 IBM Informix 製品の以前の機能との違い、お よびその違いが現在の製品に及ぼす影響を説明 します。このファイルには、問題点、および対 処方法も含まれます。 ids_machine_notes_9.40.txt xps_machine_notes_8.40.txt これはマシン ノート ファイルであり、コンピ ュータで IBM Informix 製品を設定および使用 するのに必要な作業を説明します。マシン ノ ートには、製品と同じ名前が付いています。 UNIX のみ の終り Windows のみ 次のものが、Informix フォルダに収められています。このフォルダを表示するに は、タスクバーから「スタート」”「プログラム」”「Informix」 ”「Documentation Notes or Release Notes」を選択します。 はじめに xxi プログラム グループの項目 説明 ドキュメント ノート マニュアルに対する追加や修正について説明しま す。また、マニュアルに含まれていない機能、ま たはマニュアルが出版されてから変更された機能 についても説明します。 リリース ノート IBM Informix 製品の旧バージョンとの機能の違 い、およびその違いが現在の製品に及ぼす影響に ついて説明します。このファイルには、問題点、 および対処方法も含まれます。 マシン ノートは、Windows プラットフォームには適用されません。 Windows のみ の終り v エラー メッセージ ファイル。IBM Informix ソフトウェア プロダクトが提供す る ASCII ファイルには、エラー メッセージとその修正処置が記載されていま す。 UNIX のみ UNIX でエラー メッセージを参照するには、finderr コマンドを使用し、オンラ インでエラー メッセージを表示させます。 UNIX のみ の終り Windows のみ Windows でエラー メッセージおよび修正処置を表示するには、Informix Error Messages ユーティリティを使用します。このユーティリティを表示するには、 タスクバーから「スタート」”「プログラム」”「Informix」を選択します。 Windows のみ の終り 関連資料 データベース サーバ、およびオペレーティング システム プラットフォームの概要 を説明する文献のリストは、「IBM Informix: スタートアップ ガイド」を参照して ください。 業界標準への準拠 米国規格協会 (ANSI) は、SQL 用の一連の業界標準を確立しました。 IBM Informix SQL 系製品は、ISO 9075:1992 と同一である、SQL-92 エントリ レ ベル (ANSI X3.135-1992 として発行) に完全準拠しています。さらに、Informix デ ータベース サーバの多くの機能が、SQL-92 中間および全レベル、および X/Open SQL CAE (共通アプリケーション環境) 標準に対応しています。 xxii IBM Informix: SQL ガイド: チュートリアル 第 1 章 データベースの概念 本章について この章では、基本的なデータベース概念と、以下のトピックの概要について説明し ます。 v データ モデル v 複数ユーザ v データベース用語 v SQL (構造化照会言語) データベースは、SELECT 文で開始します。これについては、15 ページの『第 2 章 SELECT 文の作成』で説明します。 データ モデルによる説明 データベースに収集される情報とファイルに収集される情報の基本的な違いは、デ ータの編成方法にあります。フラット ファイルは物理的に編成されます。つまり、 ある項目は他の項目の前か後といった関係しかありません。しかし、データベース の内容はデータ モデル に従って編成されます。データ モデルは計画またはマップ であり、データの単位を定義し、各単位間の相互関係を指定します。 例えば、数字はファイルにもデータベースにも入れることができます。ファイルで の数字は、ファイル内のある場所に置かれる単なる数字に過ぎません。これに対し て、データベースでの数字は、データ モデルによって割り当てられた特定のロール (データベース サーバ管理の役割分担) を持っています。このロールには、顧客 が 注文 した品目 として販売された製品 の価格 が含まれます。これら価格、製品、 品目、注文、および顧客というそれぞれの要素もまた、データ モデルによって指定 されたロールを持っています。データ モデルを図 1 に図示します。 © Copyright IBM Corp. 1996, 2003 1 図 1. データ モデル使用の利点 データ モデルの設計は、データベースを作成するときに行います。そのモデルから 策定される計画に従って、データの単位を挿入します。資料によっては、データ モ デル の代わりにスキーマ という用語を使用している場合があります。 データの格納 データベースには、データベースの編成方法も格納されます。これも、データベー スがファイルと異なる点です。 ファイルは複雑な内部構造を持っていますが、その構造の定義はファイル内ではな く、ファイルを作成したり使用したりするプログラムの内部に格納されます。例え ば、ワード プロセッシング プログラムに格納される文書ファイルには、文書の形 式を記述する詳細な構造が含まれる場合があります。しかし、この構造はファイル ではなくプログラム内で定義されているため、ワード プロセッシング プログラム のみがファイルの内容を解読することができます。 データ モデルの場合はその記述先となるデータベースに格納されます。したがって データベース内に構造が定義されているため、データベースを使用するすべてのプ ログラムでの利用が可能です。データ モデルはデータの項目名だけでなくデータ型 も定義するため、プログラムはデータベースに合わせて処理を変化させることがで きます。例えば、あるデータベースで価格 項目が 8 桁の 10 進数であり、小数部 2 IBM Informix: SQL ガイド: チュートリアル が 2 桁であるとします。プログラムは、このデータ型の数字に適した記憶域を割り 当てることができます。プログラムとデータベースの関係については、197 ページ の『第 8 章 SQL を使用したプログラミング』と 223 ページの『第 9 章 SQL プロ グラムによるデータの更新』で説明します。 データの問合せ データベースとファイルでは、そのアクセス方法も異なります。ファイル内のデー タは、順番に検索して、各行または各レコード内の特定の物理位置にある特定の値 を探すことができます。つまり、「1 番目のフィールドに 1013 という数値を持つ レコードはどれか」という問合せをすることになります。図 2 に、このタイプの検 索を示します。 図 2. ファイルの順次探索 これに対し、データベースに対して問合せを行う場合は、モデルで定義された用語 を使用します。データベースに対しては、次のような問合せを実行できます。 「New Jersey の顧客 が注文 した Shimara Corporation 製の製品 で、出荷日 が第 3 四半期のものは何か」。このタイプの問合せについて、図 3 に示します。 第 1 章 データベースの概念 3 図 3. データベースの問合せ つまり、ファイルに格納されているデータにアクセスする場合は、ファイルの物理 的なレイアウトを表す用語で問合せを行う必要があるということです。データベー スへの問合せを行うときは、コンピュータの記憶域に関する詳細は無視し、データ ベースで定義された現実の世界を反映する言葉を使用して、問合せを行うことがで きます。 問合せに使用する言語については、15 ページの『第 2 章 SELECT 文の作成』と 113 ページの『第 5 章 高度な SELECT 文の作成』で説明します。 また、データ モデルをビルドして実装する方法については、「IBM Informix: デー タベース設計および実装 ガイド」を参照してください。 データの変更 データ モデルを使用すると、データベースの内容を変更するときにミスを起こす可 能性を小さくすることもできます。例えば、「Presta または Schraeder というメー カー のすべての在庫品 を検索して、その価格 を 13% 上げる」というような文 で、データベースに問合せを行うことができます。このように、データの意味を反 映する用語で、変更内容を記述します。ファイル内にあるレコードのフィールドの 詳細を検討することに時間や労力を割く必要がなくなり、エラーの確率が低くなり ます。 格納されているデータを変更する文の詳細については、 151 ページの『第 6 章 デ ータの変更』を参照してください。 4 IBM Informix: SQL ガイド: チュートリアル 複数のユーザによる同時利用とセキュリティ データベースは、多くのユーザの共通資源にすることができます。 1 つのデータベ ースに対して、複数のユーザが同時に問合せや変更ができます。その場合は問合せ と変更が衝突せず順次処理されるよう、データベース サーバ (すべてのデータベー スの内容を管理するプログラム) が調整します。 ユーザが並行してデータベースを利用することには大きな利点がありますが、同時 にセキュリティとプライバシーという新たな問題が生じます。一部のデータベース はプライベートであり、個人が独自に使用するためにセットアップされています。 特定のグループ間でのみ共有する必要がある機密事項を格納するデータベースもあ ります。また、一般にアクセスできるデータベースもあります。 データベース利用の制御 Informix データベース ソフトウェアには、データベースの利用を制御する機能が組 み込まれています。次のように機能するように、データベースを設計することがで きます。 v 個人専用のデータベースにする。 v データベースの内容全体をすべてのユーザまたは特定のユーザに公開する。 v 一部のユーザに対し、表示できるデータの選択を制限する (ユーザのグループご とに異なるデータを表示する)。 v 特定のユーザに、特定のデータの表示を許可し、その変更を禁止する。 v 特定のユーザに、新しいデータの追加を許可し、古いデータの変更を禁止する。 v 特定のユーザに、既存のデータのすべて、あるいは特定の部分のみの変更を許可 する。 v 追加または変更されたデータが、データ モデルに準拠していることを確認する。 データベースに対するアクセス権を付与および制限する方法については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。 集中管理 多くの人が使用するデータベースは貴重であるため、大切なビジネス資産として保 護する必要があります。多くの貴重なデータをコンパイルし、なおかつ多くの社員 がそのデータへアクセスできるように管理することは、非常に重要な問題です。こ の難題を解決するには、パフォーマンスを維持しながらデータを保護する必要があ ります。データベース サーバを使用すれば、これらのタスクを集中化できます。 データベースは、損害が起こらないよう保護しなければなりません。ソフトウェア およびハードウェアの障害、火災や洪水といった自然災害のリスクなど、数多くの 危険があります。重要なデータベースが消失すると、かなりの確率で損害が発生し ます。損害が発生すると、消失したデータの再作成に費用および労力が発生するだ けでなく、データベース ユーザの生産時間が奪われ、ユーザが作業できない間に取 引や信用が失われることがあります。データベースを定期的にバックアップするこ とで、このような災害による影響を少なくすることができます。 多くのユーザが使用する大規模なデータベースの場合は、保守と調整が必要です。 担当者がシステム資源の利用状況やデータベースの発展過程を図表で監視し、障害 第 1 章 データベースの概念 5 が発生しやすい部分を予測し、データベースの拡張を計画することが必要です。ユ ーザからアプリケーション プログラムの問題が報告された場合、担当者は問題を診 断して解決しなければなりません。迅速な応答が重要な場合、担当者はシステムの パフォーマンスを分析して、応答が遅れる原因を突き止めなければなりません。 重要なデータベース用語 次の章に進む前に、いくつかの用語について理解しておく必要があります。使用す るデータベース サーバによって、データベースおよびデータ モデルを説明する用 語が異なる場合があります。 リレーショナル データベース モデル (IDS のみ) Informix データベース サーバで作成するデータベースは、オブジェクト リレーシ ョナル データベースです。実際には、すべてのデータは行 および列 で構成される 表 形式で格納されます。次にそれぞれの説明を示します。 関係 説明 表 = エンティティ 各表は、1 つの対象または 1 種類の事柄について データベースが持っているすべてのデータを表しま す。 列 = 属性 各列は、表が記述する対象が持つ 1 つの機能、特 性、またはファクトを表します。 行 = インスタンス 各行は、表が記述する対象が持つ 1 つのインスタ ンスを表します。 エンティティおよび属性の選択方法についてのルールもありますが、それらが重要 になるのはデータベースを新しく設計する場合だけです。 (データベース設計の詳 細については、「IBM Informix: データベース設計および実装 ガイド」を参照して ください。) 既存のデータベースではデータ モデルは既に設定されています。既存 のデータベースを使用する場合、表と列の名前、および表と列が現実の世界で何に 対応しているかを理解しておけば十分です。 表 データベースは、1 つ以上の表にグループ分けされる情報を収集したものです。表 は、行と列が編成するデータ項目 の配列です。デモンストレーション データベー スは、すべての Informix データベース サーバ製品と共に配布されます。次の図 に、デモンストレーション データベースの表の一部を示します。 6 IBM Informix: SQL ガイド: チュートリアル stock_num . . . manu_code . . . description . . . unit_price . . . unit . . . unit_descr . . . 1 HRO baseball gloves 250.00 case 10 gloves/case 1 HSK baseball gloves 800.00 case 10 gloves/case 1 SMT baseball gloves 450.00 case 10 gloves/case 2 HRO baseball 126.00 case 24/case 3 HSK baseball bat 240.00 case 12/case 4 HSK football 960.00 case 24/case 4 HRO football 480.00 case 24/case 5 . . . NRG . . . tennis racquet . . . 28.00 . . . each . . . each . . . 313 ANZ swim cap 60.00 case 12/box 表は、1 つのエンティティ、つまりデータベースが記述する対象の 1 つの型につい て、DBA (Database Administrator: データベース管理者) が格納するものすべてを表 現します。例の表 stock は、スポーツ用品店が在庫として持つ商品について、DBA が格納する必要のあるすべてを表しています。このほかに、デモンストレーション データベースには、customer や orders といったエンティティを表す表がありま す。 データベースは表の集合と考えることができます。データベースを作成すること は、互いに関連する複数の表を作成することになります。表に対して問い合わせま たは変更を行う権限は、表単位で制御することができるため、ユーザによって参照 または変更できる表が異なることもあります。 列 表の各列には、属性 が 1 つ含まれます。属性とは、表の対象を記述する 1 つの特 性、機能、またはファクトです。表 stock の列には、在庫品に関するファクトとし て、在庫数、メーカー コード、説明、価格、および取扱い単位が示されています。 行 表の各行は表の対象のインスタンス で、そのエンティティの具体例になります。表 stock の各行は、スポーツ用品店が販売する商品の各品目を表しています。 ビュー ビューは特定の SELECT 文に基づいた仮想表です。また、ビューはデータベースの 内容を動的に制御するピクチャでもあります。プログラマはこれを使用してユーザ が参照し、操作する情報を決定します。ユーザによって参照できるデータベースの 内容は異なり、これらの内容へのアクセスはいくつかの方法で制限することができ ます。 第 1 章 データベースの概念 7 シーケンス シーケンスは、定義された範囲内の番号シーケンスを生成するデータベース オブジ ェクトです。番号シーケンスは降順と昇順のいずれも可能であり、共に単調です。 シーケンスの詳細については、「IBM Informix: SQL ガイド: 構文」を参照してくだ さい。 表の操作 データベースは表の集まりなので、データベースの操作は表に対する操作というこ とになります。オブジェクト リレーショナル モデルは、選択、射影、結合という 3 つの基本操作をサポートしています。図 4 は選択および射影の操作を示していま す。これら 3 つの操作については、後の章で多数の例を使用して詳細に説明しま す。 図 4. 選択と射影の説明 表からデータを選択する 場合、選択する行と、無視する行とがあります。例えば、 データベース管理システムに対し、表 stock について「manufacturer code が HSK で、unit price が 200.00 から 300.00 である行をすべて選択する」という問合せを 行うことができます。 表からデータを射影する 場合、選択する列と、無視する列とがあります。例えば、 データベース管理システムに対し、表 stock について「列 stock_num、 unit_descr、および unit_price を射影する」という問合せを行うことができま す。 各表には 1 つのエンティティに関する情報のみが格納されるため、複数のエンティ ティについて情報が必要な場合はそれらの表を結合 しなければなりません。表を結 合するには多くの方法があります。結合操作の詳細については、 113 ページの『第 5 章 高度な SELECT 文の作成』 を参照してください。 8 IBM Informix: SQL ガイド: チュートリアル オブジェクト リレーショナル モデル (IDS のみ) Dynamic Server を使用してオブジェクト リレーショナル データベースをビルドで きます。オブジェクト リレーショナル データベースは、文字列、整数、日付、10 進数などの英数字データをサポートするとともに、次のオブジェクト関連機能によ り、リレーショナル モデルの機能を拡張します。 v 拡張性。新しいデータ型 (およびそれをサポートするアクセス方法と関数)、およ びユーザ定義ルーチン (UDR) を定義して、データベース サーバの機能を拡張す ることができます。これにより、画像、音声、映像、サイズの大きいテキスト文 書などを格納および管理することが可能になります。 IBM およびサード パーティ ベンダは、いくつかのデータ型とそのアクセス方法 を DataBlade モジュール または共有クラス ライブラリにパッケージ化していま す。ユーザは必要に応じて、これらをデータベース サーバにアドオンできます。 DataBlade モジュールを使用すると、直線、多角形、楕円、および円といった 2 次元空間 (地理空間) オブジェクトなどの非従来型のデータ型を格納して、R ツ リー インデックスからこれらにアクセスすることができます。また DataBlade モジュールには、サイズの大きいテキスト文書に対する新しいタイプのアクセス 方法が用意されており、これには、フレーズ照合、あいまい検索、シノニム照合 などが含まれます。 さらに、データ型およびアクセス方法を追加できる Dynamic Server の機能を使 用して、自分でデータベース サーバを拡張することもできます。詳しくは、 「IBM Informix: ユーザ定義ルーチンおよびデータ タイプ 開発者ガイド」を参照 してください。 UDR を SPL および C プログラム言語で作成し、アプリケーション論理のカプ セル化または Dynamic Server の機能拡張を実行できます。詳しくは、 259 ペー ジの『第 11 章 SPL ルーチンの作成と使用』 を参照してください。 v 複合 (Complex) 型。 1 つ以上の既存のデータ型を組み合わせた新しいデータ型 を定義することができます。複合 (Complex) 型を使用すれば、列や表のレベルで データをより柔軟に編成できます。例えば、単一型の値の集合を含む列や、複数 のコンポーネント型を含む列を、複合 (Complex) 型で定義することが可能です。 v 継承。 他のオブジェクトのプロパティを取得するオブジェクト (型および表) を 定義したり、定義したオブジェクトに固有のプロパティを新しく追加したりする ことができます。 Dynamic Server には、関係モデルがもつ以上のオブジェクト指向の機能があります が、データはすべて行 と列 をもつ表 の形式で表されます。オブジェクト リレー ショナル モデルはリレーショナル モデルの機能を拡張したものですが、必要に応 じて、データ モデルを従来型のリレーショナル データベースとして実装すること もできます。 エンティティおよび属性の選択方法についてのルールもありますが、それらが重要 になるのはデータベースを新しく設計する場合だけです。オブジェクト リレーショ ナル データベースの設計に関する詳細は、「IBM Informix: データベース設計およ び実装 ガイド」を参照してください。 第 1 章 データベースの概念 9 構造化照会言語 (SQL) ほとんどのコンピュータ ソフトウェアでは、「New Jersey の顧客が行った発注の うち出荷日が第 3 四半期にあたっているものはどれか」というような、日常用語で データベース問合せを行える段階には達していません。したがって、ユーザはソフ トウェアが簡単に解析できる制限的な構文で質問を記述する必要があります。次の ような用語を使用して、デモンストレーション データベースへの同じ質問を行うこ とができます。 SELECT * FROM customer, orders WHERE customer.customer_num = orders.customer_num AND customer.state = ’NJ’ AND orders.ship_date BETWEEN DATE(’7/1/98’) AND DATE(’9/30/98’) この問合せは、構造化照会言語 (SQL) の例です。 SQL とは、データベースに関す るすべての操作を指示するために使用する言語です。 SQL は文で構成され、各文 は、機能を指定する 1 つか 2 つのキーワードで開始します。 Informix に実装する SQL には、ALLOCATE DESCRIPTOR から WHENEVER 文におよぶ多くの SQL 文が含まれます。 ほとんどの文は、データベースをセットアップしたり、調整したりする場合にだけ 使用します。データベースへの問合せやデータベースの更新のために定期的に使用 する文は 3 つか 4 つです。 SQL 文の詳細については、「IBM Informix: SQL ガイ ド: 構文」を参照してください。 SELECT 文は、ほとんどの場合に使用します。 SELECT 文は、データベースから データを抽出するのに使用できる唯一の文です。また最も複雑な文でもあります。 本書では、第 2 章と第 3 章を SELECT 文の説明に当てています。 標準 SQL SQL および関係モデルは、1970 年代のはじめから半ばにかけて、IBM で発明およ び開発されました。 IBM によって、実用的なリレーショナル データベースの実装 が可能であること、および SQL がこれらを制御できる便利な言語であることが証 明されてから、他の SQL インプリメンテーションが開発されるようになりまし た。 パフォーマンスや競争力を高め、またはローカルなハードウェアやソフトウェア機 能を使用するために実装されるこれらの SQL は、インプリメンテーションごとに 異なっており、IBM バージョンの言語と微妙に異なっています。そこでこのような 相違点を最小限にするため、1980 年代初期に標準化委員会が設立されました。 米国規格協会 (ANSI) がスポンサーである委員会 X3H2 は、1986 年に SQL1 規格 を発行しました。この規格では、SQL 機能のコア セット、および SELECT などの 文の構文が定義されています。 Informix SQL と ANSI 標準 SQL Informix が実装する SQL は、標準 SQL と互換性があります。また、Informix SQL は、この言語の IBM バージョンとも互換性があります。ただし、Informix SQL に は、標準に対して拡張機能 が装備されているため、特定の文に対するオプションま たは機能、およびその他の広範なルールが追加されています。ただし、相違点のほ 10 IBM Informix: SQL ガイド: チュートリアル とんどは、日常的には使用頻度の低い文に関係しています。例えば、通常使用する SQL の 90% を占める SELECT 文には、ほとんど違いがありません。 ただし、Informix SQL の拡張機能が存在するため、矛盾が発生します。 Informix の数多くのユーザは、プログラムおよびストアド ルーチン内に Informix スタイル の SQL を埋め込んでいます。 IBM データ管理製品スイートに Informix 製品が組 み込まれた現在、ユーザは IBM に対して Informix スタイルの SQL 言語を変更し ないように要求しています。一方、ANSI 標準に完全に準拠する方法でデータベー スを使用する機能が必要なユーザも存在します。これらのユーザは、標準に準拠す るよう IBM が言語を変更することを要求しています。 IBM では、次のような調整を行うことでこの矛盾を解決します。 v 標準に対する拡張機能を備えた SQL の Informix スタイル バージョンをデフォ ルトで使用できる。 v Informix スタイルの SQL 言語処理プログラムに対して、SQL の使用をチェック し、 Informix の拡張機能を使用する場合は常に警告フラグを立てるように要求で きる。 Informix と ANSI SQL が異なる場合は、「IBM Informix: SQL ガイド: 構文」に両 方の説明が記載されています。しかしほとんどの場合、どちらか一方のバージョン しか使用しないため、必要のないバージョンは無視してください。 対話型 SQL 本書の例を実行したり、SQL およびデータベース設計を実験するには、SQL 文を対 話式に実行できるプログラムが必要です。 DB–Access は、このプログラムに該当し ます。このプログラムを使用すると、SQL 文を構成してから、SQL をデータベース サーバに渡して実行し、結果をユーザに表示することができます。 一般的なプログラミング SQL 文を取り込んでデータベース サーバとの間でデータを交換するプログラムを 作成できます。すなわち、データベースからデータを検索し、選択した形式にフォ ーマットできます。任意のソースから任意の形式でデータを取り出し、処理して、 データベースに挿入するプログラムを作成することもできます。 データベースのデータおよびオブジェクトと連動するような、ストアド ルーチンと 呼ばれるプログラムを作成することができます。作成したストアド ルーチンはデー タベースの表に直接格納されます。その後、DB–Access または IBM Informix ESQL/C のような SQL アプリケーション プログラム インターフェイス (SQL API) でストアド ルーチンを実行できます。 197 ページの『第 8 章 SQL を使用したプログラミング』と 223 ページの『第 9 章 SQL プログラムによるデータの更新』には、プログラム内での SQL の使用方法 の概要について記載しています。 ANSI 標準準拠データベース ANSI 標準準拠のデータベースを作成するには、作成時にキーワード MODE ANSI を使用します。そのようなデータベース内では、ANSI 標準の一定の特性が適用さ れます。例えば、データを更新する動作はすべて自動的にトランザクション内で実 第 1 章 データベースの概念 11 行されるため、変更は完全に行われるか、それとも全く行われないかが保証されま す。 ANSI 標準準拠のデータベース間の動作の違いについては、「IBM Informix: SQL ガイド: 構文」の文の説明に記載されています。ANSI 標準準拠データベース の詳細については、「IBM Informix: データベース設計および実装 ガイド」を参照 してください。 広域言語サポート (GLS) Informix データベース サーバ製品には、広域言語サポート (GLS) 機能がありま す。GLS を使用することで、U.S. ASCII 英語に加え、他のロケールで SQL データ および識別子に ASCII が対応していない文字を使用することができます。また、 GLS 機能を使用して特定のロケールの習慣に対応することができます。ロケール ファイルには、金額形式、日付形式、照合順序などについての文化に固有の情報が 含まれています。 GLS に関する詳細は、「IBM Informix: GLS ユーザーズ ガイ ド」を参照してください。 サマリ データベースは関連する情報の集まりですが、他のデータ格納方法とは基本的に異 なります。データベースには、データだけでなく、各データ項目を定義したり、そ の意味を他の項目や現実の世界と対比して指定するデータ モデルが格納されます。 複数のユーザが同時にデータベースにアクセスして変更を加えることができます。 ユーザによって参照できるデータベースの内容は異なり、これらの内容へのアクセ スはいくつかの方法で制限することができます。 リレーショナル データベースは表で構成され、表は列と行で構成されます。リレー ショナル モデルでは、選択、射影、結合という、表に対する 3 つの基本操作がサ ポートされています。 オブジェクト リレーショナル データベースは、リレーショナル データベースの機 能を拡張したものです。ユーザは、音声、映像、サイズの大きいテキスト文書など を格納および管理できる新しいデータ型を定義することができます。 1 つ以上の既 存のデータ型を組み合わせた複合 (Complex) 型を定義すると、データを、列や表に より柔軟に編成できます。また、別のデータベース オブジェクトのプロパティを継 承する型および表を定義したり、定義したオブジェクトに固有のプロパティを新し く追加したりできます。 データベースの操作、またはデータベースへの問合せを実行するには、SQL を使用 します。 SQL は IBM が開発し、ANSI が標準化した言語です。 ANSI で定義さ れた言語に Informix の拡張機能を追加して使用しますが、 IBM Informix ツールを 使用すると、ANSI 標準に厳密に準拠させることもできます。 データベース操作は、2 層のソフトウェアによって実行されます。下位層はデータ ベース サーバであり、常に SQL 文を実行し、ディスク内およびコンピュータ メ モリ内のデータを管理します。上位層は、IBM、ユーザ、他のベンダ、または他の ユーザなどにより作成される多くのアプリケーションのいずれかになります。ミド ルウェアはデータベース サーバとアプリケーションをリンクするコンポーネント 12 IBM Informix: SQL ガイド: チュートリアル で、データベース ベンダから提供され、クライアント プログラムをデータベース サーバにバインドします。 IBM Informix ストアド プロシジャ言語はそのようなツ ールの一例です。 第 1 章 データベースの概念 13 14 IBM Informix: SQL ガイド: チュートリアル 第 2 章 SELECT 文の作成 SELECT 文について . . . . . . . . . . . . SELECT 文の出力 . . . . . . . . . . . . ラージ オブジェクト データ型の出力 . . . . ユーザ定義 (user-defined) 型の出力 . . . . . 非デフォルト コード セットの出力 (GLS のみ) . 基本的な概念 . . . . . . . . . . . . . . アクセス権 . . . . . . . . . . . . . 関係演算 . . . . . . . . . . . . . . 選択と射影 . . . . . . . . . . . . . 結合 . . . . . . . . . . . . . . . . 単一表 SELECT 文 . . . . . . . . . . . . . アスタリスク記号 (*) の使用方法 . . . . . . . 列の再配列 . . . . . . . . . . . . . ORDER BY 節を使用した行のソート . . . . . . 昇順 . . . . . . . . . . . . . . . . 降順 . . . . . . . . . . . . . . . . 複数の列を基にしたソート . . . . . . . . 特定の列の選択 . . . . . . . . . . . . . サブ文字列の選択 . . . . . . . . . . . ORDER BY と英語以外のデータ (GLS のみ) . . WHERE 節の使用方法 . . . . . . . . . . . 比較条件の作成 . . . . . . . . . . . . . 行のインクルード . . . . . . . . . . . 行の除外 . . . . . . . . . . . . . . 行範囲の指定 . . . . . . . . . . . . . 特定範囲の行の除外 . . . . . . . . . . WHERE 節を使用した値のサブセットの検索 . . NULL 値の識別 . . . . . . . . . . . . 複合条件の作成 . . . . . . . . . . . . 正確なテキスト比較の使用 . . . . . . . . 変数テキスト検索の使用 . . . . . . . . . 単一文字ワイルドカードの使用 . . . . . . . 初めの文字の範囲を指定する WHERE 節 . . 可変長ワイルドカードを使用する WHERE 節 . MATCHES と非デフォルト ロケール (GLS のみ) 特殊文字のプロテクト . . . . . . . . . . WHERE 節でのサブスクリプトの使用方法 . . . 特定の行を選択するためのFIRST節の使用 . . . . ORDER BY 節を使用しない FIRST 節 . . . . ORDER BY 節を使用する FIRST 節 . . . . . 式と導出値 . . . . . . . . . . . . . . 算術式 . . . . . . . . . . . . . . . 表示ラベルの使用 . . . . . . . . . . CASE 式 . . . . . . . . . . . . . . 導出列のソート . . . . . . . . . . . . SELECT 文での行 ID 値の使用. . . . . . . . 複数表の SELECT 文 . . . . . . . . . . . . デカルト積の作成 . . . . . . . . . . . . 結合の作成 . . . . . . . . . . . . . . 交差結合 (IDS のみ) . . . . . . . . . . © Copyright IBM Corp. 1996, 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 17 17 17 17 18 18 18 18 20 22 22 23 24 24 24 25 27 31 32 33 34 35 35 36 37 38 39 40 40 41 42 43 43 45 46 46 47 47 48 49 49 51 53 54 55 56 56 57 57 15 等価結合 . . . . 自然結合 . . . . 複数表結合 . . . 問合せのショートカット 別名の使用 . . . INTO TEMP 節 . . サマリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 60 62 64 64 66 67 本章について SELECT は、最も重要かつ複雑な SQL 文です。この文は、SQL 文 INSERT、 UPDATE、および DELETE と共にデータを操作するために使用します。SELECT 文は、データベースからデータを抽出するために使用します。この時、INSERT 文 の一部として新規行を作成でき、UPDATE 文の一部として情報を更新できます。 SELECT 文はデータベース内の情報を問い合わせる主要な方法です。SELECT 文は プログラム、レポート、フォーム、スプレッドシートなどからデータを抽出する際 に重要な働きをします。また、SELECT 文は DB–Access のような問合せツールで 使用できるほか、アプリケーションに埋め込むこともできます。 この章では、SELECT 文を使用して、リレーショナル データベースへ問合せを行 い、データを抽出する基本的な方法を紹介します。具体的には、1 つ以上の表から 複数の列または行の情報を得るために文をカスタマイズする方法、SELECT 文に式 や関数をインクルードする方法、データベース内の表間のさまざまな結合条件を設 定する方法について説明します。 SELECT 文の構文および使用方法の詳細は、 「IBM Informix: SQL ガイド: 構文」に記載されています。 本書に記載されている例の大部分には、IBM Informix SQLAPI またはデータベース ユーティリティのソフトウェアに付属のデータベース stores_demo の表が使用さ れています。簡略化のため、各 SELECT 文では抽出されるデータの一部のみを例示 します。デモンストレーション データベースの構造と内容については、 「IBM Informix: SQL ガイド: 参照」を参照してください。SQL では大文字と小文 字を区別しませんが、例の中では強調するためにキーワードを大文字で表記してい ます。 SELECT 文について SELECT 文は、リレーショナル データベースのデータを選択して表示する機能を持 つ複数の節から構成されています。それらの節を使用すると、1 つ以上の表やビュ ーから 1 つ以上の条件を指定して列や行を抽出し、データの順番をそろえたり、集 計をとって一時表に格納することができます。 ここでは、SELECT 文を構成する 5 つの節の使用方法を説明します。 5 つの節は 次の順序で SELECT 文にインクルードしなければなりません。 1. SELECT 節 2. FROM 節 3. WHERE 節 4. ORDER BY 節 5. INTO TEMP 節 16 IBM Informix: SQL ガイド: チュートリアル SELECT 節と FROM 節のみが必須です。この 2 つの節は、抽出の対象となる表と 列を指定するため、データベースに対するすべての問合せの基本となります。他の 節は、次に示す目的に応じて使用します。 v 特定の行を選択したり、join 条件を作成する場合は、WHERE 節を追加する。 v データを作成する順序を変更する場合は、ORDER BY 節を追加する。 v 後で別の問合せで利用できるように問合せ結果を一時表に保存する場合は、INTO TEMP 節を追加する。 SELECT 文の 2 つの節 GROUP BY および HAVING をさらに使用すると、より 複雑なデータ抽出を行うことができます。これらの節については、 113 ページの 『第 5 章 高度な SELECT 文の作成』に記載されています。もう 1 つの節 INTO は、SELECT 文からデータを受け取るために、プログラムまたはホスト変数を指定 する場合に使用します。 SELECT 文を使用するための完全な構文およびルールにつ いては、「IBM Informix: SQL ガイド: 構文」に記載されています。 SELECT 文の出力 構文はすべての IBM Informix 製品に共通ですが、結果出力の形式と表示はアプリ ケーションに依存します。この章および第 5 章の例に示す SELECT 文とその出力 は、DB–Access で対話 (interactive) 型問合せ言語を使用した場合に表示されるもの を使用しています。 ラージ オブジェクト データ型の出力 ラージ オブジェクトを含む SELECT 文を発行する場合、DB–Access は以下のよう な結果を表示します。 v テキスト (TEXT) 型列または文字ラージ オブジェクト (CLOB) 型列には、列の 内容が表示される。 v バイト (BYTE) 型列には、実際値ではなく、<BYTE value> が表示される。 v バイナリ ラージ オブジェクト (BLOB) 型列には、実際値ではなく、 <SBlob data> が表示される。 ユーザ定義 (user-defined) 型の出力 DB–Access では、特別なルールを使用して、複合 (Complex) 型または不透明 (OPAQUE) 型を含む列からの出力を表示します。これらのデータ型については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。 非デフォルト コード セットの出力 (GLS のみ) 文字 (CHAR) 型列の代わりに各国語文字 (NCHAR) 型列を、または可変長文字 (VARCHAR) 型列の代わりに各国語可変長文字 (NVARCHAR) 型を問い合わせる SELECT 文を発行できます。 広域言語サポート (GLS) の情報については、「IBM Informix: GLS ユーザーズ ガ イド」を参照してください。非デフォルト コード セットにおける各国語文字 (NCHAR) 型および各国語可変長文字 (NVARCHAR) 型の使用方法の詳細について は、「IBM Informix: データベース設計および実装 ガイド」および「IBM Informix: SQL ガイド: 参照」を参照してください。 第 2 章 SELECT 文の作成 17 基本的な概念 SELECT 文は、INSERT、UPDATE、および DELETE 文とは異なり、データベース 内のデータを変更しません。単にデータの問合せを行います。データの変更は、1 回に 1 人のユーザしか実行できませんが、データの問合せや選択 は、複数のユー ザが同時に行うことができます。データを変更する文については、 151 ページの 『第 6 章 データの変更』を参照してください。INSERT、UPDATE、および DELETE 文の構文の説明は、「IBM Informix: SQL ガイド: 構文」を参照してくだ さい。 リレーショナル データベースでは 1 つの列 が 1 データ要素となり、表の各行に 共通して存在する特定のタイプの情報を表します。行 とは、単一のエンティティに 関する情報の集まりで、各項目がデータベースの表の各列に相当します。 SELECT 文を使用して、データベースの表、システム カタログ表、ビュー などの 行や列を選択することができます。システム カタログ表はデータベースに関する情 報を収めた特殊な表です。ビューはカスタマイズされたデータセットを格納するた めに作成された仮想表です。システム カタログ表については、「IBM Informix: SQL ガイド: 参照」に記載されています。また、ビューについては、 「IBM Informix: データベース設計および実装 ガイド」に記載されています。 アクセス権 データの問合せを行う前に、データベースの接続アクセス権と表の選択アクセス権 を所有している必要があります。通常、これらの権限はすべてのユーザに与えられ ています。データベースに対するアクセス権については、「IBM Informix: データベ ース設計および実装 ガイド」および「IBM Informix: SQL ガイド: 構文」の GRANT 文と REVOKE 文に記載されています。 関係演算 関係演算 では、1 つ以上の表または関係 を操作して、別の表を作成します。関係 演算には、選択、射影、結合の 3 種類があります。ここでは選択、射影、および簡 単な結合の例を示します。 選択と射影 リレーショナル データベースでいう選択 とは、1 つの表から特定の条件に合致し た行を水平方向 に抽出することを意味します。選択を行う SELECT 文は、表の中 のいくつかの行とその行に含まれる列をすべて戻します。選択は、SELECT 文の WHERE 節を使用して実装されます。図 5 にその例を示します。 SELECT * FROM customer WHERE state = ’NJ’ 図 5. 問合せ この問合せを行うと、図 6 に示すような結果になります。表 customer の中の指定 条件に合致したいくつかの行について、その行に属するすべての列が抽出されま す。この例では、DB–Access が個別行の各列のデータを表示します。 18 IBM Informix: SQL ガイド: チュートリアル customer_num fname lname company address1 address2 city state zipcode phone customer_num fname lname company address1 address2 city state zipcode phone 119 Bob Shorter The Triathletes Club 2405 Kings Highway Cherry Hill NJ 08002 609-663-6079 122 Cathy O‘Brian The Sporting Life 543d Nassau Princeton NJ 08540 609-342-0054 図 6. 問合せ結果 関係 (relational) 型の用語では、射影 は、一意な行を保持している 1 つの表の列か ら垂直方向の サブセットを取得することと定義されます。射影を行う、この種の SELECT 文は、表の中のいくつかの列とその列に含まれる行をすべて戻します。 射影は、SELECT 文の SELECT 節の選択リスト を使用して実装されます。 SELECT city, state, zipcode FROM customer 図 7. 問合せ 図 8 には、表 customer と同数の行がありますが、その表にある列のサブセットだ けが射影 されます。各行から少量のデータのみが選択されるため、DB–Access は行 からのすべてのデータを 1 行で表示できます。 第 2 章 SELECT 文の作成 19 city state zipcode Sunnyvale San Francisco Palo Alto Redwood City Los Altos Mountain View Palo Alto Redwood City Sunnyvale Redwood City Sunnyvale . . . Oakland Cherry Hill Phoenix Wilmington Princeton Jacksonville Bartlesville CA CA CA CA CA CA CA CA CA CA CA 94086 94117 94303 94026 94022 94063 94304 94063 94086 94062 94085 CA NJ AZ DE NJ FL OK 94609 08002 85016 19898 08540 32256 74006 図 8. 問合せ結果 通常使用する SELECT 文のほとんどは、選択と射影の両方を同時に行います。この ような問合せでは、図 9 に示すように、表の一部の行と列が戻されます。 SELECT UNIQUE city, state, zipcode FROM customer WHERE state = ’NJ’ 図 9. 問合せ 図 10 では、表 customer の一部の行と列が抽出されています。 city state zipcode Cherry Hill Princeton NJ NJ 08002 08540 図 10. 問合せ結果 結合 複数の表が共通の 1 つ以上の列に接続されている場合に結合が行われ、結果の新規 表が作成されます。表 items および表 stock のサブセットを使用した問合せを図 11 に示し、結合の概念を説明します。 20 IBM Informix: SQL ガイド: チュートリアル 図 11. 2 つの表の結合 図 12 では、表 customer と表 state を結合しています。 SELECT UNIQUE city, state, zipcode, sname FROM customer, state WHERE customer.state = state.code 図 12. 問合せ 図 13 は、表 customer と表 state の両方で指定した行および列から構成されてい ます。 第 2 章 SELECT 文の作成 21 city state zipcode sname Bartlesville Blue Island Brighton Cherry Hill Denver Jacksonville Los Altos Menlo Park Mountain View Mountain View Oakland Palo Alto Palo Alto Phoenix Phoenix Princeton Redwood City Redwood City Redwood City San Francisco Sunnyvale Sunnyvale Wilmington OK NY MA NJ CO FL CA CA CA CA CA CA CA AZ AZ NJ CA CA CA CA CA CA DE 74006 60406 02135 08002 80219 32256 94022 94025 94040 94063 94609 94303 94304 85008 85016 08540 94026 94062 94063 94117 94085 94086 19898 Oklahoma New York Massachusetts New Jersey Colorado Florida California California California California California California California Arizona Arizona New Jersey California California California California California California Delaware 図 13. 問合せ結果 単一表 SELECT 文 データベース内の 1 つの表に対する問合せにもさまざまな方法があります。 SELECT 文を目的に合わせて構成し、次の処理を実行できます。 v すべての列、または特定の列のみを抽出する。 v すべての行、または特定の行のみを抽出する。 v 抽出したデータに対して計算のみの処理を行う。 v 抽出したデータを目的に応じて並べ替える。 最も基本的な SELECT 文には、2 つの必須の節である SELECT 節および FROM 節のみが含まれます。 アスタリスク記号 (*) の使用方法 図 14 は、選択リスト の表 manufact のすべての列を指定します。明示的 選択リ ストは、表から射影する列名または式のリストです。 SELECT manu_code, manu_name, lead_time FROM manufact 図 14. 問合せ 図 15 では、選択対象リストの省略形としてワイルドカード を意味するアスタリス ク記号 (*) を使用し、表の中の列すべての名前を表しています。表のすべての列 22 IBM Informix: SQL ガイド: チュートリアル を、その定義されている順で指定する場合、このアスタリスク記号 (*) を使用しま す。暗黙的な 選択リストでは、アスタリスク記号を使用します。 SELECT * FROM manufact 図 15. 問合せ 表 manufact には 3 列しかないため、図 14 と図 15 は同じ処理を意味し、同じ結 果、つまり表 manufact 内のすべての列と行のリストを出力します。図 16 に結果 を示します。 manu_code manu_name SMT ANZ NRG HSK HRO SHM KAR NKL PRC Smith Anza Norge Husky Hero Shimara Karsten Nikolus ProCycle lead_time 3 5 7 5 4 30 21 8 9 図 16. 問合せ結果 列の再配列 図 17 の SELECT 文は、選択対象リストの順番を変えて、問合せ結果で表示される 列の順番を変える方法を示しています。 SELECT manu_name, manu_code, lead_time FROM manufact 図 17. 問合せ 図 18 には、直前の問合せ結果と同じ列が含まれていますが、列の順番の指定が異な るため表示が異なっています。 manu_name Smith Anza Norge Husky Hero Shimara Karsten Nikolus ProCycle manu_code lead_time SMT ANZ NRG HSK HRO SHM KAR NKL PRC 3 5 7 5 4 30 21 8 9 図 18. 問合せ結果 第 2 章 SELECT 文の作成 23 ORDER BY 節を使用した行のソート 問合せ結果は、特に順序付けされていません。例えば、20 ページの図 8 と図 18 は、ランダムな順序で表示されています。 ORDER BY 節を SELECT 文に追加し、特定の順序でデータをソートすることがで きます。 ORDER BY 節は、任意のリモートまたはローカルの表またはビューの列 名リストです。 SELECT リストで使用できる式はすべて、ORDER BY リストでも 使用できます。ORDER BY リストで使用される列が選択トリガを持つ場合、そのト リガは活動化されません。 図 19 は、表 manufact の列 manu_code、manu_name、および lead_time のす べての行を、lead_time の順にソートして戻します。 SELECT manu_code, manu_name, lead_time FROM manufact ORDER BY lead_time 図 19. 問合せ Dynamic Server 選択リストには、ORDER BY 節で使用する列を含めなくてもかまいません。つま り、選択リストに抽出されない列を基にソートすることもできます。 図 20 は、表 manufact の列 manu_code および manu_name のすべての行を、 lead_time の順にソートして戻します。列 lead_time は、SELECT リストで宣言されていませ んが、ORDER BY 節に含めることができます。 SELECT manu_code, manu_name, FROM manufact ORDER BY lead_time 図 20. 問合せ Dynamic Server の終り 昇順 SELECT 文が抽出したデータは、デフォルトでは昇順 にソートされて表示されま す。昇順は、文字 (CHARACTER) 型の場合は大文字の A から小文字の z への順序 になり、数値のデータ型の場合は最低値から最高値への順序になります。日付 (DATE) 型および日時 (DATETIME) 型の場合は、最も早い日時から最新の日時への 順序、時間隔 (INTERVAL) 型の場合は最短の期間から最長の期間への順序になりま す。 降順 降順は昇順とは逆に、文字 (CHARACTER) 型の場合は、英小文字の z から始まり 大文字の A に至る順序です。数値 (NUMERIC) 型の場合は数値が減少していく順序 です。漢字などの日本語文字は文字コードの逆順になります。日付 (DATE) 型およ び日時 (DATETIME) 型の場合は、最新の日時から最も早い日時への順序、時間隔 24 IBM Informix: SQL ガイド: チュートリアル (INTERVAL) 型の場合は最長の期間から最短の期間への順序になります。 図 21 に、降順の例を示します。 SELECT * FROM manufact ORDER BY lead_time DESC 図 21. 問合せ 列名の後にキーワード DESC が続く場合は、抽出されたデータが降順 にソートさ れます。図 22 に例を示します。 manu_code manu_name SHM KAR PRC NKL NRG HSK ANZ HRO SMT Shimara Karsten ProCycle Nikolus Norge Husky Anza Hero Smith lead_time 30 21 9 8 7 5 5 4 3 図 22. 問合せ結果 ORDER BY 節にはどのような列でも指定でき (テキスト (TEXT) 型、バイト (BYTE) 型、バイナリ ラージ オブジェクト (BLOB) 型、または文字ラージ オブジ ェクト (CLOB) 型を除く) 、データベース サーバはその列の値に基づいてデータを ソートします。 複数の列を基にしたソート 複数の列に ORDER BY を指定して、多重ソート を実行することもできます。デフ ォルトは昇順のままですが、ORDER BY 節で最初にリストされる列が優先されま す。 図 23 と図 25、およびそれぞれに対応する問合せ結果に、多重ソートの例を示しま す。選択されたデータの表示の順番を変更するには、ORDER BY 節で命名した 2 つの列の順番を変えます。 SELECT stocknum, manu_code, description, unit_price FROM stock ORDER BY manu_code, unit_price 図 23. 問合せ 図 24 では、列 manu_code の値がアルファベット順に並ぶようにソートされ、 ANZ、HRO など、同じ manu_code を持つ行はさらに列 unit_price の値により 昇順にソートされています。 第 2 章 SELECT 文の作成 25 stock_num manu_code description unit_price 5 9 6 313 201 310 ANZ ANZ ANZ ANZ ANZ ANZ tennis racquet volleyball net tennis ball swim cap golf shoes kick board $19.80 $20.00 $48.00 $60.00 $75.00 $84.00 111 112 113 5 6 1 SHM SHM SHM SMT SMT SMT 10-spd, assmbld 12-spd, assmbld 18-spd, assmbld tennis racquet tennis ball baseball gloves $499.99 $549.00 $685.90 $25.00 $36.00 $450.00 . . . 図 24. 問合せ結果 図 25 では、ORDER BY 節の列の順序は逆になります。 SELECT stock_num, manu_code, description, unit_price FROM stock ORDER BY unit_price, manu_code 図 25. 問合せ 図 26 では、データは unit_price の昇順に表示され、複数の行に同じ unit_price がある場合 (例えば、$20.00、$48.00、$312.00)、manu_code はアルファベット順 に表示されます。 stock_num manu_code description unit_price 302 302 5 9 103 HRO KAR ANZ ANZ PRC ice pack ice pack tennis racquet volleyball net frnt derailleur $4.50 $5.00 $19.80 $20.00 $20.00 108 6 305 303 311 SHM ANZ HRO PRC SHM crankset tennis ball first-aid kit socks water gloves $45.00 $48.00 $48.00 $48.00 $48.00 113 1 8 4 SHM HSK ANZ HSK 18-spd, assmbld baseball gloves volleyball football . . . . . . $685.90 $800.00 $840.00 $960.00 図 26. 問合せ結果 ORDER BY 節の列の順序、およびキーワード DESC の位置は重要です。 図 27 中 の各文の ORDER BY 節に含まれている構成要素は同じですが、それぞれが異なる 結果を出力します。ここでは出力結果は表示していません。 26 IBM Informix: SQL ガイド: チュートリアル SELECT * FROM stock ORDER BY manu_code, unit_price DESC SELECT * FROM stock ORDER BY unit_price, manu_code DESC SELECT * FROM stock ORDER BY manu_code DESC, unit_price SELECT * FROM stock ORDER BY unit_price DESC, manu_code 図 27. 問合せ 特定の列の選択 前節では、表からすべてのデータを抽出して順序付けする方法について説明しまし た。しかし、すべてのデータではなく、特定の列のデータのみを抽出する場合もよ くあります。この場合も、SELECT 節と FROM 節を使用して列と表を指定しま す。通常、ORDER BY 節も指定して、データを昇順か降順に並べます。 表 orders のすべての顧客番号を探索する場合は、図 28 に示す文を使用します。 SELECT customer_num FROM orders 図 28. 問合せ この問合せ結果は、図 29 に示すように、表 orders の列 customer_num のデー タをすべて抽出してリスト表示します。重複した顧客番号も表示されます。 customer_num 104 101 104 . . . 122 123 124 126 127 図 29. 問合せ結果 問合せ結果に重複する顧客番号が含まれているのは、一部の顧客が複数件の注文を 出しているためです。重複した行を射影で表示させる必要がある場合もあります。 それ以外では、それぞれの値が表示される頻度ではなく、個々の異なる値を表示す るだけでよいのです。 重複行を非表示にするには、問合せのレベルごとに、キーワード DISTINCT、また はそのシノニムである UNIQUE を選択対象リストの先頭にインクルードします。 図 30 に例を示します。 第 2 章 SELECT 文の作成 27 SELECT DISTINCT customer_num FROM orders SELECT UNIQUE customer_num FROM orders 図 30. 問合せ リストを読みやすくするには、図 30 を使用して、図 31 で示すように表 orders の 顧客番号のみの表示にします。 customer_num 101 104 106 110 111 112 115 116 117 119 120 121 122 123 124 126 127 図 31. 問合せ結果 ある顧客からの電話問合せで、顧客注文番号 DM354331 を検索する必要があるとし ます。表 orders のすべての顧客注文番号をリストするために、図 32 で示す文を 使用します。 SELECT po_num FROM orders 図 32. 問合せ この SELECT 文の問合せ結果は、図 33 に示すように、表 orders の列 po_num をすべて抽出して表示します。 po_num B77836 9270 B77890 8006 2865 Q13557 278693 . . . 図 33. 問合せ結果 28 IBM Informix: SQL ガイド: チュートリアル しかし、このリストは便利な順番に並んでいるとはいえません。 ORDER BY 節を 追加して列データを昇順でソートすると、図 35 で示すように特定の po_num を検 出しやすくすることができます。 SELECT po_num FROM orders ORDER BY po_num 図 34. 問合せ po_num 278693 278701 2865 429Q 4745 8006 8052 9270 B77836 B77890 . . . 図 35. 問合せ結果 表から複数の列を選択するには、SELECT 節の選択リストにこれらの列をリストし ます。 図 36 に示すように、列を選択する順序は、列が生成される順序、つまり左 から右への順序になります。 SELECT ship_date, order_date, customer_num, order_num, po_num FROM orders ORDER BY order_date, ship_date 図 36. 問合せ 25 ページの『複数の列を基にしたソート』に示すように、ORDER BY 節を使用し てデータを昇順または降順にソートし、多重ソートを行うことができます。 図 37 に、昇順の例を示します。 第 2 章 SELECT 文の作成 29 ship_date order_date customer_num 06/01/1998 05/26/1998 05/23/1998 05/30/1998 06/09/1998 05/20/1998 05/21/1998 05/22/1998 05/22/1998 05/24/1998 05/30/1998 05/31/1998 06/07/1998 06/14/1998 06/17/1998 06/18/1998 06/18/1998 06/22/1998 06/25/1998 06/27/1998 06/29/1998 07/09/1998 07/10/1998 07/11/1998 07/11/1998 07/23/1998 07/24/1998 07/24/1998 06/05/1998 07/06/1998 06/21/1998 06/29/1998 06/29/1998 07/03/1998 07/10/1998 07/03/1998 07/16/1998 07/12/1998 07/13/1998 07/13/1998 07/16/1998 07/16/1998 07/25/1998 07/30/1998 07/30/1998 104 101 104 106 116 112 117 110 111 115 117 104 104 106 110 119 120 121 122 123 124 126 127 order_num po_num 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1012 1011 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 B77836 9270 B77890 8006 2865 Q13557 278693 LZ230 4745 429Q 278701 B77897 B77930 8052 MA003 PC6782 DM354331 S22942 Z55709 W2286 C3288 W9925 KF2961 図 37. 問合せ結果 SELECT と ORDER BY 節を使用して表の中の複数列を抽出する場合、ORDER BY 節で整数を使用すると、列の位置を簡単に参照できるようになります。 ORDER BY リストの要素に整数がある場合、データベース サーバはそれを、選択リスト内の位 置と認識します。例えば、ORDER BY リストで 3 (ORDER BY 3) を使用する場合 は、選択リストの 3 番目が参照されます。 図 38 の文は、図 39 に示すように、同 じデータを抽出し、表示します。 SELECT customer_num, order_num, po_num, order_date FROM orders ORDER BY 4, 1 SELECT customer_num, order_num, po_num, order_date FROM orders ORDER BY order_date, customer_num 図 38. 問合せ 30 IBM Informix: SQL ガイド: チュートリアル customer_num order_num po_num 104 101 104 106 116 112 117 110 111 115 104 117 104 106 110 119 120 121 122 123 124 126 127 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 B77836 9270 B77890 8006 2865 Q13557 278693 LZ230 4745 429Q B77897 278701 B77930 8052 MA003 PC6782 DM354331 S22942 Z55709 W2286 C3288 W9925 KF2961 order_date 05/20/1998 05/21/1998 05/22/1998 05/22/1998 05/24/1998 05/30/1998 05/31/1998 06/07/1998 06/14/1998 06/17/1998 06/18/1998 06/18/1998 06/22/1998 06/25/1998 06/27/1998 06/29/1998 07/09/1998 07/10/1998 07/11/1998 07/11/1998 07/23/1998 07/24/1998 07/24/1998 図 39. 問合せ結果 図 40 に示すように、列名に整数を割り当てた場合は、キーワード DESC を ORDER BY 節に含めることができます。 SELECT customer_num, order_num, po_num, order_date FROM orders ORDER BY 4 DESC, 1 図 40. 問合せ このように指定すると、抽出されたデータは、まず列 order_date の値で降順にソ ートされ、次に列 customer_num の値で昇順にソートされます。 サブ文字列の選択 サブ文字列 を選択リストに含めることにより、文字カラムの値の一部を選択するこ とができます。マーケティング部門で顧客にダイレクト メールを発送することにな り、郵便番号を基にして顧客の居住分布を調査すると仮定します。 図 41 に示す問 合せと同様の文を記述します。 SELECT zipcode[1,3], customer_num FROM customer ORDER BY zipcode 図 41. 問合せ 図 41 では、サブ文字列で列 zipcode (州を示す) の最初の 3 文字と customer_num 全体を選択して、図 42 で示されているように、それらを郵便番号 で昇順にリストします。 第 2 章 SELECT 文の作成 31 zipcode customer_num 021 080 085 198 322 . . . 943 943 946 125 119 122 121 123 103 107 118 図 42. 問合せ結果 ORDER BY と英語以外のデータ (GLS のみ) Informix データベース サーバでは、デフォルトで、データベースのデータに対して 米国英語 (U.S. English) 言語環境が使用されます。米国英語 (U.S. English) ロケー ルは、コード セット順にソートされたデータを指定します。このデフォルト ロケ ールは、ISO 8859-1 コード セットを使用します。 データベースに英語以外のデータが含まれている場合、データを各国語文字 (NCHAR) 型、または各国語可変長文字 (NVARCHAR) 型の列に格納し、データの 言語でソートできるようにする必要があります。 ORDER BY 節は、各言語に対応 した順序でデータを戻す必要があります。 図 43 では、SELECT 文の ORDER BY 節を使用して、表 abonnés を検索し、選択された情報を列 nom 内のデータでソ ートします。 SELECT numéro,nom,prénom FROM abonnés ORDER BY nom 図 43. 問合せ この問合せ結果の照合順序は、次のようにシステムによって異なります。 v 列 nom が文字 (CHAR) 型の場合と各国語文字 (NCHAR) 型の場合。データベ ース サーバは文字 (CHAR) 型列のデータをコード セットに出てくる順序でソー トします。データベース サーバは各国語文字 (NCHAR) 型列のデータをロケール の照合部分にリストされている文字の順序でソートします。 v データベースへのアクセス時に、データベース サーバが英語以外の正しいロケー ルを使用している場合。英語以外のロケールを使用するには、環境変数 CLIENT_LOCALE および DB_LOCALE を該当するロケール名に設定する必要が あります。 図 43 で予想通りの結果を戻すには、列 nom が、フランス語のロケールを使用す るデータベース内の各国語文字 (NCHAR) 型データでなければなりません。また、 より小さい、より大きい、...に等しいなどの演算は、ユーザ指定のロケールの影響を 受けます。英語以外のデータおよびロケールに関する詳細は、「IBM Informix: GLS ユーザーズ ガイド」を参照してください。 32 IBM Informix: SQL ガイド: チュートリアル 図 44 と図 45 に、2 つの異なる出力を示します。 numéro nom prénom 13612 13606 13607 13602 13604 13610 13613 13603 13611 13609 13600 13615 13601 13608 13605 13614 Azevedo Dupré Hammer Hämmer LaForêt LeMaître Llanero Montaña Oatfield Tiramisù da Sousa di Girolamo Ålesund Étaix Ötker Øverst Edouardo Freire Michèle Françoise Gerhard le Greta Jean-Noël Héloïse Gloria Dolores José Antonio Emily Paolo Alfredo João Lourenço Antunes Giuseppe Sverre Émile Hans-Jürgen Per-Anders 図 44. 問合せ結果 図 44 は、ISO 8859-1 のコード セット順に準拠しています。小文字より大文字が前 に順序付けられており、アクセント付き文字で始まる名前 (Ålesund、Étaix、Ötker、 および Øverst) をリストの末尾に移動します。 numéro nom prénom 13601 13612 13600 13615 13606 13608 13607 13602 13604 13610 13613 13603 13611 13605 13614 13609 Ålesund Azevedo da Sousa di Girolamo Dupré Étaix Hammer Hämmer LaForêt LeMaître Llanero Montaña Oatfield Ötker Øverst Tiramisù Sverre Edouardo Freire João Lourenço Antunes Giuseppe Michèle Françoise Émile Gerhard le Greta Jean-Noël Héloïse Gloria Dolores José Antonio Emily Hans-Jürgen Per-Anders Paolo Alfredo 図 45. 問合せ結果 図 45 は、データベース サーバが適切なロケール ファイルを参照した場合、英語以 外の文字を含む名前 (Ålesund、Étaix、Ötker、および Øverstt) が ISO 8859-1 コード セットとは異なる順序で照合されることを示しています。英語以外で始まっている 名前は、ロケールで正しくソートされます。この場合、大文字と小文字は区別され ません。 WHERE 節の使用方法 SELECT 文が戻す行のセットは、その文に対するアクティブ セット です。単一行 SELECT 文は、1 つの行を戻します。 SELECT 文に WHERE 節を追加して、特定 の行を参照できます。例えば、WHERE 節を使用して行に制限を設定し、特定の顧 第 2 章 SELECT 文の作成 33 客からの注文や、特定の顧客サービス担当者からの問合せが入力された行のみがデ ータベース サーバから戻されるようにします。 WHERE 節を使用して、比較条件 や結合条件 を設定できます。ここでは、比較条 件の設定についてのみ説明します。結合条件については、後述します。 比較条件の作成 SELECT 文の WHERE 節は、表示する行を指定します。比較条件は、特定のキーワ ード および演算子 を使用して、検索条件を定義します。 例えば、キーワード BETWEEN、IN、LIKE、または MATCHES のうち 1 つを使 用して等価性をテストしたり、キーワード IS NULL を使用して NULL 値をテスト することができます。キーワード NOT とこれらのキーワードを組み合わせて、否 定条件を設定することもできます。 次の表に、キーワードの代わりに WHERE 節で使用して等値関係をテストする関係 演算子 のリストを示します。 演算子 演算 = 等しい != または <> 等しくない > より大きい >= より大か等しい < より小さい <= より小か等しい 文字 (CHAR) 型式では、より大きい は ASCII 照合順序において後 であることを 意味し、小文字は大文字の後になり、両者とも数値の後になります。 「IBM Informix: SQL ガイド: 構文」の ASCII 文字セット グラフを参照してくださ い。日付 (DATE) 型および日時 (DATETIME) 型式では、より大きい は時間的に後 であることを意味し、時間隔 (INTERVAL) 型式では、期間が長い ことを意味しま す。 NULL 値をキーワード IS NULL または IS NOT NULL でテストする場合を除 き、テキスト (TEXT) 型またはバイト (BYTE) 型列を使用して比較条件を作成する ことはできません。 Dynamic Server NULL 値をキーワード IS NULL または IS NOT NULL でテストする場合を除 き、バイナリ ラージ オブジェクト (BLOB) 型または文字ラージ オブジェクト (CLOB) 型列を使用して Dynamic Server での比較条件を作成することはできませ ん。 Dynamic Server の終り 前のページに示したキーワードや演算子を WHERE 節に使用すると、次のような動 作をする比較条件付き問合せを作成できます。 34 IBM Informix: SQL ガイド: チュートリアル v 特定の値を検索する v 特定の値を除外する v 特定の範囲の値を検索する v 一部の値を検索する v NULL を検索する 以下に示す基準で変数テキストの検索を実行するには、WHERE 節に先行するキー ワードおよび演算子を使用して比較条件付きの問合せを作成します。 v 文字列を正確に比較する v 単一文字ワイルドカードを使用する v 値の範囲を制限する単一文字ワイルドカードを使用する v 可変長ワイルドカードを使用する v サブスクリプト付け 問合せの型それぞれの例を次に示します。 行のインクルード 図 46 で示されているように、関係演算子等号 (=) を使用して行を WHERE 節にイ ンクルードします。 SELECT customer_num, call_code, call_dtime, res_dtime FROM cust_calls WHERE user_id = ’maryj’ 図 46. 問合せ 図 46 は、図 47 に示す行のセットを戻します。 customer_num 106 121 127 call_code call_dtime res_dtime D O I 1998-06-12 08:20 1998-06-12 08:25 1998-07-10 14:05 1998-07-10 14:06 1998-07-31 14:30 図 47. 問合せ結果 行の除外 関係演算子 != または <> を使用して行を WHERE 節から除外します。 図 48 では、問合せの対象が ANSI 標準準拠データベースであることを前提にして います。文には、表 customer の所有者、すなわち、この表の作成者のログイン名 が指定されています。この修飾子 (所有者名) は、表の作成者が現行ユーザの場合 や、データベースが ANSI 標準準拠でない場合は必要ありません。しかしどちらの 場合でも修飾子をインクルードすることはできます。所有者の命名に関する詳細 は、「IBM Informix: SQL ガイド: 構文」を参照してください。 第 2 章 SELECT 文の作成 35 SELECT customer_num, company, city, state FROM odin.customer WHERE state != ’CA’ SELECT customer_num, company, city, state FROM odin.customer WHERE state <> ’CA’ 図 48. 問合せ 図 49 で示されているように、図 48 の 2 つの SELECT 文では、ユーザ odin が所 有する表 customer で、列 state 内の値と CA は等しくないという指定により値 を除外しています。 customer_num 119 120 121 122 123 124 125 126 127 128 company The Triathletes Club Century Pro Shop City Sports The Sporting Life Bay Sports Putnum’s Putters Total Fitness Sports Neelie’s Discount Sp Big Blue Bike Shop Phoenix College city Cherry Hill Phoenix Wilmington Princeton Jacksonville Bartlesville Brighton Denver Blue Island Phoenix state NJ AZ DE NJ FL OK MA CO NY AZ 図 49. 問合せ結果 行範囲の指定 図 50 に、WHERE 節で行範囲を指定する 2 つの方法を示します。 SELECT catalog_num, stock_num, manu_code, cat_advert FROM catalog WHERE catalog_num BETWEEN 10005 AND 10008 SELECT catalog_num, stock_num, manu_code, cat_advert FROM catalog WHERE catalog_num >= 10005 AND catalog_num <= 10008 図 50. 問合せ 図 50 の各文では、列 catalog_num の値の範囲を 10005 から 10008 までと指定 しています。最初の文ではキーワードを、2 番目の文では関係演算子をそれぞれ使 用して、行の抽出を行います。図 51 に結果を示します。 36 IBM Informix: SQL ガイド: チュートリアル catalog_num 10005 stock_num 3 manu_code HSK cat_advert High-Technology Design Expands the Sweet Spot catalog_num 10006 stock_num 3 manu_code SHM cat_advert Durable Aluminum for High School and Collegiate Athletes catalog_num 10007 stock_num 4 manu_code HSK cat_advert Quality Pigskin with Joe Namath Signature catalog_num 10008 stock_num 4 manu_code HRO cat_advert Highest Quality Football for High School and Collegiate Competitions 図 51. 問合せ結果 表 catalog にはバイト (BYTE) 型の列が含まれていますが、この列を SELECT 文 で指定しても <BYTE value> と列名に表示されるだけなので、指定されていませ ん。 SQL API アプリケーションを記述することで、テキスト (TEXT) 型およびバ イト (BYTE) 型の値を表示できます。 特定範囲の行の除外 図 52 では、キーワード NOT BETWEEN を使用して、列 zipcode に 94000 から 94999 の文字範囲を持つ行を 図 53 のように除外します。 SELECT fname, lname, city, state FROM customer WHERE zipcode NOT BETWEEN ’94000’ AND ’94999’ ORDER BY state 図 52. 問合せ fname lname city state Frank Fred Eileen Jason Marvin James Bob Cathy Kim Chris Lessor Jewell Neelie Wallack Hanlon Henry Shorter O’Brian Satifer Putnum Phoenix Phoenix Denver Wilmington Jacksonville Brighton Cherry Hill Princeton Blue Island Bartlesville AZ AZ CO DE FL MA NJ NJ NY OK 図 53. 問合せ結果 第 2 章 SELECT 文の作成 37 WHERE 節を使用した値のサブセットの検索 35 ページの『行の除外』と同様、図 54 では、ANSI 準拠のデータベースを使用す ることを想定しています。これらの例で所有者名を示す修飾子が引用符で囲まれて いるのは、英大文字と英小文字を区別するためです。 SELECT lname, city, state, phone FROM ’Aleta’.customer WHERE state = ’AZ’ OR state = ’NJ’ ORDER BY lname SELECT lname, city, state, phone FROM ’Aleta’.customer WHERE state IN (’AZ’, ’NJ’) ORDER BY lname 図 54. 問合せ 図 54 の各文は、表 Aleta.customer の列 state に AZ または NJ のサブセットが 含まれる行を抽出します。これを 図 55 に示します。 lname city state phone Jewell Lessor O’Brian Shorter Phoenix Phoenix Princeton Cherry Hill AZ AZ NJ NJ 602-265-8754 602-533-1817 609-342-0054 609-663-6079 図 55. 問合せ結果 キーワード IN を使用して、テキスト (TEXT) 型 列またはバイト (BYTE) 型列を テストすることはできません。 Dynamic Server また、Dynamic Server を使用する場合は、キーワード IN を使用してバイナリ ラ ージ オブジェクト (BLOB) 型または文字ラージ オブジェクト (CLOB) 型列をテス トできません。 Dynamic Server の終り 図 56 に ANSI 標準準拠データベースでの問合せ例を示しますが、ここでは表の所 有者名の前後に引用符がついていません。 図 54 の 2 つの問合せは表 Aleta.customer を検索しましたが、図 56 は表 ALETA.customer (別の表) を検索 します。この 2 つは、ANSI 準拠のデータベースが所有者名を検索する方法が異な ります。 SELECT lname, city, state, phone FROM Aleta.customer WHERE state NOT IN (’AZ’, ’NJ’) ORDER BY state 図 56. 問合せ 38 IBM Informix: SQL ガイド: チュートリアル 図 56 では、キーワード NOT IN を追加することにより、state 列のサブセット AZ および NJ を除外するようにサブセットを変更します。 図 57 に示す結果は、state 列の順序になります。 lname city state phone Pauli Sadler Currie Higgins Vector Watson Ream Quinn Miller Jaeger Keyes Lawson Beatty Albertson Grant Parmelee Sipes Baxter Neelie Wallack Hanlon Henry Satifer Putnum Sunnyvale San Francisco Palo Alto Redwood City Los Altos Mountain View Palo Alto Redwood City Sunnyvale Redwood City Sunnyvale Los Altos Menlo Park Redwood City Menlo Park Mountain View Redwood City Oakland Denver Wilmington Jacksonville Brighton Blue Island Bartlesville CA CA CA CA CA CA CA CA CA CA CA CA CA CA CA CA CA CA CO DE FL MA NY OK 408-789-8075 415-822-1289 415-328-4543 415-368-1100 415-776-3249 415-389-8789 415-356-9876 415-544-8729 408-723-8789 415-743-3611 408-277-7245 415-887-7235 415-356-9982 415-886-6677 415-356-1123 415-534-8822 415-245-4578 415-655-0011 303-936-7731 302-366-7511 904-823-4239 617-232-4159 312-944-5691 918-355-2074 図 57. 問合せ結果 NULL 値の識別 IS NULL または IS NOT NULL オプションを使用して、NULL 値をチェックしま す。 NULL 値とはデータが存在していない状態か、または未知の値のいずれかで す。また、NULL 値はゼロや空白とは異なります。 図 58 は、NULL paid_date を持つ行をすべて戻します。結果は、図 59 に示しま す。 SELECT order_num, customer_num, po_num, ship_date FROM orders WHERE paid_date IS NULL ORDER BY customer_num 図 58. 問合せ 第 2 章 SELECT 文の作成 39 order_num customer_num po_num 1004 1006 1007 1012 1016 1017 106 8006 112 Q13557 117 278693 117 278701 119 PC6782 120 DM354331 ship_date 05/30/1998 06/05/1998 06/29/1998 07/12/1998 07/13/1998 図 59. 問合せ結果 複合条件の作成 論理演算子 AND、OR、および NOT を使用して、複数の比較条件またはブール (BOOLEAN) 式を結合することができます。ブール (BOOLEAN) 式は、 TRUE また は FALSE を評価します。また、NULL 値が含まれている場合は、unknown として評 価します。 図 60 では、演算子 AND は、WHERE 節の 2 つの比較式を結合します。 SELECT order_num, customer_num, po_num, ship_date FROM orders WHERE paid_date IS NULL AND ship_date IS NOT NULL ORDER BY customer_num 図 60. 問合せ この問合せは、図 61 に示すように、NULL paid_date を含み、NULL ship_date を 含まないすべての行を戻します。 order_num customer_num po_num 1004 1007 1012 1017 106 117 117 120 8006 278693 278701 DM354331 ship_date 05/30/1998 06/05/1998 06/29/1998 07/13/1998 図 61. 問合せ結果 正確なテキスト比較の使用 以下の例の WHERE 節では、キーワード LIKE、キーワード MATCHES、または等 号 (=) 関係演算子を使用して、正確なテキスト比較を検索します。これまでの例と 異なり、ここでは現行データベースにない表に対して問合せを行います。現行デー タベースにない表にアクセスできるのは、アクセス対象となるデータベースと現行 データベースとで、ANSI 標準準拠または非準拠の状態が同じである場合のみで す。現行データベースが ANSI 標準準拠データベースの場合は、アクセス対象とな る表は ANSI 標準準拠データベースに存在している必要があります。現行データベ ースが ANSI 標準非準拠データベースの場合は、アクセス対象となる表は ANSI 標 準非準拠データベースに存在している必要があります。 40 IBM Informix: SQL ガイド: チュートリアル この章でこれまで使用してきたデータベースは、デモンストレーション データベー スですが、次の例の FROM 節で指定している所有者 bubba 作成の表 manatee は、syzygy という名前の ANSI 標準準拠のデータベース内にあります。現行デー タベースにない表にアクセスする方法については、「IBM Informix: SQL ガイド: 構 文」を参照してください。 図 62 のすべての文は、図 63 に示すように、列 description に helmet という単一 文字が含まれるすべての行を抽出します。 SELECT stock_no, mfg_code, description, unit_price FROM syzygy:bubba.manatee WHERE description = ’helmet’ ORDER BY mfg_code SELECT stock_no, mfg_code, description, unit_price FROM syzygy:bubba.manatee WHERE description LIKE ’helmet’ ORDER BY mfg_code SELECT stock_no, mfg_code, description, unit_price FROM syzygy:bubba.manatee WHERE description MATCHES ’helmet’ ORDER BY mfg_code 図 62. 問合せ 結果は 図 63 のようになります。 stock_no mfg_code 991 991 991 991 991 ABC BKE HSK PRC SPR description helmet helmet helmet helmet helmet unit_price $222.00 $269.00 $311.00 $234.00 $245.00 図 63. 問合せ結果 変数テキスト検索の使用 フィールドのサブ文字列検索に基づく変数テキスト 問合せに、キーワード LIKE お よび MATCHES を使用することができます。反対の条件を指定するには、キーワー ド NOT をインクルードします。キーワード LIKE は ANSI 標準ですが、 MATCHES は Informix の拡張です。 変数テキスト検索文字列には、LIKE または MATCHES と共に、次の表に示すワイ ルドカードを含めることができます。 第 2 章 SELECT 文の作成 41 キーワード 記号 意味 LIKE % ゼロまたは 1 文字以上と評価する LIKE _ 1 文字と評価する LIKE \ 次の 1 文字を一般文字として扱う MATCHES * ゼロまたは 1 文字以上と評価する MATCHES ? 1 文字と評価する (NULL を除く) MATCHES [ ] 1 文字または値の範囲と評価する MATCHES \ 次の 1 文字を一般文字として扱う LIKE またはキーワード MATCHES を使用して、テキスト (TEXT) 型列またはバイ ト (BYTE) 型列をテストすることはできません。 Dynamic Server また、Dynamic Server を使用する場合は、LIKE またはキーワード MATCHES を 使用してバイナリ ラージ オブジェクト (BLOB) 型または文字ラージ オブジェク ト (CLOB) 型列をテストできません。 Dynamic Server の終り 単一文字ワイルドカードの使用 図 64 の文は、WHERE 節での単一文字ワイルドカードの使用方法を示します。ま た、現行のデータベースに含まれない表への問合せも行っています。表 stock は、 外部のデータベース sloth 内にあります。現行のデモンストレーション データベ ースの外部にない場合、sloth は meerkat というデータベース サーバ上にありま す。 詳しくは、 193 ページの『第 7 章 外部データベースのデータへのアクセスおよび 修正』 および「IBM Informix: SQL ガイド: 構文」を参照してください。 SELECT stock_num, manu_code, description, unit_price FROM sloth@meerkat:stock WHERE manu_code LIKE ’_R_’ AND unit_price >= 100 ORDER BY description, unit_price SELECT stock_num, manu_code, description, unit_price FROM sloth@meerkat:stock WHERE manu_code MATCHES ’?R?’ AND unit_price >= 100 ORDER BY description, unit_price 図 64. 問合せ 図 64 の各文は、図 65 に示すように、manu_code の中央の文字が R である行の みを抽出します。比較 ’_R_’ (LIKE) または ’?R?’ (MATCHES) は、次の項目を左か ら右へ指定します。 v 任意の単一文字 v 文字 R v 任意の単一文字 42 IBM Informix: SQL ガイド: チュートリアル stock_num manu_code description 205 2 1 7 102 114 4 110 110 307 306 308 304 HRO HRO HRO HRO PRC PRC HRO PRC HRO PRC PRC PRC HRO 3 golf balls baseball baseball gloves basketball bicycle brakes bicycle gloves football helmet helmet infant jogger tandem adapter twin jogger watch unit_price $312.00 $126.00 $250.00 $600.00 $480.00 $120.00 $480.00 $236.00 $260.00 $250.00 $160.00 $280.00 $280.00 図 65. 問合せ結果 初めの文字の範囲を指定する WHERE 節: 図 66 は、manu_code が A から H で始まる行のみを選択し、図 67 に示す行のみを戻します。テスト ’[A-H]’ は、A から H の任意の単一文字を指定します。キーワード LIKE と同等なワイルドカード 記号はありません。 SELECT stock_num, manu_code, description, unit_price FROM stock WHERE manu_code MATCHES ’[A-H]*’ ORDER BY description, manu_code 図 66. 問合せ stock_num manu_code description unit_price 205 205 2 3 1 1 7 ANZ HRO HRO HSK HRO HSK HRO 3 golf balls 3 golf balls baseball baseball bat baseball gloves baseball gloves basketball $312.00 $312.00 $126.00 $240.00 $250.00 $800.00 $600.00 313 6 5 8 9 304 ANZ ANZ ANZ ANZ ANZ ANZ swim cap tennis ball tennis racquet volleyball volleyball net watch $60.00 $48.00 $19.80 $840.00 $20.00 $170.00 . . . 図 67. 問合せ結果 可変長ワイルドカードを使用する WHERE 節: 図 68 の SELECT 文は、文字列の 末尾にワイルドカードを使用して、列 description の値が bicycle で始まるすべ ての行を抽出します。 第 2 章 SELECT 文の作成 43 SELECT stock_num, manu_code, description, unit_price FROM stock WHERE description LIKE ’bicycle%’ ORDER BY description, manu_code SELECT stock_num, manu_code, description, unit_price FROM stock WHERE description MATCHES ’bicycle*’ ORDER BY description, manu_code 図 68. 問合せ いずれの文も、図 69 に示す行を戻します。 stock_num manu_code description 102 102 114 107 106 101 101 105 105 PRC SHM PRC PRC PRC PRC SHM PRC SHM bicycle bicycle bicycle bicycle bicycle bicycle bicycle bicycle bicycle brakes brakes gloves saddle stem tires tires wheels wheels unit_price $480.00 $220.00 $120.00 $70.00 $23.00 $88.00 $68.00 $53.00 $80.00 図 69. 問合せ結果 比較 ’bicycle%’ または ’bicycle*’ は、文字 bicycle の後に 0 個以上の文字の任 意のシーケンスが続く文字を指定します。これらは bicycle stem と一致し、stem がワイルドカードと対応しています。列 description にこれに該当する値があれば、 bicycle 単独の場合も一致します。 図 70 は、PRC の manu_code を除外するもう 1 つの比較条件を追加することに よって、さらに検索を絞り込みます。 SELECT stock_num, manu_code, description, unit_price FROM stock WHERE description LIKE ’bicycle%’ AND manu_code NOT LIKE ’PRC’ ORDER BY description, manu_code 図 70. 問合せ この文は、図 71 に示す行のみを抽出します。 stock_num manu_code description 102 SHM 101 SHM 105 SHM bicycle brakes bicycle tires bicycle wheels unit_price $220.00 $68.00 $80.00 図 71. 問合せ結果 %cycle’ のように比較条件の先頭にワイルドカードを使用して大規模な表に対する 問合せを行うと、実行にかなりの時間を要する場合がよくあります。インデックス を使用することができないため、すべての行が検索されます。 44 IBM Informix: SQL ガイド: チュートリアル MATCHES と非デフォルト ロケール (GLS のみ) Informix データベース サーバでは、デフォルトで、データベースのデータに対して 米国英語 (U.S. English) 言語環境が使用されます。このデフォルト ロケールは、 ISO 8859-1 コード セットを使用します。米国英語 (U.S. English) ロケールは、 MATCHES がコード セットの順序を使用することを指定します。 データベースがデフォルトでないロケールを使用する場合、範囲を指定する MATCHES 節は、文字 (CHARACTER) 型 (文字 (CHAR) 型、各国語文字 (NCHAR) 型、可変長文字 (VARCHAR) 型、各国語可変長文字 (NVARCHAR) 型、 およびラージ可変長文字 (LVARCHAR) 型を含む) にそのロケールの照合順序を使 用します。 MATCHES の範囲におけるこの機能は、一般ルールに対する例外であ り、各国語文字 (NCHAR) 型および各国語可変長文字 (NVARCHAR) 型列のみがロ ケールに固有な照合を使用できます。ただし、ロケールが特定の照合順序を指定し ない場合、MATCHES はコード セットの順序を使用します。 Dynamic Server SET COLLATION 文を使用して、セッション用に DB_LOCALE の設定とは異なる データベース ロケールを指定することができます。 SET COLLATION の説明につ いては、「IBM Informix: SQL ガイド: 構文」を参照してください。 Dynamic Server の終り SELECT numéro,nom,prénom FROM abonnés WHERE nom MATCHES ’[E-P]*’ ORDER BY nom 図 72. 問合せ 図 73 では、Étaix、Ötker、および Øverst の行が選択およびリストされていませ ん。これは、ISO 8859-1 コード セット順序では、名前の最初のアクセントの付い た文字は、列 nom の MATCHES の範囲 E から P に含まれていないためです。 numéro nom 13607 13602 13604 13610 13613 13603 13611 Hammer Hämmer LaForêt LeMaître Llanero Montaña Oatfield prénom Gerhard Greta Jean-Noël Héloïse Gloria Dolores José Antonio Emily 図 73. 問合せ結果 英語以外のデータおよびロケールに関する詳細は、「IBM Informix: GLS ユーザー ズ ガイド」を参照してください。 第 2 章 SELECT 文の作成 45 特殊文字のプロテクト 図 74 では、キーワード ESCAPE を、LIKE またはキーワード MATCHES と共に 使用しています。これにより、特殊文字がワイルドカード記号として誤って解釈さ れるのを防ぐことができます。 SELECT * FROM cust_calls WHERE res_descr LIKE ’%!%%’ ESCAPE ’!’ 図 74. 問合せ キーワード ESCAPE は、エスケープ文字 (この例では、!) を指定し、ワイルドカ ードではなくデータとして解釈されるようにように、後続の 1 文字をプロテクトし ます。この例では、エスケープ文字を指定すると、中央のパーセント記号 (%) がデ ータとして処理されます。キーワード ESCAPE を使用すると、ワイルドカード LIKE のパーセント記号 (%) で、列 res_descr 内のパーセント記号 (%) のオカレ ンスを検索することができます。この問合せは、図 75 に示す行を抽出します。 customer_num call_dtime user_id call_code call_descr res_dtime res_descr 116 1997-12-21 11:24 mannyn I Second complaint from this customer! Received two cases righthanded outfielder glove (1 HRO) instead of one case lefties. 1997-12-27 08:19 Memo to shipping (Ava Brown) to send case of lefthanded gloves, pick up wrong case; memo to billing requesting 5% discount to placate customer due to second offense and lateness of resolution because of holiday. 図 75. 問合せ結果 WHERE 節でのサブスクリプトの使用方法 SELECT 文の WHERE 節でサブスクリプト付け をすることにより、列の文字また は数値の範囲を指定することができます。図 76 に例を示します。 SELECT catalog_num, stock_num, manu_code, cat_advert, cat_descr FROM catalog WHERE cat_advert[1,4] = ’High’ 図 76. 問合せ サブスクリプト [1,4] により、図 76 は、列 cat_advert の最初の 4 文字が High であるすべての行を抽出します。この結果を図 77 に示します。 46 IBM Informix: SQL ガイド: チュートリアル catalog_num 10004 stock_num 2 manu_code HRO cat_advert Highest Quality Ball Available, from Hand-Sti tching to the Robinson Signature cat_descr Jackie Robinson signature ball. Highest professional quality, used by National League. catalog_num 10005 stock_num 3 manu_code HSK cat_advert High-Technology Design Expands the Sweet Spot cat_descr Pro-style wood. Available in sizes: 31, 32, 33, 34, 35. . . . catalog_num 10045 stock_num 204 manu_code KAR cat_advert High-Quality Beginning Set of Irons. Appropriate for High School Competitions cat_descr Ideally balanced for optimum control. Nylon covered shaft. catalog_num 10068 stock_num 310 manu_code ANZ cat_advert High-Quality Kickboard cat_descr White. Standard size. 図 77. 問合せ結果 特定の行を選択するためのFIRST節の使用 SELECT 文に FIRST 節をインクルードし、SELECT 文の条件に一致する最初の行 を、指定された数だけ戻すようにすることができます。キーワード FIRST のすぐ後 に数値を入れて、問合せで戻す行の最大数を指定します。 FIRST 節を含む SELECT 文が実行されたときにデータベース サーバが戻す行は、その SELECT 文 に ORDER BY 節も含まれるかどうかにより異なります。 SELECT 文が副問合せまたはビュー定義の一部である場合は、FIRST 節を使用でき ません。 FIRST 節の使用に関する制約事項については、「IBM Informix: SQL ガイド: 構 文」の SELECT 文の説明を参照してください。 ORDER BY 節を使用しない FIRST 節 FIRST 節を含む SELECT 文で ORDER BY 節を使用しない場合、SELECT 文の条 件と一致するすべての行が戻される可能性があります。言い替えると、適合する行 のどれを戻すかをデータベース サーバが決定するため、問合せ結果はオプティマイ ザが選択する問合せ予定により異なります。 図 78 では、FIRST 節を使用して、表 state の最初の 5 行を戻します。 第 2 章 SELECT 文の作成 47 SELECT FIRST 5 * FROM state 図 78. 問合せ code sname AK HI CA OR WA Alaska Hawaii California Oregon Washington 図 79. 問合せ結果 また、FIRST 節を使用して、表内のすべての列名とデータ型を判別できるほか、多 くの行を戻す可能性のある問合せをテストできます。 図 80 では、表の最初の行の 列の値を、FIRST 節を使用して戻します。 SELECT FIRST 1 * FROM orders 図 80. 問合せ order_num order_date customer_num ship_instruct backlog po_num ship_date ship_weight ship_charge paid_date 1001 05/20/1998 104 express n B77836 06/01/1998 20.40 $10.00 07/22/1998 図 81. 問合せ結果 ORDER BY 節を使用する FIRST 節 ORDER BY 節を FIRST 節と共に SELECT 文で使用し、特定の列の最大値および 最小値を含む行を戻すことができます。 図 82 では、ORDER BY 節を使用して (アルファベット順で) 表 state の最初の 5 つの州を戻します。図 82 は、ORDER BY 節を使用している点以外は図 78 と同じですが、図 78 とは異なる結果を戻しま す。 SELECT FIRST 5 * FROM state ORDER BY sname 図 82. 問合せ 48 IBM Informix: SQL ガイド: チュートリアル code sname AL AK AZ AR CA Alabama Alaska Arizona Arkansas California 図 83. 問合せ結果 図 84 では、ORDER BY と共に FIRST 節を使用し、表 stock の最も高価な商品 を 10 個戻します。 SELECT FIRST 10 description, unit_price FROM stock ORDER BY unit_price DESC 図 84. 問合せ description unit_price football volleyball baseball gloves 18-spd, assmbld irons/wedge basketball 12-spd, assmbld 10-spd, assmbld football bicycle brakes $960.00 $840.00 $800.00 $685.90 $670.00 $600.00 $549.00 $499.99 $480.00 $480.00 図 85. 問合せ結果 式と導出値 SELECT 文の SELECT 節には、列名以外の要素も指定できます。 SELECT 文の SELECT 節に式 をリストして列データの計算を行い、1 つ以上の列の内容から導出 した情報を表示できます。 式の基本構成要素は、列名、定数、引用符付き文字列、キーワードです。これらを 演算子で自由に組み合わせて式を構成します。また、SELECT 文をプログラムに埋 め込むと、式にホスト変数 (プログラム データ) を含めることができます。 算術式 算術式には、49 にリストされている算術演算子 が 1 つ以上含まれ、計算結果の数 値が戻されます。 演算子 演算 + 加算 - 減算 * 乗算 第 2 章 SELECT 文の作成 49 除算 / テキスト (TEXT) 型またはバイト (BYTE) 型列を算術式に使用することはできませ ん。 Dynamic Server Dynamic Server では、算術式にバイナリ ラージ オブジェクト (BLOB) 型または文 字ラージ オブジェクト (CLOB) 型を指定できません。 Dynamic Server の終り 算術演算子は、データベース内のデータを実際に変更することなく、指定した計算 の結果を確認することができます。後で参照、計算、または即時レポートの作成を 行うために、変更したデータを一時表に保存するには、INTO TEMP 節を追加しま す。 図 86 は、unit_price が $400 以上の場合、列 unit_price に関して 7% の消 費税を計算します (ただし、データベース内のデータは更新されません)。 SELECT stock_num, description, unit_price, unit_price * 1.07 FROM stock WHERE unit_price >= 400 図 86. 問合せ この結果は、図 87 に示すように、列 expression に表示されます。 stock_num description 1 1 4 4 7 8 102 111 112 113 203 baseball gloves baseball gloves football football basketball volleyball bicycle brakes 10-spd, assmbld 12-spd, assmbld 18-spd, assmbld irons/wedge unit_price (expression) $800.00 $450.00 $960.00 $480.00 $600.00 $840.00 $480.00 $499.99 $549.00 $685.90 $670.00 $856.00 $481.50 $1027.20 $513.60 $642.00 $898.80 $513.60 $534.99 $587.43 $733.91 $716.90 図 87. 問合せ結果 図 88 では、注文量が 5 より少ない場合、$6.50 の追加料金を計算します。 SELECT item_num, order_num, quantity, total_price, total_price + 6.50 FROM items WHERE quantity < 5 図 88. 問合せ この結果は、図 89 に示すように、列 expression に表示されます。 50 IBM Informix: SQL ガイド: チュートリアル item_num . . . order_num quantity total_price (expression) 1 1 2 1 2 1 2 3 4 1001 1002 1002 1003 1003 1004 1004 1004 1004 1 1 1 1 1 1 1 1 1 $250.00 $960.00 $240.00 $20.00 $840.00 $250.00 $126.00 $240.00 $800.00 $256.50 $966.50 $246.50 $26.50 $846.50 $256.50 $132.50 $246.50 $806.50 1 2 3 4 5 6 1023 1023 1023 1023 1023 1023 2 2 1 1 1 1 $40.00 $116.00 $80.00 $228.00 $170.00 $190.00 $46.50 $122.50 $86.50 $234.50 $176.50 $196.50 図 89. 問合せ結果 図 90 は、顧客注文を受けてから (call_dtime) 納入するまでの (res_dtime) 間隔 を、日、時間、および分で計算し、列 expression に表示します。 SELECT customer_num, call_code, call_dtime, res_dtime - call_dtime FROM cust_calls ORDER BY customer_num 図 90. 問合せ customer_num call_code call_dtime 106 110 116 116 119 121 127 D L I I B O I 1998-06-12 1998-07-07 1997-11-28 1997-12-21 1998-07-01 1998-07-10 1998-07-31 (expression) 08:20 10:24 13:34 11:24 15:00 14:05 14:30 0 0 0 5 0 0 00:05 00:06 03:13 20:55 17:21 00:01 図 91. 問合せ結果 表示ラベルの使用: 表示ラベル を計算済みデータまたは導出データの列に設定し て、デフォルトの列見出し expression と置き換えることができます。 図 86、図 88、および図 92 では、導出データが列 expression に表示されます。図 92 で導出 値が表示される列には、taxed という記述ヘッダが付けられます。 SELECT stock_num, description, unit_price, unit_price * 1.07 taxed FROM stock WHERE unit_price >= 400 図 92. 問合せ 第 2 章 SELECT 文の作成 51 図 93 ではラベル taxed が、演算結果 unit_price * 1.07 を表示する選択対象リ ストの式に割り当てられていることを示しています。 stock_num description 1 1 4 4 7 8 102 111 112 113 203 unit_price taxed $800.00 $450.00 $960.00 $480.00 $600.00 $840.00 $480.00 $499.99 $549.00 $685.90 $670.00 $856.00 $481.50 $1027.20 $513.60 $642.00 $898.80 $513.60 $534.99 $587.43 $733.91 $716.90 baseball gloves baseball gloves football football basketball volleyball bicycle brakes 10-spd, assmbld 12-spd, assmbld 18-spd, assmbld irons/wedge 図 93. 問合せ結果 図 94 では、ラベル surcharge を、演算結果 total_price + 6.50 を表示する列に 定義します。 SELECT item_num, order_num, quantity, total_price, total_price + 6.50 surcharge FROM items WHERE quantity < 5 図 94. 問合せ 図 95 で示されているように、出力では、列に surcharge というラベルが割り当て られます。 item_num . . . order_num quantity total_price surcharge 1 1 2 1 2 1001 1002 1002 1003 1003 1 1 1 1 1 $250.00 $960.00 $240.00 $20.00 $840.00 $256.50 $966.50 $246.50 $26.50 $846.50 1 2 3 4 5 6 1023 1023 1023 1023 1023 1023 2 2 1 1 1 1 $40.00 $116.00 $80.00 $228.00 $170.00 $190.00 $46.50 $122.50 $86.50 $234.50 $176.50 $196.50 図 95. 問合せ結果 図 96 では、日時 (DATETIME) 型列 call_dtime を日時 (DATETIME) 型列 res_dtime から減算した結果を表示する列に、ラベル span を割り当てます。 52 IBM Informix: SQL ガイド: チュートリアル SELECT customer_num, call_code, call_dtime, res_dtime - call_dtime span FROM cust_calls ORDER BY customer_num 図 96. 問合せ 図 97 で示されているように、出力では、列に span というラベルが付きます。 customer_num call_code call_dtime 106 110 116 116 119 121 127 D L I I B O I 1998-06-12 1998-07-07 1997-11-28 1997-12-21 1998-07-01 1998-07-10 1998-07-31 span 08:20 10:24 13:34 11:24 15:00 14:05 14:30 0 0 0 5 0 0 00:05 00:06 03:13 20:55 17:21 00:01 図 97. 問合せ結果 CASE 式 CASE 式は、プログラム言語の CASE 文の概念に似た条件式です。データの表示方 法を変える場合に、CASE 式を使用します。 CASE 式により、いくつかの条件テス トのどれが TRUE と評価されるかによって、文はいくつかの可能な結果の 1 つを 戻すことができます。 CASE 式には、テキスト (TEXT) 型またはバイト (BYTE) 型の値を使用できませ ん。 既婚/独身を表す列は数字 1、2、3、および 4 で表示され、それぞれ未婚、既婚、離 別、死別を示します。データベースに効率的に格納するためには短い値 (1,2,3,4) が適していても、人事部のスタッフにとっては、詳しい値 (未婚、既婚、離別、死 別) のほうが便利なことがあります。このような場合、CASE 式を使用して、異な る値のセットを簡単に変換できます。 Dynamic Server また、CASE 式は、拡張 (extended) 型やキャスト式をサポートします。 Dynamic Server の終り 次の例は、複数の WHEN 節を使用する CASE 式です。この式は、表 stock の列 manu_code について、より詳しい値を戻します。 WHEN 条件がいずれも偽の場 合、NULL が結果のデフォルトになります。 (ELSE NULL 節は省略できます。) SELECT CASE WHEN manu_code = "HRO" THEN "Hero" WHEN manu_code = "SHM" THEN "Shimara" WHEN manu_code = "PRC" THEN "ProCycle" 第 2 章 SELECT 文の作成 53 WHEN manu_code = "ANZ" THEN "Anza" ELSE NULL END FROM stock CASE 式には、必ず 1 つ以上の WHEN 節をインクルードします。後続の WHEN 節および ELSE 節はオプションです。WHEN 条件が TRUE と評価しない限り、結 果の値は NULL です。 NULL の結果は、IS NULL 式を使用して処理することが できます。この方法については、「IBM Informix: SQL ガイド: 構文」を参照してく ださい。 図 98 は、表 orders の中でまだ顧客に出荷されていない注文がある場合に、フラ グを立てる文字列値を戻す単純な CASE 式です。 SELECT order_num, order_date, CASE WHEN ship_date IS NULL THEN "order not shipped" END FROM orders 図 98. 問合せ order_num order_date (expression) 1001 1002 1003 1004 1005 1006 1007 05/20/1998 05/21/1998 05/22/1998 05/22/1998 05/24/1998 05/30/1998 order not shipped 05/31/1998 1019 1020 1021 1022 1023 07/11/1998 07/11/1998 07/23/1998 07/24/1998 07/24/1998 . . . 図 99. 問合せ結果 CASE 式を使用して列を更新する方法については、171 ページの『CASE 式による 列の更新』を参照してください。 導出列のソート 図 100 と図 102 で示されているように、式として ORDER BY 節を使用すると、式 に設定した表示ラベルまたは整数を使用することができます。 SELECT customer_num, call_code, call_dtime, res_dtime - call_dtime span FROM cust_calls ORDER BY span 図 100. 問合せ 54 IBM Informix: SQL ガイド: チュートリアル 図 100 は、表 cust_calls から、図 96 と同じデータを抽出します。図 100 では、 ORDER BY 節により、span 列の導出値の昇順にデータが表示されます。 customer_num call_code call_dtime 127 121 106 110 116 119 116 I O D L I B I 1998-07-31 1998-07-10 1998-06-12 1998-07-07 1997-11-28 1998-07-01 1997-12-21 span 14:30 14:05 08:20 10:24 13:34 15:00 11:24 0 0 0 0 0 5 00:01 00:05 00:06 03:13 17:21 20:55 図 101. 問合せ結果 図 102 は、整数を使用して演算 res_dtime - call_dtime の結果を表示し、図 101 に表示されるのと同じ行を抽出します。 SELECT customer_num, call_code, call_dtime, res_dtime - call_dtime span FROM cust_calls ORDER BY 4 図 102. 問合せ SELECT 文での行 ID 値の使用 データベース サーバは、固有行 ID 番号をフラグメント化されていない表に割り当 てます。 rowid は、実際はどの表にも存在する隠れた列です。rowid の連続値には 特に意味はなく、チャンク内の物理データの格納場所によって異なる場合がありま す。行 ID を使用して、表の行に関連付けられた内部レコード番号を検索すること ができます。フラグメント表の行に自動的に列 rowid が含まれることはありませ ん。 アプリケーションでのアクセス方法には、行 ID 番号ではなく主キーを使用するこ とをお勧めします。主キーは ANSI の SQL 仕様で定義されているため、これをデ ータへのアクセスに使用することで、アプリケーションの移植性を高めることがで きます。また、データベース サーバでは、主キーを使用してフラグメント表内のデ ータにアクセスした方が、行 ID 番号を使用して同一データにアクセスするより も、所要時間が短くて済みます。 行 ID の詳細については、「IBM Informix: データベース設計および実装 ガイド」 および「IBM Informix: 管理者ガイド」を参照してください。 図 103 では、SELECT 節で行 ID とワイルドカードのアスタリスク記号 (*) を使用 して、表 manufact の各行をその行 ID とともに抽出します。 SELECT rowid, * FROM manufact 図 103. 問合せ 第 2 章 SELECT 文の作成 55 rowid manu_code manu_name 257 258 259 260 261 262 263 264 265 SMT ANZ NRG HSK HRO SHM KAR NKL PRC Smith Anza Norge Husky Hero Shimara Karsten Nikolus ProCycle lead_time 3 5 7 5 4 30 21 8 9 図 104. 問合せ結果 絶対に行 ID を永続 表に格納したり、外部キーとして使用したりしないでくださ い。表を削除してから外部データから再ロードすると、行 ID の値はすべて変更さ れます。 複数表の SELECT 文 FROM 節に表名を指定して、複数の表からデータを選択することができます。各表 の 1 つ以上の関連する列間の結合 条件を作成するには、WHERE 節を追加しま す。この WHERE 節は一時複合表を作成します。結合条件を満たす行のペアはすべ てリンクされ、単一行を形成しています。 単純結合 では、各表内の 1 つの列の関係に基づいて複数表の情報を結合します。 複合結合 は、各表内の複数列の関係に基づいた複数表の結合です。 結合を作成するには、各表の少なくとも 1 つの列の間で、結合条件 と呼ばれる関 係を指定する必要があります。列は比較の対象となるため、互換 (compatible) 型を 含んでいなければなりません。大きな表を結合する場合は、結合条件で列にインデ ックスを付けると効率的です。 データ型については、「IBM Informix: SQL ガイド: 参照」および「IBM Informix: データベース設計および実装 ガイド」に記載されています。インデックス機能の詳 細については、「IBM Informix: 管理者ガイド」を参照してください。 デカルト積の作成 表の結合条件が明示的に示されていない複数表の問合せを実行する場合は、デカル ト積 を作成します。デカルト積は、表におけるすべての行の組合せからなります。 デカルト積の結果は通常、非常に大きくなります。 図 105 では、2 つの表から選択してデカルト積を作成します。 SELECT * FROM customer, state 図 105. 問合せ 表 state には 52 行、表 customer には 28 行しかありませんが、図 105 を行う と、一方の表の行数と他方の表の行数の乗算が行われ、図 106 のように実用性のな い 1,456 行が抽出されます。 56 IBM Informix: SQL ガイド: チュートリアル customer_num fname lname company address1 address2 city state zipcode phone code sname customer_num fname lname company address1 address2 city state zipcode phone code sname customer_num fname lname company address1 address2 city state zipcode phone code sname . . . 101 Ludwig Pauli All Sports Supplies 213 Erstwild Court Sunnyvale CA 94086 408-789-8075 AK Alaska 101 Ludwig Pauli All Sports Supplies 213 Erstwild Court Sunnyvale CA 94086 408-789-8075 HI Hawaii 101 Ludwig Pauli All Sports Supplies 213 Erstwild Court Sunnyvale CA 94086 408-789-8075 CA California 図 106. 問合せ結果 加えて、連結された行に表示されるデータの一部は、矛盾しています。例えば、表 customer の city と state はカリフォルニア州のアドレスを示しますが、表 state の code と sname は他の州のものである場合があります。 結合の作成 理論的には、結合の最初の段階でデカルト積を作成します。このデカルト積を詳細 化または制限し、意味のない行データの組み合せを除去するには、有効な結合条件 を指定した WHERE 節を SELECT 文に含めます。 このセクションでは、交差結合、等価結合、自然結合、および複数表結合 について 説明します。セルフ結合 や外部結合 などの複雑な結合については、第 5 章に記載 されています。 交差結合 (IDS のみ) 交差結合では、選択されたすべての表のすべての行を結合し、デカルト積を作成し ます。交差結合の結果は非常に大きくなり、管理が困難になる場合があります。 第 2 章 SELECT 文の作成 57 図 107 では、ANSI 結合構文を使用して、交差結合を作成します。 SELECT * FROM customer CROSS JOIN state 図 107. 問合せ 図 107 の結果は、図 105 の結果と同じになります。また、WHERE 節を指定するこ とで、交差結合をフィルターに掛けることも可能です。 デカルト積の詳細については、56 ページの『デカルト積の作成』を参照してくださ い。ANSI 構文の詳細については、124 ページの『ANSI 結合構文』に記載された ANSI 結合構文 を参照してください。 等価結合 等価結合は、等価関係 (列の値が一致しているかどうか) に基づく結合です。この等 価性は、図 108 に示すように、 WHERE 節に比較演算の等号 (=) で示されます。 SELECT * FROM manufact, stock WHERE manufact.manu_code = stock.manu_code 図 108. 問合せ 図 108 では、表 manufact と表 stock を列 manu_code に基づいて結合しま す。この問合せでは、図 109 で示されているように、2 つの列の値が等しい場合、 それらの行のみを抽出します。 58 IBM Informix: SQL ガイド: チュートリアル manu_code manu_name lead_time stock_num manu_code description unit_price unit unit_descr SMT Smith 3 1 SMT baseball gloves $450.00 case 10 gloves/case manu_code manu_name lead_time stock_num manu_code description unit_price unit unit_descr SMT Smith 3 5 SMT tennis racquet $25.00 each each manu_code manu_name lead_time stock_num manu_code description unit_price unit unit_descr SMT Smith 3 6 SMT tennis ball $36.00 case 24 cans/case manu_code manu_name lead_time stock_num manu_code description unit_price unit unit_descr . . . ANZ Anza 5 5 ANZ tennis racquet $19.80 each each 図 109. 問合せ結果 この等結合では、選択対象リストですべての列が要求されたため、図 109 には、表 manufact と stock の両方の列 manu_code が含まれています。 追加の制約がある等価結合として、結合された列の値の等価性に基づく比較条件を もつ等価結合を作成することもできます。このような結合の場合、WHERE 節に指 定される比較条件には、等号 (=) のほかに関係演算子が使用されます。 結合する表の列が同じ名前を持つ場合、図 110 に示すように、列名の前に各表の名 前とピリオド (.) を付加する必要があります。 SELECT order_num, order_date, ship_date, cust_calls.* FROM orders, cust_calls WHERE call_dtime >= ship_date AND cust_calls.customer_num = orders.customer_num ORDER BY orders.customer_num 図 110. 問合せ 第 2 章 SELECT 文の作成 59 図 110 は、列 customer_num を結合し、表 cust_calls の call_dtime が表 orders の ship_date 以上である行のみを選択します。 図 111 に、結合されて戻 される行を示します。 order_num order_date ship_date customer_num call_dtime user_id call_code call_descr res_dtime res_descr 1004 05/22/1998 05/30/1998 106 1998-06-12 08:20 maryj D Order received okay, but two of the cans of ANZ tennis balls within the case were empty 1998-06-12 08:25 Authorized credit for two cans to customer, issued apology. Called ANZ buyer to report the qa problem. order_num order_date ship_date customer_num call_dtime user_id call_code call_descr res_dtime res_descr 1008 06/07/1998 07/06/1998 110 1998-07-07 10:24 richc L Order placed one month ago (6/7) not received. 1998-07-07 10:30 Checked with shipping (Ed Smith). Order out yesterday-was waiting for goods from ANZ. Next time will call with delay if necessary. order_num order_date ship_date customer_num call_dtime user_id call_code call_descr 1023 07/24/1998 07/30/1998 127 1998-07-31 14:30 maryj I Received Hero watches (item # 304) instead of ANZ watches res_dtime res_descr Sent memo to shipping to send ANZ item 304 to customer and pickup HRO watches. Should be done tomorrow, 8/1 図 111. 問合せ結果 自然結合 自然結合は、結合列がデータを重複して表示しないように構成された等価結合の一 種です。図 112 に例を示します。 SELECT manu_name, lead_time, stock.* FROM manufact, stock WHERE manufact.manu_code = stock.manu_code 図 112. 問合せ 60 IBM Informix: SQL ガイド: チュートリアル 図 112 では、表 manufact と表 stock を列 manu_code に基づいて結合しま す。選択対象リストがさらに詳しく定義されているため、図 113 に示すように、抽 出された各行に対して列 manu_code がリストされるのは 1 回のみです。 manu_name lead_time stock_num manu_code description unit_price unit unit_descr Smith 3 1 SMT baseball gloves $450.00 case 10 gloves/case manu_name lead_time stock_num manu_code description unit_price unit unit_descr Smith 3 5 SMT tennis racquet $25.00 each each manu_name lead_time stock_num manu_code description unit_price unit unit_descr Smith 3 6 SMT tennis ball $36.00 case 24 cans/case manu_name lead_time stock_num manu_code description unit_price unit unit_descr . . . Anza 5 5 ANZ tennis racquet $19.80 each each 図 113. 問合せ結果 すべての結合には、結合性 があります。つまり、WHERE 節の結合条件の順序は結 合の意味に影響を与えません。 図 114 の文は同じ自然結合を作成します。 SELECT catalog.*, description, unit_price, unit, unit_descr FROM catalog, stock WHERE catalog.stock_num = stock.stock_num AND catalog.manu_code = stock.manu_code AND catalog_num = 10017 SELECT catalog.*, description, unit_price, unit, unit_descr FROM catalog, stock WHERE catalog_num = 10017 AND catalog.manu_code = stock.manu_code AND catalog.stock_num = stock.stock_num 図 114. 問合せ 第 2 章 SELECT 文の作成 61 いずれの文も 図 115 に示す行を抽出します。 catalog_num 10017 stock_num 101 manu_code PRC cat_descr Reinforced, hand-finished tubular. Polyurethane belted. Effective against punctures. Mixed tread for super wear and road grip. cat_picture <BYTE value> cat_advert Ultimate in Puncture Protection, Tires Designed for In-City Riding description bicycle tires unit_price $88.00 unit box unit_descr 4/box 図 115. 問合せ結果 図 114 には、テキスト (TEXT) 型列 cat_descr、バイト (BYTE) 型列 cat_picture、および可変長文字 (VARCHAR) 型列 cat_advert が含まれます。 複数表結合 複数表の結合では、関連する 1 つ以上の列で複数の表を結合します。この結合は、 等結合または自然結合です。 図 116 では、catalog、stock、および manufact の各表において等結合が作成さ れます。 SELECT * FROM catalog, stock, manufact WHERE catalog.stock_num = stock.stock_num AND stock.manu_code = manufact.manu_code AND catalog_num = 10025 図 116. 問合せ 図 116 は、図 117 に示す行を抽出します。 62 IBM Informix: SQL ガイド: チュートリアル catalog_num 10025 stock_num 106 manu_code PRC cat_descr Hard anodized alloy with pearl finish; 6mm hex bolt hard ware. Available in lengths of 90-140mm in 10mm increments. cat_picture <BYTE value> cat_advert stock_num manu_code description unit_price unit unit_descr manu_code manu_name lead_time ProCycle Stem with Pearl Finish 106 PRC bicycle stem $23.00 each each PRC ProCycle 9 図 117. 問合せ結果 manu_code は 3 回 (1 つの表につき 1 回)、stock_num は 2 回使用されていま す。 図 116 のように複数表の問合せで行が重複しないようにするには、図 118 で示され ているように、選択対象リストに特定の列を含めて SELECT 文をより詳細に定義し ます。 SELECT catalog.*, description, unit_price, unit, unit_descr, manu_name, lead_time FROM catalog, stock, manufact WHERE catalog.stock_num = stock.stock_num AND stock.manu_code = manufact.manu_code AND catalog_num = 10025 図 118. 問合せ 図 118 では、ワイルドカードを使用して、最も多くの列を含む表から列をすべて選 択し、他の 2 つの表の列を指定します。図 119 は、図 118 が作成した自然結合を 示しています。この問合せでは、直前の例と同じ情報を表示していますが、重複し た行は含まれていません。 第 2 章 SELECT 文の作成 63 catalog_num 10025 stock_num 106 manu_code PRC cat_descr Hard anodized alloy with pearl finish. 6mm hex bolt hardware. Available in lengths of 90-140mm in 10mm increments. cat_picture <BYTE value> cat_advert ProCycle Stem with Pearl Finish description bicycle stem unit_price $23.00 unit each unit_descr each manu_name ProCycle lead_time 9 図 119. 問合せ結果 問合せのショートカット 別名、INTO TEMP 節、および表示ラベルを使用すると、結合と複数表への問合せ を高速で処理し、他で使用するための出力を作成することができます。 別名の使用 SELECT 文の FROM 節の表に別名 を割り当てることにより、複数表問合せを短縮 し、読みやすくすることができます。例えば、他の節にある列名のプレフィックス として使用するなど、表名が使用されるところであれば、別名を使用することがで きます。 SELECT s.stock_num, s.manu_code, s.description, s.unit_price, c.catalog_num, c.cat_advert, m.lead_time FROM stock s, catalog c, manufact m WHERE s.stock_num = c.stock_num AND s.manu_code = c.manu_code AND s.manu_code = m.manu_code AND s.manu_code IN (’HRO’, ’HSK’) AND s.stock_num BETWEEN 100 AND 301 ORDER BY catalog_num 図 120. 問合せ 結合性のある SELECT 文では、別名を定義する前に使用することができます。 図 120 では、表 stock の別名 s、表 catalog の別名 c、および表 manufact の別名 m が FROM 節で指定され、列のプレフィックスとして SELECT 節と WHERE 節 で使用されます。 図 120 の長さを、別名を使用していない図 121 の長さと比較してみてください。 64 IBM Informix: SQL ガイド: チュートリアル SELECT stock.stock_num, stock.manu_code, stock.description, stock.unit_price, catalog.catalog_num, catalog.cat_advert, manufact.lead_time FROM stock, catalog, manufact WHERE stock.stock_num = catalog.stock_num AND stock.manu_code = catalog.manu_code AND stock.manu_code = manufact.manu_code AND stock.manu_code IN (’HRO’, ’HSK’) AND stock.stock_num BETWEEN 100 AND 301 ORDER BY catalog_num 図 121. 問合せ 図 120 と図 121 は同義であり、図 122 に示すデータを抽出します。 stock_num 110 manu_code HRO description helmet unit_price $260.00 catalog_num 10033 cat_advert Lightweight Plastic with Vents Assures Cool Comfort Without Sacrificing Protection lead_time 4 stock_num 110 manu_code HSK description helmet unit_price $308.00 catalog_num 10034 cat_advert Teardrop Design Used by Yellow Jerseys; You Can Time the Difference lead_time 5 . . . 図 122. 問合せ結果 テキスト (TEXT) 型列 cat_descr またはバイト (BYTE) 型列 cat_picture に ORDER BY 節を使用することはできません。 また、別名を使用すると、現行のデータベースにない表の問合せを簡単に行うこと ができます。 図 123 では、現在のデータベースまたはシステム以外の別のデータベースおよびシ ステムに常駐する 2 つの表の列を結合します。 SELECT order_num, lname, fname, phone FROM masterdb@central:customer c, sales@western:orders o WHERE c.customer_num = o.customer_num AND order_num <= 1010 図 123. 問合せ 別名 c および o を、ロング database@system:table ネームである masterdb@central:customer と sales@western:orders にそれぞれ割り当てるこ とにより、別名を使用して WHERE 節の式を短縮し、図 124 に示す情報を抽出す ることができます。 第 2 章 SELECT 文の作成 65 order_num lname 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 Higgins Pauli Higgins Watson Parmelee Lawson Sipes Jaeger Keyes Grant fname Anthony Ludwig Anthony George Jean Margaret Arnold Roy Frances Alfred phone 415-368-1100 408-789-8075 415-368-1100 415-389-8789 415-534-8822 415-887-7235 415-245-4578 415-743-3611 408-277-7245 415-356-1123 図 124. 問合せ結果 現行データベースにない表にアクセスする方法については、193 ページの『他のデ ータベース サーバへのアクセス』および「IBM Informix: SQL ガイド: 構文」を参 照してください。 また、現行表と現行ビューのロング名だけでなく現行のデータベースにない表とビ ューのロング名に対するクイック リファレンスとしてシノニム を使用することも できます。シノニムの作成および使用方法の詳細については、「IBM Informix: デー タベース設計および実装 ガイド」を参照してください。 INTO TEMP 節 INTO TEMP 節を SELECT 文に追加すると、データベースを変更せずに、問合せま たは操作できる個別の表へ複数表の問合せ結果を一時的に保存することができま す。 SQL セッションを終了した場合、あるいはプログラムまたはレポートを終了 した場合は一時表が削除されます。 図 125 のように、一時表 stockman を作成して、その表に問合せ結果を格納しま す。一時表では、すべての列に名前を付けなければならないため、別名 adj_price が必要です。 SELECT DISTINCT stock_num, manu_name, description, unit_price, unit_price * 1.05 adj_price FROM stock, manufact WHERE manufact.manu_code = stock.manu_code INTO TEMP stockman; SELECT * from stockman; 図 125. 問合せ 66 IBM Informix: SQL ガイド: チュートリアル stock_num manu_name 1 1 1 2 3 4 4 description Hero Husky Smith Hero Husky Hero Husky baseball baseball baseball baseball baseball football football gloves gloves gloves Shimara ProCycle ProCycle Hero Shimara Anza Shimara Shimara Hero Shimara Anza Shimara tandem adapter infant jogger twin jogger ear drops ear drops kick board kick board water gloves racer goggles racer goggles swim cap swim cap bat unit_price adj_price $250.00 $800.00 $450.00 $126.00 $240.00 $480.00 $960.00 $262.5000 $840.0000 $472.5000 $132.3000 $252.0000 $504.0000 $1008.0000 $190.00 $250.00 $280.00 $40.00 $40.00 $84.00 $80.00 $48.00 $72.00 $96.00 $60.00 $72.00 $199.5000 $262.5000 $294.0000 $42.0000 $42.0000 $88.2000 $84.0000 $50.4000 $75.6000 $100.8000 $63.0000 $75.6000 .. . 306 307 308 309 309 310 310 311 312 312 313 313 図 126. 問合せ結果 これで、この表の問合せを行い、他の表と結合することができます。その結果、複 数ソートが回避され、データベース内をより短時間で移動することができます。一 時表の詳細については、「IBM Informix: SQL ガイド: 構文」および「IBM Informix: 管理者ガイド」を参照してください。 サマリ この章では、リレーショナル データベースへの問合せで使用する基本的な種類の SELECT 文の構文例とその出力結果を紹介しました。 22 ページの『単一表 SELECT 文』には、以下のアクションを実行する方法について記載しています。 v SELECT 節および FROM 節を使用して表内の列および行を選択する。 v SELECT 節、FROM 節、および WHERE 節を使用して表内の行を選択する。 v SELECT 節にキーワード DISTINCT または UNIQUE を使用して、問合せ結果か ら重複行を除去する。 v ORDER BY 節およびキーワード DESC を使用して、抽出したデータをソートす る。 v 英語以外の文字を含むデータの選択と順序づけを行う。 v WHERE 節に キーワード BETWEEN、IN、MATCHES、LIKE、およびさまざま な関係演算子を使用して、比較条件を作成する。 v 値を含む、値を除外する、値の範囲を (キーワード、関係演算子、サブスクリプ ト付けで) 検索する、値のサブセットを検索するなどの比較条件を作成する。 v テキストの比較照合、可変長のワイルドカード、および制限付きと制限なしのワ イルドカードを使用して、変数テキストの検索を実行する。 v 論理演算子 AND、OR、および NOT を使用して、WHERE 節の検索条件または ブー ル (BOOLEAN) 式を結合する。 v ESCAPE キーワードを使用して、問合せの特殊文字をプロテクトする。 v WHERE 節にキーワード IS NULL や IS NOT NULL を指定して、NULL 値を 検索する。 第 2 章 SELECT 文の作成 67 v FIRST 節を使用して、問合せが SELECT 文の条件に一致する行を指定した数の み戻すように指定する。 v SELECT 節の算術演算子を使用して、数値フィールドの計算を実行し、抽出した データを表示する。 v サブ文字列とサブスクリプトで、ユーザの問合せを調整する。 v レポート用のフォーマット手段として、表示ラベルを計算済みの列に設定する。 この章では、複数の表のデータを選択して表示できる簡単な結合条件の概要につい ても説明しました。 56 ページの『複数表の SELECT 文』には、以下のアクション を実行する方法について記載しています。 v デカルト積を作成する。 v デカルト積を作成する交差結合を作成する。 v 有効な結合条件を指定した WHERE 節をユーザの問合せに含めて、デカルト積に 制約条件を設定する。 v 自然結合と等結合を定義して作成する。 v 1 つ以上の列で複数の表を結合する。 v 表階層にある表から行を選択する。 v 複数表の問合せで短縮形として別名を使用する。 v 選択したデータを INTO TEMP 節で個別の一時表内に抽出し、データベースの外 部で計算を行う。 68 IBM Informix: SQL ガイド: チュートリアル 第 3 章 複合 (Complex) 型データの選択 行 (ROW) 型データの選択 . . . . . . . . . . . . . . . . . . 型付き表の列の選択 . . . . . . . . . . . . . . . . . . . 行 (ROW) 型データが格納されている列の選択 . . . . . . . . . . フィールド射影 . . . . . . . . . . . . . . . . . . . . フィールド射影を使用した、入れ子になったフィールドの選択 . . . . 行 (ROW) 型の個々のフィールドの選択 . . . . . . . . . . . アスタリスク表記による行 (ROW) 型のすべてのフィールドへのアクセス コレクション (COLLECTION) 型の選択 . . . . . . . . . . . . . . 入れ子コレクション (COLLECTION) 型の選択 . . . . . . . . . . キーワード IN でコレクション (COLLECTION) 型データ内の要素を検索 . 表階層にある行の選択 . . . . . . . . . . . . . . . . . . . . キーワード ONLY を使用しない上位表の行の選択 . . . . . . . . . キーワード ONLY を使用した上位表の行の選択 . . . . . . . . . . 上位表に別名を使用 . . . . . . . . . . . . . . . . . . . サマリ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 71 72 73 73 74 74 75 76 77 78 80 80 81 81 本章について (IDS のみ) この章では、複合 (Complex) 型 に対する問合せを行う方法について説明します。複 合 (Complex) 型は、SQL 型のコンストラクタと他のデータ型の組合せで構成されま す。 SQL 文で、複合 (Complex) 型内の個々のコンポーネントにアクセスできま す。複合 (Complex) 型は、行 (ROW) 型 またはコレクション (COLLECTION) 型 のいずれかです。 行 (ROW) 型。この型は、関連する 1 つ以上のデータフィールドを結合するインス タンスを持ちます。この行 (ROW) 型には、名前付き 行 (ROW) 型と名前なし 行 (ROW) 型の 2 種類があります。 コレクション (COLLECTION) 型。この型のインスタンスにおける各コレクション (COLLECTION) 型値には、基本データ型または複合 (Complex) 型のどちらか同じ型 を持つ要素のグループが含まれています。コレクションは、リスト (LIST) 型、セッ ト (SET) 型、またはマルチセット (MULTISET) 型で構成できます。 データベース サーバがサポートするデータ型の詳細説明については、 「IBM Informix: SQL ガイド: 参照」のデータ型に関する章を参照してください。 複合 (Complex) 型の作成および使用方法については、「IBM Informix: データベー ス設計および実装 ガイド」、「IBM Informix: SQL ガイド: 参照」、および 「IBM Informix: SQL ガイド: 構文」を参照してください。 行 (ROW) 型データの選択 ここでは、行 (ROW) 型データとして定義されたデータの問合せ方法について説明 します。行 (ROW) 型データは、1 つ以上の関連データ フィールドが結合されてい る複合 (Complex) 型データです。 行 (ROW) 型には、次の 2 種類があります。 © Copyright IBM Corp. 1996, 2003 69 v 名前付き行 (named row) 型。名前付き行 (named row) 型では、表、列、他の行 (ROW) 型列のフィールド、プログラム変数、文の局所変数、およびルーチンの戻 り値を定義できます。 v 名前なし行 (unnamed row) 型。名前なし行 (unnamed row) 型では、列、他の 行 (ROW) 型列のフィールド、プログラム変数、文の局所変数、ルーチンの戻り 値、および定数を定義できます。 このセクションに記載するは、表 employee を定義する名前付き行 (named row) 型zip_t、address_t、および employee_t を使用します。 図 127 に、行 (ROW) 型および表を作成する SQL 構文を示します。 CREATE ROW TYPE zip_t ( z_code CHAR(5), z_suffix CHAR(4) ) CREATE ROW TYPE address_t ( street VARCHAR(20), city VARCHAR(20), state CHAR(2), zip zip_t ) CREATE ROW TYPE employee_t ( name VARCHAR(30), address address_t, salary INTEGER ) CREATE TABLE employee OF TYPE employee_t 図 127. 名前付き行 (named row) 型の zip_t、address_t、および employee_t は、型付き 表 employee のフィールドと列に対するテンプレートの役割も果たします。型付き 表 とは、名前付き行 (named row) 型で定義される表のことです。表 employee の テンプレートとなっている型 employee_t では、フィールド address のデータ型 として型 address_t が使用されています。型 address_t では、フィールド zip のデータ型として型 zip_t が使用されています。 71 ページの図 128 に、表 student を作成する SQL 構文を示します。表 student の列 s_address は、名前なし行 (unnamed row) 型で定義されています。ただし、 列 s_address は、名前付き行 (named row) 型として定義された可能性もありま す。 70 IBM Informix: SQL ガイド: チュートリアル CREATE TABLE student ( s_name VARCHAR(30), s_address ROW(street VARCHAR (20), city VARCHAR(20), state CHAR(2), zip VARCHAR(9)), grade_point_avg DECIMAL(3,2) ) 図 128. 型付き表の列の選択 型付き表での問合せには、他の表での問合せと特に異なる点はありません。例え ば、図 129 では、アスタリスク記号 (*) を使用して、表 employee のすべての列 を戻す暗黙的な SELECT 文を作成しています。 SELECT * FROM employee 図 129. 問合せ 表 employee に対する暗黙的な SELECT 文は、図 130 に示すように、すべての列 のすべての行を戻します。 name address salary Paul, J. ROW(102 Ruby, Belmont, CA, 49932, 1000) 78000 name address salary . . . Davis, J. ROW(133 First, San Jose, CA, 85744, 4900) 75000 図 130. 問合せ結果 図 131 に、表 employee の列 name および列 address に含まれる行を戻す問合 せを示します。 SELECT name, address FROM employee 図 131. 問合せ name address Paul, J. ROW(102 Ruby, Belmont, CA, 49932, 1000) name address . . . Davis, J. ROW(133 First, San Jose, CA, 85744, 4900) 図 132. 問合せ結果 第 3 章 複合 (Complex) 型データの選択 71 行 (ROW) 型データが格納されている列の選択 行 (ROW) 型列 とは、名前付き行 (named row) 型または名前なし行 (unnamed row) 型で定義される列のことです。名前付き行 (named row) 型と名前なし行 (unnamed row) 型に対する問合せには、同じ SQL 構文を使用します。 行 (ROW) 型列に対する問合せでは、行 (ROW) 型のすべてのフィールドにあるデ ータが戻されます。フィールド は、行 (ROW) 型内のコンポーネント データ型で す。例えば、表 employee の列 address には、street、city、state、および zip というフィールドが含まれています。 図 133 に、列 address のすべてのフィール ドを戻す問合せを構成する方法を示します。 SELECT address FROM employee 図 133. 問合せ address address address . . . ROW(102 Ruby, Belmont, CA, 49932, 1000) ROW(133 First, San Jose, CA, 85744, 4900) ROW(152 Topaz, Willits, CA, 69445, 1000)) 図 134. 問合せ結果 1 つの列に含まれる個々のフィールドにアクセスするには、単一ピリオド表記を使 用して、列の個々のフィールドを射影します。例えば、表 employee の列 address にある特定のフィールドにアクセスすると仮定します。その場合には、次 の SELECT 文を実行して、列 address にあるフィールド city とフィールド state を射影します。 SELECT address.city, address.state FROM employee 図 135. 問合せ city state Belmont San Jose Willits . . . CA CA CA 図 136. 問合せ結果 名前なし行 (unnamed row) 型列に対する問合せも、名前付き行 (named row) 型列へ の問合せと同じ方法で作成します。例えば、図 128 に示す表 student の列 s_address にあるデータにアクセスすると仮定します。名前なし行 (unnamed row) 型で定義された列の個々のフィールドに対して問合せを行うには、ピリオド表記 を 使用します。 図 137 に、表 student に関して列 s_address の city および state フィールドに関する行を戻す SELECT 文を示します。 72 IBM Informix: SQL ガイド: チュートリアル SELECT s_address.city, s_address.state FROM student 図 137. 問合せ city state Belmont Mount Prospect Greeley . . . CA IL CO 図 138. 問合せ結果 フィールド射影 フィールドと列を混同しないようにしてください。列は表に関連付けられており、 列の射影には name_1.name_2 というフォーム (それぞれ表と列を示す) の標準的な ピリオド表記が使用されます。フィールド は、行 (ROW) 型内のコンポーネント データ型です。行 (ROW) 型では、単一の列に行 (ROW) 型を割り当てる機能を使 用し、name_a.name_b.name_c.name_d という単一ピリオド表記を使用することで、 列の個々のフィールドを射影できます。Informix データベース サーバでは、ピリオ ド表記は次の優先順位に従って解釈されます。 1. 表 name_a . 列 name_b . フィールド name_c . フィールド name_d 2. 列 name_a . フィールド name_b . フィールド name_c . フィールド name_d ある識別子の意味があいまいな場合、データベース サーバでは、上記の優先順位の ルールにより、その識別子で指定するデータベース オブジェクトがどれであるかが 決定されます。次の 2 つの文を検討してみてください。 CREATE TABLE b (c ROW(d INTEGER, e CHAR(2))) CREATE TABLE c (d INTEGER) 次の SELECT 文では、表の識別子の方が列の識別子より優先順位が高いため、式 c.d は、表 c の列 d を参照します。表 b にある列 c のフィールド d を参照す るのではありません。 SELECT * FROM b,c WHERE c.d = 10 間違ったデータベース オブジェクトを参照するのを防ぐには、完全な表記で指定し て、フィールドを射影します。例えば、表 c の列 d ではなく、表 b にある列 c のフィールド d を参照する必要があると仮定します。次の文では、参照するオブジ ェクトの表、列、およびフィールドの識別子を指定しています。 SELECT * FROM b,c WHERE b.c.d = 10 重要: 優先順位規則により、データベース サーバでフィールド投影が誤って解釈さ れる危険性は減少しますが、表、列、フィールドの識別子にはすべて一意の 名前を使用することをお勧めします。 フィールド射影を使用した、入れ子になったフィールドの選択 通常、行 (ROW) 型は 1 つの列ですが、任意の行 (ROW) 型式を使用してフィール ドを射影することができます。行 (ROW) 型式が他の行 (ROW) 型を含む場合、そ 第 3 章 複合 (Complex) 型データの選択 73 の式には入れ子になったフィールド が含まれます。式内の入れ子になったフィール ドや個々のフィールドにアクセスするには、ピリオド表記を使用します。行 (ROW) 型のすべてのフィールドにアクセスするには、アスタリスク (*) を使用します。こ こでは、両方の行 (ROW) 型へのアクセス方法について説明します。 行 (ROW) 型式でピリオド表記やアスタリスク表記を使用する方法については、 「IBM Informix: SQL ガイド: 構文」の式セグメントを参照してください。 行 (ROW) 型の個々のフィールドの選択: 表 employee の列 address について 考えてみましょう。この中には、street、city、state、および zip というフィール ドが含まれています。また、フィールド zip には、z_code と z_suffix という入 れ子になったフィールドが含まれています。 70 ページの図 127の行 (ROW) 型と表 の定義を再確認してください。フィールド zip で問合せを行うと、フィールド z_code とフィールド z_suffix の行が戻されます。ただし、特定の入れ子になった フィールドのみを戻すように指定することも可能です。 図 139 に、ピリオド表記を 使用して、列 address の z_code フィールドの行のみを戻す SELECT 文の構成 方法を示します。 SELECT address.zip.z_code FROM employee 図 139. 問合せ z_code 39444 6500 76055 19004 . . . 図 140. 問合せ結果 アスタリスク表記による行 (ROW) 型のすべてのフィールドへのアク セス アスタリスク表記は、SELECT 文の選択対象リスト内でのみサポートされます。選 択リストで行 (ROW) 型列に列名を指定すると、データベース サーバはその列にあ るフィールドすべての値を戻します。行 (ROW) 型にあるフィールドすべてを射影 する場合にも、アスタリスク表記を使用することができます。 図 141 では、アスタリスク表記が使用され、表 employee の列 address にあるす べてのフィールドが戻されています。 SELECT address.* FROM employee 図 141. 問合せ 74 IBM Informix: SQL ガイド: チュートリアル address address address . . . ROW(102 Ruby, Belmont, CA, 49932, 1000) ROW(133 First, San Jose, CA, 85744, 4900) ROW(152 Topaz, Willits, CA, 69445, 1000)) 図 142. 問合せ結果 SQL タスクの中には、アスタリスク表記を使用すると簡単に実行できるようになる ものがあります。行 (ROW) 型の値を戻す関数 new_row() を作成し、この関数を 呼び出して、戻された行を表に挿入すると仮定します。こういった操作を簡単に処 理する方法は、データベース サーバでは提供されていません。しかし、図 143 で は、アスタリスク表記を使用して、new_row() のフィールドすべてを戻し、その戻 されたフィールドを表 tab_2 に挿入しています。 INSERT INTO tab_2 SELECT new_row(exp).* FROM tab_1 図 143. 問合せ INSERT 文の使用方法については、 151 ページの『第 6 章 データの変更』を参照 してください。 重要: .* 表記を使用する式が評価されるのは 1 回のみです。 コレクション (COLLECTION) 型の選択 ここでは、コレクション (COLLECTION) 型で定義されている列への問合せ方法を 説明します。コレクション (COLLECTION) 型とは、コレクション (COLLECTION) 型のどの値にも、同じデータ型の要素のグループが格納されている複合 (Complex) 型のことです。コレクション (COLLECTION) 型の詳細については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。コレ クション (COLLECTION) 型に格納されている個々の要素へアクセスする方法につ いては、138 ページの『SELECT 文でのコレクションの処理 (IDS のみ)』を参照し てください。 ここでは、図 144 に示す表 manager を例として使用します。表 manager には、 単純コレクション (COLLECTION) 型と、入れ子コレクション (COLLECTION) 型 が含まれています。単純コレクション (COLLECTION) 型 とは、それ自体がコレク ション (COLLECTION) 型であるフィールドを 1 つも含まないコレクション (COLLECTION) 型のことです。この例では、表 manager の列 direct_reports が 単純コレクション (COLLECTION) 型です。入れ子コレクション (COLLECTION) 型 は、他のコレクション (COLLECTION) 型を含むコレクション (COLLECTION) 型 です。この例では、表 manager の列 projects が入れ子コレクション (COLLECTION) 型です。 第 3 章 複合 (Complex) 型データの選択 75 CREATE TABLE manager ( mgr_name VARCHAR(30), department VARCHAR(12), direct_reports SET(VARCHAR(30) NOT NULL), projects LIST(ROW(pro_name VARCHAR(15), pro_members SET(VARCHAR(20) NOT NULL) ) NOT NULL) ) 図 144. コレクション (COLLECTION) 型の列への問合せを実行すると、表の行ごとに、特 定のコレクション (COLLECTION) 型が含む要素がすべて戻されます。例えば、列 department にあるデータおよび列 direct_reports にある要素すべてが表 manager の行ごとに戻される問合せを、図 145 に示します。 SELECT department, direct_reports FROM manager 図 145. 問合せ department marketing direct_reports SET {Smith, Waters, Adams, Davis, Kurasawa} department engineering ddirect_reports SET {Joshi, Davis, Smith, Waters, Fosmire, Evans, Jones} department publications direct_reports SET {Walker, Fremont, Porat, Johnson} department accounting direct_reports SET {Baker, Freeman, Jacobs} .. . 図 146. 問合せ結果 コレクション (COLLECTION) 型に対する問合せの出力には必ず、そのコレクショ ンが セット (SET) 型、マルチセット (MULTISET) 型、およびリスト (LIST) 型の いずれであるかを示すコンストラクタが含まれます。例えば、図 146 では、各コレ クションの要素よりも SET コンストラクタが優先されます。コレクション (COLLECTION) 型の要素は中括弧 ({}) で囲まれ、コレクション (COLLECTION) 型の各要素はカンマで区切られています。 入れ子コレクション (COLLECTION) 型の選択 76 ページの図 144では、表 manager の列 projects が入れ子コレクション (COLLECTION) 型です。入れ子コレクション (COLLECTION) 型へ問い合わせる と、特定のコレクション (COLLECTION) 型データがもつすべての要素が戻されま す。 図 147 は、指定した行に対して列 projects にある要素がすべて戻される問合 せです。この例では、列 mgr_name に格納されている値が Sayles である単一の 行へ問い合わせるように、WHERE 節を使って制限を設けています。 76 IBM Informix: SQL ガイド: チュートリアル SELECT projects FROM manager WHERE mgr_name = ’Sayles’ 図 147. 問合せ 図 148 は、表 manager の単一行に対する列 project のコレクション (COLLECTION) 型データの表示結果です。この問合せでは、Sayles というマネー ジャが管理しているプロジェクトの名前が戻されます。このコレクション (COLLECTION) 型データには、リスト (LIST) 型の各要素に対して、プロジェクト 名 (pro_name)、およびセット (SET) 型になっている各プロジェクトを担当するメ ンバ (pro_members) が格納されています。 projects LIST {ROW(voyager_project, SET{Simonian, Waters, Adams, Davis})} projects LIST {ROW(horizon_project, SET{Freeman, Jacobs, Walker, Cannan})} projects LIST {ROW(sapphire_project, SET{Villers, Reeves, Doyle, Strongin})} .. . 図 148. 問合せ結果 キーワード IN でコレクション (COLLECTION) 型データ内の要素 を検索 SQL 文の WHERE 節にキーワード IN を使用し、コレクションが特定の要素を含 んでいるか判別できます。例えば、図 149 に、列 direct_reports のコレクション (COLLECTION) 型データに Adams という要素が格納されている mgr_name と department の値を戻す問合せを示します。 SELECT mgr_name, department FROM manager WHERE ’Adams’ IN direct_reports 図 149. 問合せ mgr_name department Sayles marketing 図 150. 問合せ結果 WHERE 節でキーワード IN を指定して単純コレクション (COLLECTION) 型デー タに格納されている特定の要素を検索することができますが、この問合せではすべ てのコレクション (COLLECTION) 型データが必ず戻されます。例えば、図 151 で は、列 direct_reports のコレクション (COLLECTION) 型の要素が Adams である コレクション型の要素すべてが戻されています。 第 3 章 複合 (Complex) 型データの選択 77 SELECT mgr_name, direct_reports FROM manager WHERE ’Adams’ IN direct_reports 図 151. 問合せ mgr_name direct_reports Sayles SET {Smith, Waters, Adams, Davis, Kurasawa} 図 152. 問合せ結果 図 152 に示すように、コレクション (COLLECTION) 型列への問合せでは、コレク ション (COLLECTION) 型データに含まれている特定の要素ではなく、コレクショ ン (COLLECTION) 型データ全体が戻されます。 WHERE 節にキーワード IN を使用し、単純コレクションのみ参照できます。コレ クション (COLLECTION) 型のフィールドを含むコレクション (COLLECTION) 型 を参照する場合には、キーワード IN は使用できません。例えば、表 manager の 列 projects は入れ子コレクション (COLLECTION) 型のため、キーワード IN を 指定してこの列 projects を参照することはできません。 SELECT 文の WHERE 節でキーワード NOT と IN を結合させ、特定の要素を含 まないコレクションを検索できます。例えば、図 153 に、列 direct_reports のコ レクションに Adams という要素が格納されていない mgr_name と department の値を戻す問合せを示します。 SELECT mgr_name, department FROM manager WHERE ’Adams’ NOT IN direct_reports 図 153. 問合せ mgr_name department Williams engineering mgr_name department Lyman publications mgr_name department Cole accounting 図 154. 問合せ結果 コレクション (COLLECTION) 型列の要素数のカウント方法については、96 ページ の『計数関数 (IDS のみ)』を参照してください。 表階層にある行の選択 ここでは、表階層内の表に含まれている行へ問合せを行う方法について説明しま す。表階層の作成および使用方法の詳細については、「IBM Informix: データベース 設計および実装 ガイド」を参照してください。 78 IBM Informix: SQL ガイド: チュートリアル このセクションで例として使用している型と表の階層を作成する文を、図 155 に示 します。 CREATE ROW ( street city state zip ) TYPE address_t CREATE ROW ( name address soc_sec ) TYPE person_t VARCHAR (20), VARCHAR(20), CHAR(2), VARCHAR(9) VARCHAR(30), address_t, CHAR(9) CREATE ROW TYPE employee_t ( salary INTEGER ) UNDER person_t CREATE ROW TYPE sales_rep_t ( rep_num SERIAL8, region_num INTEGER ) UNDER employee_t CREATE TABLE person OF TYPE person_t CREATE TABLE employee OF TYPE employee_t UNDER person CREATE TABLE sales_rep OF TYPE sales_rep_t UNDER employee 図 155. 図 156 に、図 155 内の行 (ROW) 型と表の階層関係を示します。 図 156. 型と表の階層 第 3 章 複合 (Complex) 型データの選択 79 キーワード ONLY を使用しない上位表の行の選択 表階層を使用することで、1 つの SQL 文で、問合せ範囲を上位表とその副表とす る問合せを作成することができます。上位表に対する問合せでは、上位表とその副 表の両方から行が戻されます。 図 157 に、表階層の最上位表である表 person に 対する問合せを示します。 SELECT * FROM person 図 157. 問合せ 図 35 では、上位表に格納されている列すべてと、その上位表から継承を行う副表 (employee と sales_rep) の列が戻されます。ただし、上位表に対する問合せは、 上位表にない副表の列を戻しません。 図 158 では、表 person、employee、およ び sales_rep 内の列 name、address、および soc_sec を戻します。 name address soc_sec Rogers, J. ROW(102 Ruby Ave, Belmont, CA, 69055) 454849344 name address soc_sec . . . Sallie, A. ROW(134 Rose St, San Carlos, CA, 69025) 348441214 図 158. 問合せ結果 キーワード ONLY を使用した上位表の行の選択 上位表に対する SELECT 文では上位表とその副表の両方から行が戻されますが、上 位表から選択された行と副表から選択された行を見分けることはできません。上位 表の行のみを出力するように問合せ結果を制限するには、SELECT 文にキーワード ONLY を追加する必要があります。例えば、図 159 は、表 person のみの行を戻 します。 SELECT * FROM ONLY(person) 図 159. 問合せ name address soc_sec . . . Rogers, J. ROW(102 Ruby Ave, Belmont, CA, 69055) 454849344 図 160. 問合せ結果 80 IBM Informix: SQL ガイド: チュートリアル 上位表に別名を使用 別名 は、FROM 節で表名の直後に指定されます。 SELECT 文や UPDATE 文で型 付き表に別名を指定し、その別名そのものを式として使用することができます。上 位表の別名を作成すると、その上位表、またはその上位表から継承を行う副表にあ る値をその別名で表すことができます。 DB–Access では、図 161 は表 person、 employee、および sales_rep のすべてのインスタンスの行の値を戻します。 SELECT p FROM person p 図 161. 問合せ ESQL/C では、この構成を認識しません。ESQL/C プログラムでは、図 161 でエラ ーが戻されます。 サマリ この章では、リレーショナル データベースへの問合せにおいて、SELECT 文を使用 して複合 (Complex) 型のデータを選択する場合の構文例とその実行結果を紹介しま した。 69 ページの『行 (ROW) 型データの選択』には、以下のアクションを実行 する方法について記載しています。 v 型付き表および列からの行 (ROW) 型データの選択 v 行 (ROW) 型式を使用した、フィールドの射影 75 ページの『コレクション (COLLECTION) 型の選択』には、以下のアクションを 実行する方法について記載しています。 v コレクション (COLLECTION) 型で定義された列への問合せ v コレクション (COLLECTION) 型データ内の要素の検索 v コレクション (COLLECTION) 型で定義された列への問合せ 78 ページの『表階層にある行の選択』には、以下のアクションを実行する方法につ いて記載しています。 v 上位表に対するキーワード ONLY を使用または使用しない問合せ v 上位表に対する別名の指定 第 3 章 複合 (Complex) 型データの選択 81 82 IBM Informix: SQL ガイド: チュートリアル 第 4 章 SELECT 文での関数の使用 SELECT 文での関数の使用 . . . . . . . . . . 集計関数 . . . . . . . . . . . . . . . COUNT 関数の使用 . . . . . . . . . . AVG 関数の使用 . . . . . . . . . . . MAX 関数と MIN 関数の使用 . . . . . . . SUM 関数の使用 . . . . . . . . . . . RANGE 関数の使用 . . . . . . . . . . STDEV 関数の使用 . . . . . . . . . . . VARIANCE 関数の使用 . . . . . . . . . 式への関数の適用 . . . . . . . . . . . 時刻関数 . . . . . . . . . . . . . . . DAY 関数と CURRENT 関数の使用 . . . . . MONTH 関数の使用 . . . . . . . . . . WEEKDAY 関数の使用 . . . . . . . . . YEAR 関数の使用 . . . . . . . . . . . 日時 (DATETIME) 型値の形式 . . . . . . . 日付変換関数 (IDS のみ) . . . . . . . . . . DATE 関数の使用 . . . . . . . . . . . TO_CHAR 関数の使用 . . . . . . . . . . TO_DATE 関数の使用 . . . . . . . . . . 計数関数 (IDS のみ) . . . . . . . . . . . スマート ラージ オブジェクト関数 (IDS のみ) . . 文字列操作関数 (IDS のみ) . . . . . . . . . LOWER 関数の使用 . . . . . . . . . . UPPER 関数の使用 . . . . . . . . . . . INITCAP 関数の使用 . . . . . . . . . . REPLACE 関数の使用 . . . . . . . . . SUBSTRING 関数と SUBSTR 関数の使用 . . . SUBSTRING 関数の使用. . . . . . . . . SUBSTR 関数の使用 . . . . . . . . . . LPAD 関数の使用 . . . . . . . . . . . RPAD 関数の使用 . . . . . . . . . . . その他の関数 . . . . . . . . . . . . . LENGTH 関数の使用 . . . . . . . . . . USER 関数の使用 . . . . . . . . . . . TODAY 関数の使用 . . . . . . . . . . DBSERVERNAME 関数と SITENAME 関数の使用 HEX 関数の使用 . . . . . . . . . . . DBINFO 関数の使用 . . . . . . . . . . DECODE 関数の使用 . . . . . . . . . . NVL 関数の使用 (IDS のみ) . . . . . . . SELECT 文での SPL ルーチンの使用 . . . . . . サマリ. . . . . . . . . . . . . . . . . © Copyright IBM Corp. 1996, 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 . 84 . 85 . 86 . 86 . 87 . 87 . 88 . 88 . 89 . 89 . 89 . 91 . 91 . 92 . 93 . 93 . 93 . 94 . 95 . 96 . 97 . 98 . 99 . 99 . 100 . 100 . 101 . 101 . 102 . 103 . 104 . 104 . 105 . 105 . 106 . 107 . 107 . 108 . 108 . 110 . 110 . 112 83 本章について 列名と演算子と同様に、式には、1 つ以上の関数を含むことができます。この章で は、SELECT 文の中で関数を使用して、さらに複雑なデータベースへの問合せとデ ータ操作を実行する方法を説明します。この章では、集計関数、時刻関数、日付変 換関数、計数関数、スマート ラージ オブジェクト関数、文字列操作関数などの関 数について説明します。 以下の SQL 関数およびその他の SQL 関数については、「IBM Informix: SQL ガイ ド: 構文」の式セグメントを参照してください。 ヒント: ユーザ独自の関数を使用することもできます。ユーザ定義の関数について は、259 ページの『第 11 章 SPL ルーチンの作成と使用』および 「IBM Informix: ユーザ定義ルーチンおよびデータ タイプ 開発者ガイド」 を参照してください。 SELECT 文での関数の使用 選択リストの中では、列、定数、関数、集計関数、およびプロシジャという基本的 なタイプの式のどれでも使用することができます。また、それらの式を組み合わせ たものも使用できます。 関数式では、問合せにおいて行ごとに評価される関数が使用されます。すべての関 数式には引数が必要です。引数に列名を指定してこれらの式を使用する場合には、 式の中に時刻関数と長さ関数が含まれます。 集計関数 Informix データベース サーバはすべて、以下の集計 関数をサポートします。 v AVG v COUNT v MAX v MIN v RANGE v STDEV v SUM v VARIANCE 集計関数は、問合せ対象行の集合に対して値を 1 つ戻します。集計関数は、 SELECT 文の WHERE 節から戻される行の集合に依存する値をとります。 WHERE 節を指定しない場合、集計関数は、FROM 節で形成されるすべての行に依存する値 をとります。 次のデータ型が含まれている式では、集計関数を使用できません。 v テキスト (TEXT) 型 v バイト (BYTE) 型 Dynamic Server 84 IBM Informix: SQL ガイド: チュートリアル v 文字ラージ オブジェクト (CLOB) 型 v バイナリ ラージ オブジェクト (BLOB) 型 v 不透明 (OPAQUE) 型 (ユーザ定義集計関数でない場合) v コレクション (COLLECTION) 型 v 行 (ROW) 型 Dynamic Server の終り 集計関数は、表内のグループ行についての情報をまとめるために多く使用されま す。この使用方法については、第 5 章で説明しています。集計関数を表全体に適用 する場合には、選択対象行をすべて集計した結果が単一行に格納されます。 COUNT 関数の使用 図 162 では、表 stock 内の行の合計数をカウントして表示します。 SELECT COUNT(*) FROM stock 図 162. 問合せ (count(*)) 73 図 163. 問合せ結果 図 164 は、表 stock の特定の行 (この場合は、SHM の manu_code を持つ行のみ) をカウントする WHERE 節を含みます。 SELECT COUNT (*) FROM stock WHERE manu_code = ’SHM’ 図 164. 問合せ (count(*)) 17 図 165. 問合せ結果 キーワード DISTINCT (またはキーワード UNIQUE) と図 166 に示されている列名 を含めると、表 stock 内の別のメーカー コード数を計算することができます。 SELECT COUNT (DISTINCT manu_code) FROM stock 図 166. 問合せ 第 4 章 SELECT 文での関数の使用 85 (count) 9 図 167. 問合せ結果 AVG 関数の使用 図 168 は、表 stock のすべての行の平均 unit_price を計算します。 SELECT AVG (unit_price) FROM stock 図 168. 問合せ (avg) $197.14 図 169. 問合せ結果 図 170 では、SHM という manu_code を持つ表 stock 内の行の平均 unit_price を計算します。 SELECT AVG (unit_price) FROM stock WHERE manu_code = ’SHM’ 図 170. 問合せ (avg) $204.93 図 171. 問合せ結果 MAX 関数と MIN 関数の使用 同じ SELECT 文の中で、集計関数を組み合わせて使用することができます。例え ば、図 172 に示すように、MAX 関数と MIN 関数を両方選択リストに含めること ができます。 SELECT MAX (ship_charge), MIN (ship_charge) FROM orders 図 172. 問合せ 図 172 では、図 173 で示されているように、表 orders 内の ship_charge の最大 値および最小値を検索して表示します。 86 IBM Informix: SQL ガイド: チュートリアル (max) (min) $25.20 $5.00 図 173. 問合せ結果 SUM 関数の使用 図 174 では、1998 年 7 月 13 日に出荷した注文合計 ship_weight を計算しま す。 SELECT SUM (ship_weight) FROM orders WHERE ship_date = ’07/13/1998’ 図 174. (sum) 130.5 図 175. 問合せ結果 RANGE 関数の使用 RANGE 関数は、選択対象行の最大値と最小値の差を計算します。 RANGE 関数は、数値を示す列のみに適用できます。 図 176 は、表 stock の商品 価格の範囲を検出します。 SELECT RANGE(unit_price) FROM stock 図 176. 問合せ (range) 955.50 図 177. 問合せ結果 図 178 に示すように、GROUP BY 節を含む問合せでは、RANGE 関数は他の集計 関数と同様にグループ内の行に適用されます。 SELECT RANGE(unit_price) FROM stock GROUP BY manu_code 図 178. 問合せ 第 4 章 SELECT 文での関数の使用 87 (range) 820.20 595.50 720.00 225.00 632.50 0.00 460.00 645.90 425.00 図 179. 問合せ結果 STDEV 関数の使用 STDEV 関数は、選択された行の標準偏差を計算します。これは、VARIANCE 関数 の平方根にあたります。 STDEV 関数は、数値を示す列のみに適用できます。次の問合せでは、母集団の標 準偏差を表示します。 SELECT STDEV(age) FROM u_pop WHERE age > 21 次の例に示すように、GROUP BY 節を含む問合せでは、STDEV 関数は他の集計関 数と同様にグループ内の行に適用されます。 SELECT STDEV(age) FROM u_pop GROUP BY state WHERE STDEV(age) > 21 指定された列のすべての値が NULL である場合を除いて、NULL 値は無視されま す。すべての列の値が NULL の場合、STDEV 関数はその列には NULL を戻しま す。 STDEV 関数の詳細については、「IBM Informix: SQL ガイド: 構文」の式セ グメントを参照してください。 VARIANCE 関数の使用 VARIANCE 関数は、選択対象行すべてに対して、値のサンプルの分散を母集団の分 散の不偏推定値として戻します。この関数は、次の値を計算します。 (SUM(Xi**2) - (SUM(Xi)**2)/N)/(N-1) この例では、Xi は列の各値を示し、N は列の値の総数を示します。 VARIANCE 関 数は、数値を示す列のみに適用できます。次の問合せでは、母集団の分散を表示し ます。 SELECT VARIANCE(age) FROM u_pop WHERE age > 21 次の例に示すように、GROUP BY 節を含む問合せでは、VARIANCE 関数は他の集 計関数と同様にグループ内の行に適用されます。 SELECT VARIANCE(age) FROM u_pop GROUP BY birth WHERE VARIANCE(age) > 21 指定された列のすべての値が NULL である場合を除いて、NULL 値は無視されま す。すべての列の値が NULL の場合、VARIANCE 関数はその列には NULL を戻 88 IBM Informix: SQL ガイド: チュートリアル します。 VARIANCE 関数の詳細については、「IBM Informix: SQL ガイド: 構 文」の式セグメントを参照してください。 式への関数の適用 図 180 は、関数を式の中で使用し、その結果に表示ラベルを付ける方法を示してい ます。 SELECT MAX (res_dtime - call_dtime) maximum, MIN (res_dtime - call_dtime) minimum, AVG (res_dtime - call_dtime) average FROM cust_calls 図 180. 問合せ 図 180 は、顧客の注文を受け取ってから処理するまでの時間 (日、時間、分の単位) の最大値、最小値、および平均値を計算して表示し、さらにその値に適切なラベル を付けます。 図 181 に、この 3 種類の時間を示します。 maximum minimum average 5 20:55 0 00:01 1 02:56 図 181. 問合せ結果 時刻関数 問合せの SELECT 節または WHERE 節に、時刻 関数 DAY、MDY、MONTH、 WEEKDAY、および YEAR を使用できます。これらの時刻関数は、関数の呼出し に使用する式または引数に対応する値を戻します。 CURRENT 関数を使用して、 現在の日付と時刻をもつ値を戻し、EXTEND 関数を使用して日付 (DATE) 型また は日時 (DATETIME) 型値の精度を調整できます。 DAY 関数と CURRENT 関数の使用 図 182 では、2 つの expression という列に列 call_dtime および res_dtime の日 付を戻します。 SELECT customer_num, DAY (call_dtime), DAY (res_dtime) FROM cust_calls 図 182. 問合せ 第 4 章 SELECT 文での関数の使用 89 customer_num (expression) (expression) 106 110 119 121 127 116 116 12 7 1 10 31 28 21 12 7 2 10 28 27 図 183. 問合せ結果 図 184 では、DAY 関数および CURRENT 関数を使用して、列の値を月の現在の日 付と比較します。この問合せでは、現在の日付より以前の日付が含まれている行の みを選択します。この例では、CURRENT 日付を 15 としています。 SELECT customer_num, DAY (call_dtime), DAY (res_dtime) FROM cust_calls WHERE DAY (call_dtime) < DAY (CURRENT) 図 184. 問合せ customer_num 106 110 119 121 (expression) (expression) 12 12 7 7 1 2 10 10 図 185. 問合せ結果 図 186 では、CURRENT 関数を使用して、今日受け取った注文を除く、すべての注 文を選択します。 SELECT customer_num, call_code, call_descr FROM cust_calls WHERE call_dtime < CURRENT YEAR TO DAY 図 186. 問合せ customer_num 106 call_code D call_descr Order was received, but two of the cans of ANZ tennis balls within the case were empty customer_num call_code call_descr .. . customer_num call_code call_descr 110 L Order placed one month ago (6/7) not received. 116 I Second complaint from this customer! Received two cases right-handed outfielder gloves (1 HRO) instead of one case lefties. 図 187. 問合せ結果 90 IBM Informix: SQL ガイド: チュートリアル MONTH 関数の使用 図 188 では、MONTH 関数を使用して顧客からの請求を受け取って処理した月を抽 出して表示し、結果を示す列の表示ラベルを使用します。しかし年は区別しませ ん。 SELECT customer_num, MONTH (call_dtime) call_month, MONTH (res_dtime) res_month FROM cust_calls 図 188. 問合せ customer_num call_month res_month 106 110 119 121 127 116 116 6 7 7 7 7 11 12 6 7 7 7 11 12 図 189. 問合せ結果 図 190 では、MONTH 関数、DAY 関数、および CURRENT 関数を使用して、 DAY が現在の日付より前の場合、顧客注文を受けた月と納入した月を表示します。 SELECT customer_num, MONTH (call_dtime) called, MONTH (res_dtime) resolved FROM cust_calls WHERE DAY (res_dtime) < DAY (CURRENT) 図 190. 問合せ customer_num called resolved 106 119 121 6 7 7 6 7 7 図 191. 問合せ結果 WEEKDAY 関数の使用 図 192 では、WEEKDAY 関数を使用して、注文を受けた曜日と納入した曜日を示 し (0 は日曜、1 は月曜を表す) 、式列にラベルを付けます。 第 4 章 SELECT 文での関数の使用 91 SELECT customer_num, WEEKDAY (call_dtime) called, WEEKDAY (res_dtime) resolved FROM cust_calls ORDER BY resolved 図 192. 問合せ customer_num called resolved 127 110 119 121 116 106 116 3 0 1 3 3 3 5 0 2 3 3 3 4 図 193. 問合せ結果 図 194 では、COUNT 関数および WEEKDAY 関数を使用して、週末に受けた注文 数をカウントします。この種の SELECT 文を使用すると、顧客からの請求パターン がどのようなものか、または時間外手当が必要かどうかを示すことができます。 SELECT COUNT(*) FROM cust_calls WHERE WEEKDAY (call_dtime) IN (0,6) 図 194. 問合せ (count(*)) 4 図 195. 問合せ結果 YEAR 関数の使用 図 196 では、call_dtime が今年の 1 月 1 日より以前の日付が含まれている行を抽 出します。 SELECT customer_num, call_code, YEAR (call_dtime) call_year, YEAR (res_dtime) res_year FROM cust_calls WHERE YEAR (call_dtime) < YEAR (TODAY) 図 196. 問合せ 92 IBM Informix: SQL ガイド: チュートリアル customer_num call_code call_year res_year 116 I 116 I 1997 1997 1997 1997 図 197. 問合せ結果 日時 (DATETIME) 型値の形式 図 198 では、EXTEND 関数は、指定されたサブフィールドのみを表示することに より、2 つの日時 (DATETIME) 型値を制限します。 SELECT customer_num, EXTEND (call_dtime, month to minute) call_time, EXTEND (res_dtime, month to minute) res_time FROM cust_calls ORDER BY res_time 図 198. 問合せ 図 199 では、列 call_time および res_time の月から分までの範囲を戻して、作業 負荷を示します。 customer_num call_time 127 106 119 110 121 116 116 07-31 06-12 07-01 07-07 07-10 11-28 12-21 14:30 08:20 15:00 10:24 14:05 13:34 11:24 res_time 06-12 07-02 07-07 07-10 11-28 12-27 08:25 08:21 10:30 14:06 16:47 08:19 図 199. 問合せ結果 日付変換関数 (IDS のみ) 次の変換関数は、日付 (DATE) 型と文字 (CHAR) 型値との間で変換処理を行いま す。 v DATE v TO_CHAR v TO_DATE 日付変換関数は、式を使用する部分ならどこででも使用することができます。 DATE 関数の使用 DATE 関数は、文字列を日付 (DATE) 型値に変換します。図 200 では、DATE 関 数で文字列を日付 (DATE) 型値に変換し、日時 (DATETIME) 型値と比較します。 第 4 章 SELECT 文での関数の使用 93 この問合せでは、call_dtime が指定された 日付 (DATE) 型よりも後である場合の み、日時 (DATETIME) 型値を抽出します。 SELECT customer_num, call_dtime, res_dtime FROM cust_calls WHERE call_dtime > DATE (’12/31/97’) 図 200. 問合せ customer_num call_dtime 106 110 119 121 127 1998-06-12 1998-07-07 1998-07-01 1998-07-10 1998-07-31 res_dtime 08:20 10:24 15:00 14:05 14:30 1998-06-12 1998-07-07 1998-07-02 1998-07-10 08:25 10:30 08:21 14:06 図 201. 問合せ結果 図 202 では、call_dtime が指定された日付以上の値である場合、日時 (DATETIME) 型値を日付 (DATE) 型に変換してラベルを付けて表示します。 SELECT customer_num, DATE (call_dtime) called, DATE (res_dtime) resolved FROM cust_calls WHERE call_dtime >= DATE (’1/1/98’) 図 202. 問合せ customer_num called 106 110 119 121 127 06/12/1998 07/07/1998 07/01/1998 07/10/1998 07/31/1998 resolved 06/12/1998 07/07/1998 07/02/1998 07/10/1998 図 203. 問合せ結果 TO_CHAR 関数の使用 TO_CHAR 関数は、日時 (DATETIME) 型値または日付 (DATE) 型値を文字列に変 換します。 TO_CHAR 関数は、指定したデータの形式 ディレクティブに従って日 時 (DATETIME) 型値を評価し、各国語可変長文字 (NVARCHAR) 型値を戻しま す。サポートされるデータの形式 ディレクティブのリストが必要な場合は、 「IBM Informix: GLS ユーザーズ ガイド」の GL_DATETIME 環境変数の説明を参 照してください。 TO_CHAR 関数を使用して、日時 (DATETIME) 型値または日付 (DATE) 型値をラ ージ可変長文字 (LVARCHAR) 型値に変換することもできます。 94 IBM Informix: SQL ガイド: チュートリアル 図 204 では、TO_CHAR 関数を使用して、日時 (DATETIME) 型値をより読みやす い文字列に変換します。 SELECT customer_num, TO_CHAR(call_dtime, "%A %B %d %Y") call_date FROM cust_calls WHERE call_code = "B" 図 204. 問合せ customer_num 119 call_date Friday July 01 1998 図 205. 問合せ結果 図 206 では、TO_CHAR 関数を使用して、日付 (DATE) 型値をより読みやすい文 字列に変換します。 SELECT order_num, TO_CHAR(ship_date,"%A %B %d %Y") date_shipped FROM orders WHERE paid_date IS NULL 図 206. 問合せ order_num date_shipped 1004 Monday May 30 1998 order_num date_shipped 1006 order_num date_shipped 1007 Sunday June 05 1998 order_num date_shipped 1012 Wednesday June 29 1998 order_num date_shipped 1016 Tuesday July 12 1998 order_num date_shipped 1017 Wednesday July 13 1998 図 207. 問合せ結果 TO_DATE 関数の使用 TO_DATE 関数は、文字 (CHAR) 型データの引数を受け入れ、この値を日時 (DATETIME) 型値に変換します。 TO_DATE 関数は、指定された日付形式に従っ て文字列を評価し、日時 (DATETIME) 型値を戻します。サポートされるデータの形 式 ディレクティブのリストが必要な場合は、「IBM Informix: GLS ユーザーズ ガ イド」の GL_DATETIME 環境変数の説明を参照してください。 第 4 章 SELECT 文での関数の使用 95 TO_DATE 関数を使用して、ラージ可変長文字 (LVARCHAR) 型値を日時 (DATETIME) 型値に変換することもできます。 図 208 では、TO_DATE 関数を使用して、文字列値を、形式を指定した日時 (DATETIME) 型値に変換します。 SELECT customer_num, call_descr FROM cust_calls WHERE call_dtime = TO_DATE("1998-07-07 10:24", "%Y-%m-%d %H:%M"). 図 208. 問合せ customer_num 110 call_descr Order placed one month ago (6/7) not received. 図 209. 問合せ結果 DATE または TO_DATE 関数を使用して、文字列を日付 (DATE) 型値に変換でき ます。 TO_DATE 関数を使用する利点の 1 つは、戻される値の形式を指定できる ことです。 (常に日時 (DATETIME) 型値を戻す TO_DATE 関数を使用し、文字列 を日付 (DATE) 型値に変換できます。これは、日付 (DATE) 型値と日時 (DATETIME) 型値間の変換を、データベース サーバが暗黙的に処理しているためで す。) 図 210 では、TO_DATE 関数を使用して、文字列値を、形式を指定した日付 (DATE) 型値に変換します。 SELECT order_num, paid_date FROM orders WHERE order_date = TO_DATE("6/7/98", "%m/%d/%iY") 図 210. 問合せ order_num paid_date 1008 07/21/1998 図 211. 問合せ結果 計数関数 (IDS のみ) CARDINALITY 関数は、コレクション (COLLECTION) 型の要素数をカウントしま す。 CARDINALITY 関数は、単純コレクション (COLLECTION) 型または入れ子コ レクション (COLLECTION) 型に使用できます。コレクション (COLLECTION) 型 データ内に重複している要素がある場合、それらは別々の要素としてカウントされ 96 IBM Informix: SQL ガイド: チュートリアル ます。 図 212 では、表 manager の行ごとに、department の値と各コレクショ ン (COLLECTION) 型 direct_reports に含まれる要素数が戻されます。 SELECT department, CARDINALITY(direct_reports) FROM manager 図 212. 問合せ department marketing 5 department engineering 7 department publications 4 department accounting 3 図 213. 問合せ結果 図 214 に示すように、述部式の中からコレクション (COLLECTION) 型に含まれて いる要素数を評価することもできます。 SELECT department, CARDINALITY(direct_reports) FROM manager WHERE CARDINALITY(direct_reports) < 6 GROUP BY department 図 214. 問合せ department accounting 3 department marketing 5 department publications 4 図 215. 問合せ結果 スマート ラージ オブジェクト関数 (IDS のみ) データベース サーバには、SQL 文の中から呼び出せ、スマート ラージ オブジェ クトをインポートまたはエクスポートすることができる 4 つの SQL 関数がありま す。次に、スマート ラージ オブジェクト関数を示します。 表 1. スマート ラージ オブジェクト用の SQL 関数 関数名 内容 FILETOBLOB() ファイルをバイナリ ラージ オブジェクト (BLOB) 型列にコピーする FILETOCLOB() ファイルを文字ラージ オブジェクト (CLOB) 型列にコピーする LOCOPY() バイナリ ラージ オブジェクト (BLOB) 型または文字ラージ オブジェ クト (CLOB) 型データを他のバイナリ ラージ オブジェクト (BLOB) 型または文字ラージ オブジェクト (CLOB) 型列にコピーする LOTOFILE() バイナリ ラージ オブジェクト (BLOB) 型データまたは文字ラージ オ ブジェクト (CLOB) 型データをファイルにコピーする 第 4 章 SELECT 文での関数の使用 97 スマート ラージ オブジェクト関数の詳細および構文については、「IBM Informix: SQL ガイド: 構文」の式セグメントを参照してください。 97 に示す関数はいずれも、SELECT、UPDATE、および INSERT 文で使用できま す。これらの関数を INSERT 文および UPDATE 文で使用する例は、 151 ページの 『第 6 章 データの変更』に記載されています。 図 216 に示すように、表 inmate と表 fbi_list を作成すると仮定します。 CREATE TABLE inmate ( id_num INT, picture BLOB, felony CLOB ) CREATE TABLE fbi_list ( id INTEGER, mugshot BLOB ) PUT mugshot IN (sbspace1) 図 216. 次の SELECT 文では、LOTOFILE() 関数を使用して、クライアント コンピュータ にあるファイル felon_322.txt に列 felony のデータをコピーします。 SELECT id_num, LOTOFILE(felony, ’felon_322.txt’, ’client’) FROM inmate WHERE id = 322 LOTOFILE() の 1 つ目の引数には、データのエクスポート元である列の名前を指定 します。 2 つ目の引数は、データのコピー先のファイル名にします。 3 つ目の引 数では、コピー先ファイルがクライアント コンピュータ (’client’) とサーバ コンピ ュータ (’server’) のどちらに置かれているのかを指定します。 関数の引数でファイル名のパス指定をする場合、クライアント コンピュータとサー バ コンピュータのどちらにそのファイルがあるかによって、次のいずれかのルール が適用されます。 v ソース ファイルがサーバ コンピュータに存在する場合は、現在の作業ディレク トリへの相対パス名ではなく、そのファイルへのフルパス名を指定する必要があ ります。 v ソース ファイルがクライアント コンピュータに存在する場合は、そのファイル へのフルパス名または相対パス名のどちらでも指定することができます。 文字列操作関数 (IDS のみ) 文字列操作関数は、文字 (CHAR) 型、各国語文字 (NCHAR) 型、可変長文字 (VARCHAR) 型、各国語可変長文字 (NVARCHAR) 型、およびラージ可変長文字 (LVARCHAR) 型の引数を受け入れます。文字列操作関数は、式を使用する部分なら どこででも使用することができます。 次の関数を使用すると、文字列の大文字と小文字の間の変換が行われます。 98 IBM Informix: SQL ガイド: チュートリアル v LOWER v UPPER v INITCAP 次の関数は、いろいろな方法で文字列を操作します。 v REPLACE v SUBSTR v SUBSTRING v LPAD v RPAD 文字列操作関数をオーバーロードして、拡張 (extended) 型を処理することはできま せん。 LOWER 関数の使用 LOWER 関数を使用すると、文字列内にある大文字がすべて小文字に置き換えられ ます。 LOWER 関数は文字 (CHAR) 型データの引数を受け入れ、指定された引数 と同じデータ型の値を戻します。 図 217 では、LOWER 関数を使用して、文字列内のすべての大文字を小文字に変換 します。 SELECT manu_code, LOWER(manu_code) FROM items WHERE order_num = 1018 図 217. 問合せ manu_code PRC KAR PRC SMT HRO (expression) prc kar prc smt hro 図 218. 問合せ結果 UPPER 関数の使用 UPPER 関数を使用すると、文字列内にある小文字がすべて大文字に置き換えられ ます。 UPPER 関数は文字 (CHAR) 型データの引数を受け入れ、指定された引数 と同じデータ型の値を戻します。 図 219 では、UPPER 関数を使用して、文字列内のすべての小文字を大文字に変換 します。 第 4 章 SELECT 文での関数の使用 99 SELECT call_code, UPPER(code_descr) FROM call_type 図 219. 問合せ call_code (expression) B D I L O BILLING ERROR DAMAGED GOODS INCORRECT MERCHANDISE SENT LATE SHIPMENT OTHER 図 220. 問合せ結果 INITCAP 関数の使用 INITCAP 関数を使用すると、文字列にあるすべての語の先頭文字が大文字に置き換 えられます。 INITCAP 関数は、英文字以外の文字が前にある文字を検出すると、 これを新しい語であるとみなします。 INITCAP 関数は文字 (CHAR) 型データの引 数を受け入れ、指定された引数と同じデータ型の値を戻します。 図 221 では、INITCAP 関数を使用して、文字列内のすべての語の先頭文字を大文字 に変換します。 SELECT INITCAP(description) FROM stock WHERE manu_code = "ANZ" 図 221. 問合せ (expression) Tennis Racquet Tennis Ball Volleyball Volleyball Net Helmet Golf Shoes 3 Golf Balls Running Shoes Watch Kick Board Swim Cap 図 222. 問合せ結果 REPLACE 関数の使用 REPLACE 関数を使用すると、文字列にある特定の文字の集合が別の文字に置き換 えられます。 100 IBM Informix: SQL ガイド: チュートリアル 図 223 では、REPLACE 関数を使用して、問合せで戻されるすべての行に関して、 unit 列の値 each を item に置き換えます。 REPLACE 関数の最初の引数は、評 価する式です。 2 番目の引数は、他のものに置き換えられる文字列を指定します。 3 番目の引数は、置き換えられる文字列に代わる新しい文字列を指定します。 SELECT stock_num, REPLACE(unit,"each", "item") cost_per, unit_price FROM stock WHERE manu_code = "HRO" 図 223. 問合せ stock_num cost_per 1 2 4 7 110 205 301 302 304 305 309 312 case case case case case case item item box case case box unit_price $250.00 $126.00 $480.00 $600.00 $260.00 $312.00 $42.50 $4.50 $280.00 $48.00 $40.00 $72.00 図 224. 問合せ結果 SUBSTRING 関数と SUBSTR 関数の使用 SUBSTRING 関数および SUBSTR 関数を使用して、文字列の一部を戻すことがで きます。文字列の中でこの関数が戻す部分を示すため、開始位置 と長さ (オプショ ン) を指定します。 SUBSTRING 関数の使用 SUBSTRING 関数を使用して、文字列の一部を戻すことができます。文字列の中で この関数が戻す部分を示すため、開始位置 と長さ (オプション) を指定します。開 始位置は、正数または負数で指定できます。開始位置 1 は、SUBSTRING 関数が 文字列の最初から戻し始めることを示します。開始位置がゼロ (0) または負数の場 合は、SUBSTRING 関数は文字列の先頭から後方に数えます。 図 225 に、SUBSTRING 関数の例を示します。ここでは、問合せが戻すすべての列 sname の値の先頭 4 文字が戻されます。この例では、SUBSTRING 関数は文字列 の先頭から開始し、開始位置から数えて 4 文字を戻します。 SELECT sname, SUBSTRING(sname FROM 1 FOR 4) FROM state WHERE code = "AZ" 図 225. 問合せ 第 4 章 SELECT 文での関数の使用 101 sname (expression) Arizona Ariz 図 226. 問合せ結果 図 227 では、SUBSTRING 関数に、開始位置 6 が指定されていますが、長さは指 定されていません。この関数は、6 番目の位置からその文字列の最後までの文字列 を戻します。 SELECT sname, SUBSTRING(sname FROM 6) FROM state WHERE code = "WV" 図 227. 問合せ sname (expression) West Virginia Virginia 図 228. 問合せ結果 図 229 では、SUBSTRING 関数により、問合せが戻したすべての sname 列値に ついて、最初の文字のみが戻されます。 SUBSTRING 関数では、開始位置が -2 のときは、文字列の開始位置から位置が 3 つ (0、-1、-2) 後方に戻されます。開始 位置が 0 のときは、文字列の先頭から位置が 1 つだけ戻されます。 SELECT sname, SUBSTRING(sname FROM -2 FOR 4) FROM state WHERE code = "AZ" 図 229. 問合せ sname (expression) Arizona A 図 230. 問合せ結果 SUBSTR 関数の使用 SUBSTR 関数は、SUBSTRING 関数を同じ機能を持ちますが、構文に違いがあり ます。 文字列の中で SUBSTR 関数が戻す部分を示すため、開始位置 と長さ (オプション) を指定します。 SUBSTR 関数の開始位置は、正数または負数で指定できます。た だし、開始位置に負数が指定された場合、SUBSTR 関数はそれを SUBSTRING 関 数とは異なる方法で扱います。開始位置が負数の場合、SUBSTR 関数は文字列の最 後から先頭に向かってカウントします。これは文字列の長さに依存し、語の文字の 102 IBM Informix: SQL ガイド: チュートリアル 長さ、または文字列に含まれている目に見える文字の長さには影響されません。 SUBSTR 関数は、ゼロ (0) または 1 が開始位置に指定された場合、文字列の最初 から戻し始めます。 図 231 に、開始位置に負数を指定した場合の SUBSTR 関数の例を示します。開始 位置が -15 なので、SUBSTR 関数は文字列の最後から先頭方向に 15 カウントし て開始位置を検出し、そこから 5 文字を戻します。 SELECT sname, SUBSTR(sname, -15, 5) FROM state WHERE code = "CA" 図 231. 問合せ sname (expression) California Calif 図 232. 問合せ結果 開始位置に負数を使用するには、評価される値の長さを知っている必要がありま す。列 sname は CHAR(15) として定義されているため、sname の型の引数をと る SUBSTR 関数では、文字列の先頭から始まる文字列を戻すには、関数の開始位 置に 0、1、または -15 を使用します。 図 233 は、図 231 と同じ結果を戻します。 SELECT sname, SUBSTR(sname, 1, 5) FROM state WHERE code = "CA 図 233. 問合せ LPAD 関数の使用 LPAD 関数を使用すると、ある文字の連続を左にパッドした文字列のコピーが戻さ れます。この文字の連続は、文字列のパッド部分の指定された長さに応じて、必要 な回数だけ反復されるか、または切り捨てられます。ソース文字列、戻される文字 列の長さ、およびパッドする文字列を指定してください。 ソース文字列およびパッドする文字列のデータ型は、可変長文字 (VARCHAR) 型ま たは各国語可変長文字 (NVARCHAR) 型に変換できるデータ型ならどれでもかまい ません。 図 234 に、長さを 21 バイトに指定した場合の LPAD 関数の例を示します。 sname が CHAR(15) として定義されており、ソース文字列の長さが 15 バイトに なるため、LPAD 関数はソース文字列の左側へ先頭から 6 バイト分だけパッドを行 います。 第 4 章 SELECT 文での関数の使用 103 SELECT sname, LPAD(sname, 21, "-") FROM state WHERE code = "CA" OR code = "AZ" 図 234. 問合せ sname (expression) California Arizona ------California ------Arizona 図 235. 問合せ結果 RPAD 関数の使用 RPAD 関数を使用すると、ある文字の連続を右にパッドした文字列のコピーが戻さ れます。この文字の連続は、文字列のパッド部分の指定された長さに応じて、必要 な回数だけ反復されるか、または切り捨てられます。ソース文字列、戻される文字 列の長さ、およびパッドする文字列を指定してください。 ソース文字列およびパッドする文字列のデータ型は、可変長文字 (VARCHAR) 型ま たは各国語可変長文字 (NVARCHAR) 型に変換できるデータ型ならどれでもかまい ません。 図 236 に、長さを 21 バイトに指定した場合の RPAD 関数の例を示します。 sname が CHAR(15) として定義されており、ソース文字列の長さが 15 バイトに なるため、RPAD 関数はソース文字列の右側へ先頭から 6 バイト分だけパッドし ます。 SELECT sname, RPAD(sname, 21, "-") FROM state WHERE code = "WV" OR code = "AZ" 図 236. 問合せ sname West Virginia Arizona (expression) West Virginia -----Arizona ------ 図 237. 問合せ結果 その他の関数 LENGTH、USER、CURRENT、および TODAY 関数を、定数を使用する SQL 式 の任意の位置に使用できます。また、DBSERVERNAME 関数を SELECT 文に含め て、現行データベースが常駐するデータベース サーバの名前を表示することができ ます。 104 IBM Informix: SQL ガイド: チュートリアル これらの関数を使用すると、定数値から構成されている関数式または列データを含 む関数式を選択することができます。最初の例では、すべての行において同じ結果 が出力されます。 また、HEX 関数で関数式を 16 進数に符号化した結果を戻したり、ROUND 関数で 四捨五入した関数式の値を戻したり、TRUNC 関数で切り詰めた関数式の値を戻す ことができます。これらの関数の詳細については、「IBM Informix: SQL ガイド: 構 文」を参照してください。 LENGTH 関数の使用 図 238 では、company の長さが 15 より長い場合、LENGTH 関数で各行において fname と lname を結合した列のバイト数を計算します。 SELECT customer_num, LENGTH (fname) + LENGTH (lname) namelength FROM customer WHERE LENGTH (company) > 15 図 238. 問合せ customer_num namelength 101 105 107 112 115 118 119 120 122 124 125 126 127 128 11 13 11 14 11 10 10 10 12 11 10 12 10 11 図 239. 問合せ結果 DB–Access 使用する場合はあまり役立ちませんが、LENGTH 関数は、プログラム およびレポートの文字列の長さを決定するときに重要な役割を果たす場合がありま す。 LENGTH 関数は、文字 (CHARACTER) 型または可変長文字 (VARCHAR) 型 文字列のクリップされた長さを戻し、テキスト (TEXT) 型またはバイト (BYTE) 型 文字列の完全なバイト数を戻します。 USER 関数の使用 USER 関数を使用して、ユーザのユーザ ID を含む行のみで構成された表の制限付 きビューを定義できます。ビューの作成方法については、「IBM Informix: データベ ース設計および実装 ガイド」と、「IBM Informix: SQL ガイド: 構文」の GRANT および CREATE VIEW 文を参照してください。 図 240 では、問合せを実行するユーザのユーザ名 (ログインアカウント名) を戻し ます。この問合せは、表内の各行に対して 1 回行われます。 第 4 章 SELECT 文での関数の使用 105 SELECT * FROM cust_calls WHERE user_id = USER 図 240. 問合せ 現行ユーザのユーザ名が richc の場合、図 240 は、表 cust_calls 内で user_id = richc である行のみを抽出します。結果を 図 241 に示します。 customer_num call_dtime user_id call_code call_descr res_dtime res_descr 110 1998-07-07 10:24 richc L Order placed one month ago (6/7) not received. 1998-07-07 10:30 Checked with shipping (Ed Smith). Order sent yesterday-we were waiting for goods from ANZ. Next time will call with delay if necessary customer_num call_dtime user_id call_code call_descr res_dtime res_descr 119 1998-07-01 15:00 richc B Bill does not reflect credit from previous order 1998-07-02 08:21 Spoke with Jane Akant in Finance. She found the error and is sending new bill to customer 図 241. 問合せ結果 TODAY 関数の使用 TODAY 関数は、現行システム日付を戻します。現在のシステム日付が 1998 年 7 月 10 日の場合に図 242 を使用すると、次の 1 行が戻されます。 SELECT * FROM orders WHERE order_date = TODAY 図 242. 問合せ order_num order_date customer_num ship_instruct backlog po_num ship_date ship_weight ship_charge paid_date 1018 07/10/1998 121 SW corner of Biltmore Mall n S22942 07/13/1998 70.50 $20.00 08/06/1998 図 243. 問合せ結果 106 IBM Informix: SQL ガイド: チュートリアル DBSERVERNAME 関数と SITENAME 関数の使用 DBSERVERNAME 関数 (またはそのシノニムである SITENAME 関数) を SELECT 文で使用し、データベース サーバの名前を検索できます。行を持つ表 (シ ステム カタログ表など) の DBSERVERNAME について問合せを実行することが できます。 図 244 では、ラベル server を DBSERVERNAME 関数式に設定し、列 tabid を システム カタログ表 systables から選択します。この表がデータベース表であ り、tabid はこの表の識別子です。 SELECT DBSERVERNAME server, tabid FROM systables WHERE tabid <= 4 図 244. 問合せ server tabid montague montague montague montague 1 2 3 4 図 245. 問合せ結果 WHERE 節では、表示する行数を制限します。制限をしない場合には、データベー ス サーバ名が表 systables の行ごとに 1 回ずつ表示されます。 HEX 関数の使用 図 246 では、HEX 関数を使用して、表 customer の 2 つの列の 16 進形式を戻 します。この結果を 図 247 に示します。 SELECT HEX (customer_num) hexnum, HEX (zipcode) hexzip FROM customer 図 246. 問合せ hexnum hexzip 0x00000065 0x00000066 0x00000067 0x00000068 0x00000069 0x0000006A . . . 0x00016F86 0x00016FA5 0x0001705F 0x00016F4A 0x00016F46 0x00016F6F 図 247. 問合せ結果 第 4 章 SELECT 文での関数の使用 107 DBINFO 関数の使用 DBINFO 関数を SELECT 文で使用し、以下の情報を検索できます。 v 表領域番号または式に対応する DB 領域の名前 v 表に挿入された最新のシリアル値 v 選択、挿入、削除、更新、および実行のルーチン文により処理された行の数 v 現行セッションのセッション ID v データベース サーバを実行しているホスト コンピュータの名前 v クライアント アプリケーションの接続先となるデータベース サーバの正確なバ ージョン DBINFO 関数は、SQL 文および SPL ルーチン内の任意の位置で使用できます。 図 248 に、DBINFO 関数を使用して、データベース サーバを実行しているホスト コンピュータの名前を抽出する方法を示します。 SELECT FIRST 1 DBINFO(’dbhostname’) FROM systables 図 248. 問合せ (constant) lyceum 図 249. 問合せ結果 tabid の値を制約する FIRST 1 節がない場合、表 systables の行ごとにデータベ ース サーバが稼動するコンピュータのホスト名が繰り返されます。 図 250 では、 DBINFO 関数を使用して、現行データベース サーバの完全なバージョン番号および 型を検出します。 SELECT FIRST 1 DBINFO(’version’,’full’) FROM systables 図 250. 問合せ DBINFO 関数を使用して、現行データベース サーバ、データベース セッション、 またはデータベースに関する情報を検出する方法の詳細については、 「IBM Informix: SQL ガイド: 構文」を参照してください。 DECODE 関数の使用 DECODE 関数は、式の 1 つの値を別の値に変換します。 DECODE 関数には、以 下のフォームがあります。 DECODE(test, a, a_value, b, b_value, ..., n, n_value, exp_m ) DECODE は、a が test と等しい場合 a_value を戻し、 b が test と等しい場合 b_value を戻し、 n が test と等しい場合に n_value を戻します。 108 IBM Informix: SQL ガイド: チュートリアル 複数の式が test と一致した場合は、DECODE は最初に一致した式に対して n_value を戻します。 test と一致する式がない場合は、DECODE は exp_m を戻し ます。test と一致する式がなく、 exp_m がない場合は、DECODE は NULL を戻 します。 DECODE 関数は、テキスト (TEXT) 型とバイト (BYTE) 型の引数を受け入れませ ん。 列 emp_id と列 evaluation を含む表 employee があるとします。表 employee に対して図 251 を実行したところ、 図 252 に示す行が戻されたと仮定します。 SELECT emp_id, evaluation FROM employee 図 251. 問合せ emp_id evaluation 012233 012344 012677 012288 012555 great poor NULL good very good 図 252. 問合せ結果 場合によっては、値のセットの変換が必要になります。例えば、前の例の列 evaluation の記述値を、対応する数値に変換する必要があるとします。 図 253 に、DECODE 関数を使用して列 evaluation の値を、 表 employee の各行につ いて、数値に変換する方法を示します。 SELECT emp_id, DECODE(evaluation, "poor", 0, "fair", 25, "good", 50, "very good", 75, "great", 100, -1) AS evaluation FROM employee 図 253. 問合せ emp_id evaluation 012233 012344 012677 012288 012555 . . . 100 0 -1 50 75 図 254. 問合せ結果 DECODE 関数の引数は、次の要件を満たす場合は任意のデータ型を指定できます。 v 引数 test, a,b, ..., n はすべて同じデータ型を持ち、共通互換 (compatible) 型とし て評価されます。 第 4 章 SELECT 文での関数の使用 109 v 引数 a_value, b_value, ..., n_value はすべて同じデータ型を持ち、共通互換 (compatible) 型として評価されます。 NVL 関数の使用 (IDS のみ) NVL 関数は、NULL と評価された式を、ユーザが指定する値に変換します。 NVL 関数は、 2 種類の引数を受け入れます。最初の引数は、評価される式の名前です。 2 番目の引数は、最初の引数が NULL と評価されたときに関数が戻す値です。最初 の引数が NULL と評価されない場合、関数は最初の引数の値を戻します。例えば列 name と列 address を含む表 student があるとします。また、表 student に対 して図 255 を実行した場合、図 256 に示す行が戻されるとします。 SELECT name, address FROM student 図 255. 問合せ name address John Smith Lauren Collier Fred Frith Susan Jordan 333 Vista Drive 1129 Greenridge Street NULL NULL 図 256. 問合せ結果 図 257 には NVL 関数が含まれています。これにより、NULL 値を含む列 address を持つ表の各行について新しい値が戻されます。 SELECT name, NVL(address, "address is unknown") AS address FROM student 図 257. 問合せ name address John Smith Lauren Collier Fred Frith Susan Jordan 333 Vista Drive 1129 Greenridge Street address is unknown address is unknown 図 258. 問合せ結果 NVL 関数の 2 つの引数が共通互換 (compatible) 型であると評価するなら、これら の引数に任意のデータ型を指定できます。 NVL 関数の両方の引数が NULL と評価される場合、NULL が戻されます。 SELECT 文での SPL ルーチンの使用 この章では、列名、演算子、および SQL 関数で構成される SELECT 文式に関する 例を示してきました。ここでは、SPL ルーチン呼出しを含む式について説明しま す。 110 IBM Informix: SQL ガイド: チュートリアル SPL ルーチンは、SQL 文とともに、特殊なストアド プロシジャ言語 (SPL) 文を含 みます。 SPL ルーチンの詳細については、第 11 章を参照してください。 Dynamic Server Dynamic Server では、C 言語および Java 言語で外部ルーチンを作成できます。詳 しくは、「IBM Informix: ユーザ定義ルーチンおよびデータ タイプ 開発者ガイド」 を参照してください。 Dynamic Server の終り SPL ルーチン式を選択リストにインクルードする場合には、単一値 (1 行で 1 列) を戻す SPL ルーチンでなければなりません。例えば、次の文は、test_func() が単 一値を戻す場合にのみ有効です。 SELECT col_a, test_func(col_b) FROM tab1 WHERE col_c = "Davis" 複数の値を戻す SPL ルーチンは、SELECT 文の選択リストでサポートされませ ん。上記の例では、test_func() が複数の値を戻すと、データベース サーバからエ ラー メッセージが戻されます。 SPL ルーチンを使用すると、関数の使用範囲を拡張できます。すなわち選択する各 行について副問合せを実行することができます。 例えば、顧客番号、顧客の姓、顧客からの注文数をリストすると仮定します。 図 259 は、この情報を抽出する方法の 1 つを示しています。表 customer には、列 customer_num と lname がありますが、各顧客の注文数の記録はありません。各 customer_num について表 orders に問合せを行い、 n_orders というラベルが 付いた対応する注文の数を戻す get_orders というルーチンを作成することができ ます。 SELECT customer_num, lname, get_orders(customer_num) n_orders FROM customer 図 259. 問合せ 図 260 に、この SPL ルーチンの結果を示します。 第 4 章 SELECT 文での関数の使用 111 customer_num lname n_orders 101 102 103 104 Pauli Sadler Currie Higgins 1 9 9 4 123 124 125 126 127 128 Hanlon Putnum Henry Neelie Satifer Lessor 1 1 0 1 1 0 . . . 図 260. 問合せ結果 SPL ルーチンを使用して、問合せの中で実行回数の多い演算をカプセル化します。 例えば、図 261 の条件には、在庫品の単価を別の通貨に換算し、輸入関税を加える ルーチン conv_price が含まれています。 SELECT stock_num, manu_code, description FROM stock WHERE conv_price(unit_price, ex_rate = 1.50, tariff = 50.00) < 1000 図 261. 問合せ サマリ この章では、リレーショナル データベースへの問合せ、および戻されたデータの操 作に使用する、基本的な SELECT 文内の関数の構文例と、その出力結果を紹介しま した。 84 ページの『SELECT 文での関数の使用』には、以下のアクションを実行 する方法について記載しています。 v SELECT 節で集計関数を使用して、特定のデータの計算と検索を行う。 v SELECT 文で、時刻関数 DATE、DAY、MDY、MONTH、WEEKDAY、YEAR、 CURRENT、および EXTEND のほかに TODAY、LENGTH、および USER を 使用する。 v SELECT 節で変換関数を使用して、日付値と文字値との間で変換を行う。 v SELECT 節で文字列操作関数を使用して、大文字と小文字の変換や文字列に対し てさまざまな操作を行う。 110 ページの『SELECT 文での SPL ルーチンの使用』には、SELECT 文に SPL ル ーチンを含める方法を記載しています。 112 IBM Informix: SQL ガイド: チュートリアル 第 5 章 高度な SELECT 文の作成 GROUP BY 節と HAVING 節の使用 . . . . . . . . . . . . . . . GROUP BY 節の使用方法 . . . . . . . . . . . . . . . . . . HAVING 節の使用方法 . . . . . . . . . . . . . . . . . . . 高度な結合の作成 . . . . . . . . . . . . . . . . . . . . . . セルフ結合 . . . . . . . . . . . . . . . . . . . . . . . 外部結合 . . . . . . . . . . . . . . . . . . . . . . . . 外部結合構文の Informix 拡張 . . . . . . . . . . . . . . . . ANSI 結合構文 . . . . . . . . . . . . . . . . . . . . . 左外部結合 . . . . . . . . . . . . . . . . . . . . . . 右外部結合 (IDS のみ) . . . . . . . . . . . . . . . . . . 単純結合 . . . . . . . . . . . . . . . . . . . . . . . 2 つの表の単純な外部結合 . . . . . . . . . . . . . . . . . 第 3 の表に対する単純結合との外部結合 . . . . . . . . . . . . 第 3 の表に対する 2 つの表の外部結合 . . . . . . . . . . . . 外部結合を組み合わせる結合 . . . . . . . . . . . . . . . . SELECT 文の副問合せ . . . . . . . . . . . . . . . . . . . . 選択リストの副問合せ . . . . . . . . . . . . . . . . . . . WHERE 節の中の副問合せ . . . . . . . . . . . . . . . . . . ALL の使用 . . . . . . . . . . . . . . . . . . . . . . ANY の使用. . . . . . . . . . . . . . . . . . . . . . 一価副問合せ . . . . . . . . . . . . . . . . . . . . . 相関副問合せ . . . . . . . . . . . . . . . . . . . . . EXISTS の使用 . . . . . . . . . . . . . . . . . . . . . SELECT 文でのコレクションの処理 (IDS のみ) . . . . . . . . . . . . コレクション (COLLECTION) 型副問合せ . . . . . . . . . . . . . コレクション (COLLECTION) 型の副問合せでのキーワード ITEM の省略 . コレクション (COLLECTION) 型の副問合せでのキーワード ITEM の指定 . コレクション (COLLECTION) 型導出表 . . . . . . . . . . . . . 集合演算 . . . . . . . . . . . . . . . . . . . . . . . . . 和集合. . . . . . . . . . . . . . . . . . . . . . . . . UNION と ORDER BY の使用 . . . . . . . . . . . . . . . UNION ALL の使用 . . . . . . . . . . . . . . . . . . . 異なる列名の使用 . . . . . . . . . . . . . . . . . . . . 複数の表に対する UNION の使用 . . . . . . . . . . . . . . 選択リスト内でのリテラルの使用. . . . . . . . . . . . . . . FIRST 節の使用 . . . . . . . . . . . . . . . . . . . . 積 . . . . . . . . . . . . . . . . . . . . . . . . . . 差 . . . . . . . . . . . . . . . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 114 117 119 120 123 124 124 124 126 126 127 128 129 130 130 131 132 132 133 134 135 136 138 139 139 140 140 142 142 144 144 145 146 147 147 148 149 150 本章について この章では、SELECT 文の範囲を広げて、さらに複雑なデータベースの問合せとデ ータ操作を実行できるようにします。 15 ページの『第 2 章 SELECT 文の作成』 では、SELECT 構文で使用する 5 つの節について説明しましたが、この章では、さ らに GROUP BY 節と HAVING 節について説明します。GROUP BY 節は、集計 関数とともに使用することで、FROM 節に戻された行を編成することができます。 また、HAVING 節を使用して、GROUP BY 節が戻した値に条件を設定することが できます。 © Copyright IBM Corp. 1996, 2003 113 この章では、結合についての説明の範囲を前よりも広げます。表をその表自体に結 合できるようにするセルフ結合、および複数の結合された表を平等に扱わないよう にキーワード OUTER を使用する 4 種類の外部結合 について、例をあげて説明し ます。また、その他にも、相関/非相関副問合せとその操作キーワード、演算子 UNION を使用して問合せを結合する方法を説明し、集合演算の和、積、差を定義し ます。 この章では例を使用して、問合せのときの一部またはすべての SELECT 文の節の使 用方法を説明します。各節は必ず次の順序で指定してください。 1. FROM 2. WHERE 3. GROUP BY 4. HAVING 5. ORDER BY 6. INTO TEMP これらすべての節を正しい順序で使用した SELECT 文の例を、119 ページの図 276 に示します。 もう 1 つの SELECT 文節 INTO では、 SQL API でプログラムとホスト変数を指 定できます。この節については、197 ページの『第 8 章 SQL を使用したプログラ ミング』と、製品に付属した資料を参照してください。 GROUP BY 節と HAVING 節の使用 オプションの GROUP BY 節および HAVING 節を使用することで、SELECT 文に 機能を加えることができます。どちらか一方または両方を SELECT 文に記述する と、集計関数をより高度に活用できます。 GROUP BY 節は、類似の行を結合して、選択リスト内の各列で値が同じ行のグルー プ ごとに結果行 を 1 つ作成します。 HAVING 節はこれらのグループが形成され た後に、条件を設定します。 GROUP BY を使用して HAVING 節を省略したり、 HAVING 節を使用して GROUP BY 節を省略したりできます。 GROUP BY 節の使用方法 GROUP BY 節は、表をいくつかのセットに分割します。この節は、それらのセット のそれぞれに対して要約値を作成する集計関数と組み合わせて使用されることが多 くなっています。 第 2 章では、表全体に適用される集計関数の使用方法を例を用 いて説明しました。この章では、行グループに適用される集計関数について説明し ます。 集計関数を使用しないで GROUP BY を使用した場合は、SELECT 節内でキーワー ド DISTINCT (または UNIQUE) を使用した場合とほぼ同じことを意味します。 図 262 の説明は、27 ページの『特定の列の選択』に記載されています。 114 IBM Informix: SQL ガイド: チュートリアル SELECT DISTINCT customer_num FROM orders 図 262. 問合せ 図 263 のように記述することもできます。 SELECT customer_num FROM orders GROUP BY customer_num 図 263. 問合せ 図 262 と図 263 は、図 264 に示す行を戻します。 customer_num 101 104 106 110 . . . 124 126 127 図 264. 問合せ結果 GROUP BY 節は、収集した行をいくつかのセットにまとめて、各セット内のすべて の行で顧客番号が同じになるようにしています。何も列が選択されていないと、結 果は一意の customer_num の値のリストとして取り出されます。 GROUP BY 節は集計関数と一緒に使用するとその機能がよくわかります。 図 265 は、各注文についての品目数と各品目の合計金額を抽出します。 SELECT order_num, COUNT (*) number, SUM (total_price) price FROM items GROUP BY order_num 図 265. 問合せ GROUP BY 節を使用すると、表 items (注文品目) の行で、列 order_num (注文 番号) に同じ値を持つものを 1 つのグループとしてまとめます。つまり、各注文を 構成する品目を 1 グループとしてまとめます。データベース サーバがグループを 形成した後で、集計関数 COUNT および SUM が各グループに適用されます。 図 265 は、それぞれのグループごとに 1 行を戻します。 COUNT および SUM 式 の結果に名前を付けるために、図 266 のようなラベルが使用されます。 第 5 章 高度な SELECT 文の作成 115 order_num number price 1001 1002 1003 1004 1 2 3 4 $250.00 $1200.00 $959.00 $1416.00 1021 1022 1023 4 3 6 $1614.00 $232.00 $824.00 . . . 図 266. 問合せ結果 図 266 は表 items の行を注文番号が同じグループにまとめて、各グループごとの 行数の COUNT を計算し、各品目の合計金額を出力します。 GROUP BY 節には、テキスト (TEXT) 型、バイト (BYTE) 型、文字ラージ オブジ ェクト (CLOB) 型、およびバイナリ ラージ オブジェクト (BLOB) 型列を指定でき ません。グループ化 するにはソート 可能である必要がありますが、これらのデー タ型には、自然なソート順がありません。 ORDER BY 節とは異なり、GROUP BY 節はデータの並び替えを行いません。デー タを特定の順序でソートするか、または選択リスト内の集合に基づいてソートする 場合は、ORDER BY 節を GROUP BY 節の後 に指定します。 図 267 は、ORDER BY 節を追加し、抽出した行を price に基づいて昇順にソート する点以外は、図 265 と同じです。 SELECT order_num, COUNT(*) number, SUM (total_price) price FROM items GROUP BY order_num ORDER BY price 図 267. 問合せ order_num number price 1010 1011 1013 1022 1001 1020 1006 2 1 4 3 1 2 5 $84.00 $99.00 $143.80 $232.00 $250.00 $438.00 $448.00 1002 1004 1014 1019 1021 1007 2 4 2 1 4 5 $1200.00 $1416.00 $1440.00 $1499.97 $1614.00 $1696.00 . . . 図 268. 問合せ結果 116 IBM Informix: SQL ガイド: チュートリアル 27 ページの『特定の列の選択』で説明したように、ORDER BY 節に整数を使用し て、選択リスト内の列の位置を指定することができます。 GROUP BY 節でも同様 に、グループ リスト内の列名や表示ラベルの位置を示すために整数を使用できま す。 図 269 は、図 268 に示すように、図 267 と同じ行を戻します。 SELECT order_num, COUNT(*) number, SUM (total_price) price FROM items GROUP BY 1 ORDER BY 3 図 269. 問合せ 問合せを作成する場合、SELECT 節の選択リスト内にある集合以外のすべての列が GROUP BY 節のグループ リストにも含まれている必要があります。 SELECT 文 で GROUP BY 節を使用する場合は、グループあたり 1 行のみが戻される必要があ るためです。 GROUP BY節の後に指定されている行は、必ずグループ内の別個の値 を 1 つのみ反映し、その値を戻すことができます。ただし、GROUP BY の後に指 定されていない列の値は、グループ内の各行で異なる場合があります。 図 270 に示すように、表を結合する SELECT 文で GROUP BY 節を使用できま す。 SELECT o.order_num, SUM (i.total_price) FROM orders o, items i WHERE o.order_date > ’01/01/98’ AND o.customer_num = 110 AND o.order_num = i.order_num GROUP BY o.order_num 図 270. 問合せ 図 270 は、表 orders と表 items を結合して、これに表の別名を付け、図 271 の 示す行を戻します。 order_num (sum) 1008 1015 $940.00 $450.00 図 271. 問合せ結果 HAVING 節の使用方法 HAVING 節は、通常 GROUP BY 節を補足するために使用し、行がグループ化され た後で、グループに対し選択のための 1 つ以上の条件を適用します。 HAVING 節 がグループに与える影響は、WHERE 節が各行を修飾する場合と似ています。 HAVING 節の利点はその探索条件に集計関数を記述できる点です。WHERE 節の探 索条件には集計関数を記述できません。 第 5 章 高度な SELECT 文の作成 117 それぞれの HAVING 節の条件では、1 つの列やグループに適用された集計関数の 値が、グループの別の集計関数の値や定数と比較されます。 HAVING 節を使用し て、グループの並びの列の値と集計関数の値の両方に条件を設定することができま す。 図 272 は、品目が 3 つ以上のすべての注文について品目ごとの平均合計金額を戻し ます。 HAVING 節は、作成された各グループをテストし、複数の行で構成された グループを選択します。 SELECT order_num, COUNT(*) number, AVG (total_price) average FROM items GROUP BY order_num HAVING COUNT(*) > 2 図 272. 問合せ order_num number average 1003 1004 1005 1006 1007 1013 1016 1017 1018 1021 1022 1023 3 4 4 5 5 4 4 3 5 4 3 6 $319.67 $354.00 $140.50 $89.60 $339.20 $35.95 $163.50 $194.67 $226.20 $403.50 $77.33 $137.33 図 273. 問合せ結果 HAVING 節を指定し、GROUP BY 節を指定しない場合、HAVING 条件は検索条件 を満たす行すべてに適用されます。つまり、探索条件を満たすすべての行が 1 つの グループを構成します。 図 274 は図 272 を書き直したもので、図 275 で示すように 1 行の結果、つまり表 のすべての列 total_price (合計価格) の平均を戻します。 SELECT AVG (total_price) average FROM items HAVING count(*) > 2 図 274. 問合せ average $270.97 図 275. 問合せ結果 118 IBM Informix: SQL ガイド: チュートリアル 図 272 と同様、図 274 では、選択リスト内に集合でない列 order_ num が含まれ ている場合、GROUP BY 節を追加し、グループ リストにこの列を指定する必要が あります。また、HAVING 節での条件が満たされていない場合は、列見出しが表示 され、該当する行を検出できなかったことを示すメッセージが表示されます。 図 276 には、対話型 SQL の Informix バージョンで使用できる SELECT 文の節が すべて含まれています (ホスト変数を命名する INTO 節は、SQL API でのみ使用で きます)。 SELECT o.order_num, SUM (i.total_price) price, paid_date - order_date span FROM orders o, items i WHERE o.order_date > ’01/01/98’ AND o.customer_num > 110 AND o.order_num = i.order_num GROUP BY 1, 3 HAVING COUNT (*) < 5 ORDER BY 3 INTO TEMP temptab1 図 276. 問合せ 図 276 は、表 orders と表 items を結合し、表示ラベル、表の別名、列標識とし て使用されている整数を使用し、データのグループ化と順序付けを行い、また、図 277 が示しているように結果を一時表に入れます。 order_num price span 1017 1016 1012 1019 1005 1021 1022 1010 1009 1020 $584.00 $654.00 $1040.00 $1499.97 $562.00 $1614.00 $232.00 $84.00 $450.00 $438.00 26 28 30 40 66 68 71 図 277. 問合せ結果 高度な結合の作成 57 ページの『結合の作成』では、SELECT 文に WHERE 文を指定して、1 つ以上 の列に関して複数の表を結合する方法について説明しました。そこで説明した結合 は、自然結合と等結合の 2 種類でした。 この章では、2 種類の結合よりもさらに複雑な、セルフ結合と外部結合の使用につ いて説明します。表セルフ結合やアウター結合においても、第 2 章で説明した単純 な結合と同じように、表の別名や表示ラベルを使用することができます。表に別名 を定義したり、式に表示ラベルを割り当てると、複数表からなる問合せの記述を簡 略化することができます。また、ORDER BY を使用した SELECT 文を発行してデ ータをソートし、一時表に格納することもできます。 第 5 章 高度な SELECT 文の作成 119 セルフ結合 結合では必ずしも 2 つの異なる表を結合させる必要はありません。表をそれ自体に 結合させて、セルフ結合 とすることができます。列内の値を同じ列内の別の値と比 較するときには、表をその表自体と結合すると便利な場合があります。 セルフ結合を作成するには、FROM 節から表を 2 回リストして、これに 1 回ごと に異なる別名を指定します。 SELECT 節と WHERE 節ではこれらの別名を使用し て、2 つの別な表があるかのように参照します。 (SELECT 文の別名については、 64 ページの『別名の使用』および「IBM Informix: SQL ガイド: 構文」を参照して ください。) 異なる表の結合の場合と同様に、セルフ結合でも算術式を使用できます。 NULL を テストすることも、ORDER BY 節を使用して、指定した列の値を昇順または降順に ソートすることもできます。 図 278 は、ship_weight が 5 倍以上異なり、ship_date が NULL ではない注文 のペアを探索します。そして、ship_date 順に並び替えます。 SELECT x.order_num, x.ship_weight, x.ship_date, y.order_num, y.ship_weight, y.ship_date FROM orders x, orders y WHERE x.ship_weight >= 5 * y.ship_weight AND x.ship_date IS NOT NULL AND y.ship_date IS NOT NULL ORDER BY x.ship_date 図 278. 問合せ 表 2. 問合せ結果 order_num ship_weight ship_date order_num ship_weight ship_date 1004 95.80 05/30/1998 1011 10.40 07/03/1998 1004 95.80 05/30/1998 1020 14.00 07/16/1998 1004 95.80 05/30/1998 1022 15.00 07/30/1998 1007 125.90 06/05/1998 1015 20.60 07/16/1998 1007 125.90 06/05/1998 1020 14.00 07/16/1998 セルフ結合の結果を一時表に格納する場合は、SELECT 文に INTO TEMP 節を追加 して、それらに表示ラベルを割り当てることにより、少なくとも 1 組の列を名前変 更してください。この処置を行わないと、列名の重複が原因でエラーが発生し、一 時表が作成されません。 図 279 では図 278 と同様に、表 orders から選択されたすべての列に表示ラベルを 付け、shipping (出荷) という名前の一時表に格納します。 120 IBM Informix: SQL ガイド: チュートリアル SELECT x.order_num orders1, x.po_num purch1, x.ship_date ship1, y.order_num orders2, y.po_num purch2, y.ship_date ship2 FROM orders x, orders y WHERE x.ship_weight >= 5 * y.ship_weight AND x.ship_date IS NOT NULL AND y.ship_date IS NOT NULL ORDER BY orders1, orders2 INTO TEMP shipping 図 279. 問合せ SELECT * from table shipping という問合せを行うと、図 280 に示す行が戻されま す。 orders1 purch1 1004 1004 1004 1005 8006 8006 8006 2865 ship1 orders2 purch2 ship2 05/30/1998 05/30/1998 05/30/1998 06/09/1998 1011 1020 1022 1011 B77897 W2286 W9925 B77897 07/03/1998 07/16/1998 07/30/1998 07/03/1998 07/16/1998 07/16/1998 07/30/1998 1020 W2286 1022 W9925 1011 B77897 07/16/1998 07/30/1998 07/03/1998 . . . 1019 Z55709 1019 Z55709 1023 KF2961 図 280. 問合せ結果 表はその表自体と何回でも結合できます。セルフ結合できる最大回数は、利用可能 なシステム資源によって異なります。 図 281 のセルフ結合では、表 stock (取扱品目) の品目のうち、3 つのメーカーか ら提供されるものを取り出します。セルフ結合では WHERE 節の最後の 2 つの条 件を指定することによって、重複するメーカー コードを抽出した行から除去できま す。 SELECT s1.manu_code, s2.manu_code, s3.manu_code, s1.stock_num, s1.description FROM stock s1, stock s2, stock s3 WHERE s1.stock_num = s2.stock_num AND s2.stock_num = s3.stock_num AND s1.manu_code < s2.manu_code AND s2.manu_code < s3.manu_code ORDER BY stock_num 図 281. 問合せ 第 5 章 高度な SELECT 文の作成 121 manu_code manu_code manu_code stock_num description HRO ANZ ANZ ANZ ANZ ANZ ANZ ANZ HRO HRO HRO . . . KAR KAR KAR NKL HSK NRG HRO HRO HRO HSK HSK PRC HSK HSK PRC SMT SMT HSK PRC SHM PRC SHM SHM PRC SHM SHM 1 5 110 110 110 110 110 110 110 110 110 baseball gloves tennis racquet helmet helmet helmet helmet helmet helmet helmet helmet helmet NKL NKL PRC PRC PRC SHM SHM SHM 301 301 301 301 running running running running shoes shoes shoes shoes 図 282. 問合せ結果 給与計算表から行を選択して、マネージャよりも所得の多い従業員を判別すると仮 定します。この場合、次の SELECT 文でセルフ結合を作成できます。 SELECT emp.employee_num, emp.gross_pay, emp.level, emp.dept_num, mgr.employee_num, mgr.gross_pay, mgr.dept_num, mgr.level FROM payroll emp, payroll mgr WHERE emp.gross_pay > mgr.gross_pay AND emp.level < mgr.level AND emp.dept_num = mgr.dept_num ORDER BY 4 図 283 では、相関副問合せ を使用して、価格の高い品目を上から順に 10 個抽出し てリストします。 SELECT order_num, total_price FROM items a WHERE 10 > (SELECT COUNT (*) FROM items b WHERE b.total_price < a.total_price) ORDER BY total_price 図 283. 問合せ 図 283 は、図 284 に示す 10 行を戻します。 122 IBM Informix: SQL ガイド: チュートリアル order_num 1018 1013 1003 1005 1006 1013 1010 1013 1022 1023 total_price $15.00 $19.80 $20.00 $36.00 $36.00 $36.00 $36.00 $40.00 $40.00 $40.00 図 284. 問合せ結果 同じような問合せを作成し、社内で最も年功が高い 10 人の従業員を探して表示す ることもできます。 相関副問合せの詳細については、130 ページの『SELECT 文の副問合せ』を参照し てください。 外部結合 ここでは、外部結合を作成し、SELECT 文で使用する方法について説明します。 57 ページの『結合の作成』では、内部結合について説明しました。内部結合では、結 合の対象となる 2 つ以上の表が対等に扱われますが、外部結合では非対称的に扱わ れます。外部結合では、表の 1 つが主表 (または外部表)となり、他の表が従属表 (または内部表) になります。 内部結合または単純結合では、結合条件を満たす行の組合せのみが結果に含まれま す。結合条件を満たさない行は無視されます。 外部結合では、結合条件を満たす行の組合せが結果に含まれます。また、従属表で 一致する行がないために廃棄されるはずの主表からの行も含まれます。従属表に一 致する行がない主表の行には、従属表に選択された列に NULL 値が設定されます。 その後、選択された列が射影されます。 外部結合を使用することで、結合条件を適用する前に、内部表に対して結合フィル タを適用できます。 旧バージョンのデータベース サーバでは、外部結合に関して、ANSI-SQL 標準構文 の Informix 拡張のみをサポートしていました。この構文は現在でもサポートされま すが、ANSI-SQL 標準構文の方が、問合せ作成に対する柔軟性が向上しています。 新しい問合せを作成する場合は、ANSI-SQL 標準構文を使用することをお勧めしま す。どちらの構文を使用する場合でも、同じ照会ブロック内で使用する構文は統一 してください。 外部結合を多用する前に、1 つ以上の内部結合が機能するか判別する必要がありま す。通常、他の表の補足情報が必要ない場合は、内部結合で間に合わせることがで きます。 重要: 同じ照会ブロック内では、Informix 外部結合構文と ANSI 外部結合構文を併 用できません。 第 5 章 高度な SELECT 文の作成 123 外部結合の構文の詳細については、「IBM Informix: SQL ガイド: 構文」を参照して ください。 外部結合構文の Informix 拡張 外部結合構文の Informix 拡張は、外部結合をキーワード OUTER で始めます。 Informix 構文を使用する場合は、結合条件を必ず WHERE 節に含めるようにしてく ださい。外部結合に Informix 構文を使用する場合、 データベース サーバがサポー トする外部結合の基本型は以下の 3 つです。 v 2 つの表の単純な外部結合 v 第 3 の表との単純な外部結合 v 第 3 の表に対する 2 つの表との外部結合 外部結合には、SELECT 節、FROM 節、および WHERE 節がある必要がありま す。結合条件は、WHERE 節に記述されます。単純結合を外部結合に変換する場合 は、キーワード OUTER を、FROM 節の従属表名の直前に挿入します。後述するよ うに、キーワード OUTER は問合せに何回でも指定できます。 外部結合構文の Informix 拡張は、ANSI 右外部結合と同じです。 ANSI 結合構文 以下の ANSI 結合がサポートされます。 v 左外部結合 Dynamic Server v 右外部結合 Dynamic Server の終り ANSI 外部結合構文では、外部結合をキーワード LEFT JOIN、LEFT OUTER JOIN、RIGHT JOIN、または RIGHT OUTER JOIN で始めます。キーワード OUTER はオプションです。問合せでは、ON 節に結合条件と結合フィルタを指定で きます。WHERE 節には、ポスト結合フィルタを指定します。また、LEFT または RIGHT 節を使用して、結合の型を明示的に指定できます。さらに、ANSI 結合構文 では、外部結合の主部または従属部を、左括弧で始まる他の結合の結果セットとし て使用しすることができます。 ANSI を外部結合に使用する場合は、同じ照会ブロックのすべての外部結合に ANSI 構文を使用してください。 ヒント: ここで説明する例では、記述を簡単にするために表の別名を使用していま す。表の別名については、64 ページの『別名の使用』を参照してくださ い。 左外部結合 左外部結合の構文では、外部結合の主表が、外部結合の最初のキーワードの左に表 示されます。左外部結合は、結合条件を満たしたすべての行を戻します。また、主 表の他の行もすべて戻し、従表の対応する値を NULL として表示します。 124 IBM Informix: SQL ガイド: チュートリアル 次の問合せでは ANSI 構文 LEFT OUTER JOIN を使用しています。これは、 Informix 外部結合構文を使用した127 ページの図 291と同じ結果を戻します。 SELECT c.customer_num, c.lname, c.company, c.phone, u.call_dtime, u.call_descr FROM customer c LEFT OUTER JOIN cust_calls u ON c.customer_num = u.customer_num 図 285. 問合せ この例では、ON 節を使用して、結合条件を指定できます。また、WHERE に別の フィルタを追加し、結果セットを制限できます。この場合のフィルタはポスト結合 フィルタです。 次の問合せでは、カスタマ サービスに電話していない顧客の行のみを戻します。こ の問合せでは、表 customer および表 cust_calls の列 customer_num を外部結 合してから、WHERE 節のフィルタを適用します。 SELECT c.customer_num, c.lname, c.company, c.phone, u.call_dtime, u.call_descr FROM customer c LEFT OUTER JOIN cust_calls u ON c.customer_num = u.customer_num WHERE u.customer_num IS NULL 図 286. 問合せ 上述の例以外にも、ANSI 結合構文を使用して、以下のような問合せを作成できま す。 SELECT * FROM (t1 LEFT OUTER JOIN (t2 LEFT OUTER JOIN t3 ON t2.c1=t3.c1) ON t1.c1=t3.c1) JOIN (t4 LEFT OUTER JOIN t5 ON t4.c1=t5.c1) ON t1.c1=t4.c1; SELECT * FROM (t1 LEFT OUTER JOIN (t2 LEFT OUTER JOIN t3 ON t2.c1=t3.c1) ON t1.c1=t3.c1) , (t4 LEFT OUTER JOIN t5 ON t4.c1=t5.c1) WHERE t1.c1 = t4.c1; SELECT * FROM (t1 LEFT OUTER JOIN (t2 LEFT OUTER JOIN t3 ON t2.c1=t3.c1) ON t1.c1=t3.c1) LEFT OUTER JOIN (t4 JOIN t5 ON t4.c1=t5.c1) ON t1.c1=t4.c1; SELECT * FROM t1 LEFT OUTER JOIN (t2 LEFT OUTER JOIN t3 ON t2.c1=t3.c1) ON t1.c1=t2.c1; SELECT * FROM t1 LEFT OUTER JOIN (t2 LEFT OUTER JOIN t3 ON t2.c1=t3.c1) ON t1.c1=t3.c1; SELECT * FROM (t1 LEFT OUTER JOIN t2 ON t1.c1=t2.c1) LEFT OUTER JOIN t3 ON t2.c1=t3.c1; SELECT * FROM (t1 LEFT OUTER JOIN t2 ON t1.c1=t2.c1) LEFT OUTER JOIN t3 ON t1.c1=t3.c1; 第 5 章 高度な SELECT 文の作成 125 SELECT * FROM t9, (t1 LEFT JOIN t2 ON t1.c1=t2.c1) , (t3 LEFT JOIN t4 ON t3.c1=10), t10, t11 , (t12 LEFT JOIN t14 ON t12.c1=100); 右外部結合 (IDS のみ) 右外部結合の構文では、外部結合の主表が、外部結合の最初のキーワードの右に表 示されます。右外部結合は、結合条件を満たしたすべての行を戻します。また、主 表の他の行もすべて戻し、従表の対応する値を NULL として表示します。 図 287 は、 表 customer と表 orders の右外部結合の例です。 SELECT c.customer_num, c.fname, c.lname, o.order_num, o.order_date, o.customer_num FROM customer c RIGHT OUTER JOIN orders o ON (c.customer_num = o.customer_num); 図 287. 問合せ 図 287 は、主表 orders のすべての行を戻し、従表 customer の対応する値を NULL として表示します。 customer_num fname lname order_num 104 Anthony Wiggins 1001 101 Ludwig Pauli 1002 104 Anthony Wiggins 1003 <NULL> <NULL> <NULL> 1004 order_date customer_num 05/30/1998 104 05/30/1998 101 05/30/1998 104 06/05/1998 106 図 288. 問合せ結果 WHERE に別のフィルタを追加し、結果セットを制限できます。この場合のフィル タはポスト結合フィルタです。 単純結合 図 289 は、表 customer と表 cust_calls の単純結合の例です。 SELECT c.customer_num, c.lname, c.company, c.phone, u.call_dtime, u.call_descr FROM customer c, cust_calls u WHERE c.customer_num = u.customer_num 図 289. 問合せ 図 289 は、図 290 が示しているように、カスタマ サービスに顧客が電話した行の みを戻します。 126 IBM Informix: SQL ガイド: チュートリアル customer_num lname company phone call_dtime call_descr . . . customer_num lname company phone call_dtime call_descr 106 Watson Watson & Son 415-389-8789 1998-06-12 08:20 Order was received, but two of the cans of ANZ tennis balls within the case were empty 116 Parmelee Olympic City 415-534-8822 1997-12-21 11:24 Second complaint from this customer! Received two cases right-handed outfielder gloves (1 HRO) instead of one case lefties. 図 290. 問合せ結果 2 つの表の単純な外部結合 図 291 は、前の例と同じ選択リスト、表、および比較条件を使用していますが、今 度は単純な外部結合を Informix 拡張構文で作成します。 SELECT c.customer_num, c.lname, c.company, c.phone, u.call_dtime, u.call_descr FROM customer c, OUTER cust_calls u WHERE c.customer_num = u.customer_num 図 291. 問合せ 表 cust_calls の前にキーワード OUTER を挿入することで、これが従表になりま す。外部結合にすると、カスタマ サービスに電話したかどうかに関係なく、顧客全 員 に関する情報が戻されます。 図 292 に示すように、主表 customer のすべての 行が抽出され、従表 cust_calls の列に NULL 値が割り当てられます。 第 5 章 高度な SELECT 文の作成 127 customer_num 101 lname Pauli company All Sports Supplies phone 408-789-8075 call_dtime call_descr customer_num lname company phone call_dtime call_descr . . . customer_num lname company phone call_dtime call_descr 102 Sadler Sports Spot 415-822-1289 107 Ream Athletic Supplies 415-356-9876 customer_num 108 lname Quinn company Quinn’s Sports phone 415-544-8729 call_dtime call_descr 図 292. 問合せ結果 第 3 の表に対する単純結合との外部結合 ANSI 構文を使用した 図 293 には、第 3 の表に対する単純結合の結果としての外 部結合を示します。この第 2 のタイプの外部結合は、入れ子になった単純結合 と 呼ばれています。 SELECT c.customer_num, c.lname, o.order_num, i.stock_num, i.manu_code, i.quantity FROM customer c, LEFT OUTER JOIN (orders o, items i) WHERE c.customer_num = o.customer_num AND o.order_num = i.order_num AND manu_code IN (’KAR’, ’SHM’) ORDER BY lname 図 293. 問合せ 図 293 は、最初に表 orders と表 items に対して単純結合を実行して、列 manu_code (メーカー コード) の値が KAR または SHM である品目のすべての 注文についての情報を抽出します。次に外部結合を実行して、この情報を主表 customer のデータと結合します。オプションの ORDER BY 節を使用して、デー タを図 294 に示す形に再編成します。 128 IBM Informix: SQL ガイド: チュートリアル customer_num lname order_num stock_num manu_code quantity 114 Albertson 118 Baxter 113 Beatty .. . 105 Vector 121 Wallack 106 Watson 1018 302 KAR 3 図 294. 問合せ結果 第 3 の表に対する 2 つの表の外部結合 Informix 構文を使用した 図 295 には、第 3 の表に対する 2 つの表それぞれの外 部結合の結果を示します。この第 3 のタイプの外部結合では、結合関係は主表と従 表との間でのみ 成立します。 SELECT c.customer_num, c.lname, o.order_num, order_date, call_dtime FROM customer c, OUTER orders o, OUTER cust_calls x WHERE c.customer_num = o.customer_num AND c.customer_num = x.customer_num ORDER BY lname INTO TEMP service 図 295. 問合せ 図 295 は、従表 ordersと cust_calls を主表 customer に個別に結合します。2 つの従表同士は結合しません。 INTO TEMP 節は、結果を一時表に格納し、さらに 操作または問合せを実行できるようにします。図 296 に例を示します。 customer_num lname 114 118 113 103 115 Albertson Baxter Beatty Currie Grant 117 105 121 106 106 Sipes Vector Wallack Watson Watson order_num order_date call_dtime 1010 06/17/1998 .. . 1012 06/18/1998 1018 07/10/1998 1998-07-10 14:05 1004 05/22/1998 1998-06-12 08:20 1014 06/25/1998 1998-06-12 08:20 図 296. 問合せ結果 図 297 が示すように、図 295 で 2 つの従表 o と x の間に結合条件を作成しよう とすると、エラー メッセージが戻されて、両面外部結合の作成が示されます。 WHERE o.customer_num = x.customer_num 図 297. 問合せ 第 5 章 高度な SELECT 文の作成 129 外部結合を組み合わせる結合 複数レベルの入れ子を達成するために、3 種類の外部結合のどの組合せの結合も作 成できます。 図 298 では、ANSI を使用して、2 つの表の単純な外部結合と 2 番 目の外部結合の組合せの結果である結合を作成しています。 SELECT c.customer_num, c.lname, o.order_num, stock_num, manu_code, quantity FROM customer c, OUTER (orders o, OUTER items i) WHERE c.customer_num = o.customer_num AND o.order_num = i.order_num AND manu_code IN (’KAR’, ’SHM’) ORDER BY lname 図 298. 問合せ 図 298 は、最初に表 orders と表 items に対して外部結合を実行して、列 manu_code の値が KAR または SHM である品目のすべての注文についての情報 を抽出します。次に外部結合を実行して、この情報を主表 customer のデータと結 合します。 customer_num lname 114 118 113 103 115 Albertson Baxter Beatty Currie Grant 117 117 105 121 106 106 Sipes Sipes Vector Wallack Watson Watson order_num stock_num manu_code quantity 1010 .. . 1012 1007 1018 1014 1004 302 KAR 3 図 299. 問合せ結果 外部結合を第 3 の表との外部結合の結果に適用する場合、結合条件を 2 つの方法 で指定できます。 2 つの従表が結合されますが、主表と従表が共通列を共有してい る場合、その結果に影響を与えることなくどちらの従表にも主表を結合することが できます。 SELECT 文の副問合せ データベース サーバでサポートされる副問合せの種類は、次の状況で定義されま す。 v 別の SELECT 文の SELECT リストに入れ子になった SELECT 文 v 別の SELECT 文の WHERE 節 (または INSERT、DELETE、または UPDATE 文) に入れ子になった SELECT 文 各副問合せには、SELECT 節および FROM 節を指定します。副問合せは、相関 で ある場合と、無相関 である場合があります。副問合せ (または内部 SELECT 文) 130 IBM Informix: SQL ガイド: チュートリアル によって生成される値が、この値を囲む外部 SELECT 文の値によって決定される場 合、この副問合せは相関です。それ以外の副問合せはすべて、非相関副問合せで す。 相関副問合せの重要な特徴は、相関副問合せは外側の SELECT 文の値に依存してい るため、外側の SELECT 文が作成するすべての値に対して 1 回ずつ、繰り返し実 行しなければならないという点です。非相関副問合せは 1 回しか実行されません。 2 つの異なる SELECT 文の代わりに、副問合せを含む SELECT 文を構築すること ができます。 SELECT 文内で副問合せを使用することで、以下のアクションを実行できます。 v 式を、別の SELECT 文の結果と比較する。 v 他の SELECT 文の結果に式が含まれるかどうか判別する。 v 他の SELECT 文が行を選択するかどうか判別する。 オプションの WHERE 節は、探索条件を狭めるために使用されることがよくありま す。 副問合せは値を取り出して、その値を最初の SELECT 文か外側の SELECT 文に戻 します。副問合せには、値を 1 つも戻さない、1 つの値を戻す、または、1 組の値 を戻す場合があります。以下にそれぞれの場合を説明します。 v 副問合せが値を戻さない 場合、その問合せでは行を戻しません。このような副問 合せは NULL 値と同じです。 v 副問合せが値を 1 つ戻す場合、値のフォームは 1 つの集計式または 1 つの行と 1 つの列になります。このような副問合せは単一の数値か文字値と同じです。 v 副問合せが値のリストまたはセット を戻す場合、それらの値は 1 つの行または 1 つの列を表します。 選択リストの副問合せ 副問合せは別の SELECT 文の選択リストで使用できます。 図 300 では、選択リス トの中で副問合せを使用して、表 customer の各顧客について (表 orders から) 合計出荷費用を戻す方法を示しています。この問合せは、3 つの表の結合として作 成することもできます。 SELECT customer.customer_num, (SELECT SUM(ship_charge) FROM orders WHERE customer.customer_num = orders.customer_num) AS total_ship_chg FROM customer 図 300. 問合せ 第 5 章 高度な SELECT 文の作成 131 customer_num total_ship_chg 101 102 103 104 105 $15.30 123 124 125 126 127 128 $8.50 $12.00 $38.00 . . . $13.00 $18.00 図 301. 問合せ結果 WHERE 節の中の副問合せ ここでは、別の SELECT 文の WHERE 節に入れ子 になった SELECT 文として実 行される副問合せについて説明します。 次のキーワードは、SELECT 文内の WHERE 節内に副問合せを導入します。 v ALL v ANY v IN v EXISTS ALL および ANY に任意の関係演算子を使用すると、特定の値を、副問合せが生成 するすべての値と比較したり (ALL)、副問合せが生成するいずれかの値と比較する (ANY) ことができます。 ANY の代わりにキーワード SOME を使用することがで きます。演算子 IN は = ANY と同等です。反対の探索条件を作成するには、キー ワード NOT か他の関係演算子を使用してください。 演算子 EXISTS は、副問合せをテストして、何らかの値が戻されたかを確認しま す。つまり、副問合せの結果が NULL でないかどうかを調べます。テキスト (TEXT) 型またはバイト (BYTE) 型の列を含む副問合せには、キーワード EXISTS を使用できません。 副問合せでの条件の作成に使用する構文については、「IBM Informix: SQL ガイド: 構文」を参照してください。 ALL の使用 副問合せが戻すどの値についても比較が TRUE であるかどうかを判定するには、副 問合せの前にキーワード ALL を指定します。副問合せが値を戻さない場合の探索 条件は TRUE です。副問合せが値を戻さない場合は、条件は、すべてのゼロ値に関 して TRUE になります。 132 IBM Informix: SQL ガイド: チュートリアル 図 302 は、注文番号が 1023 である注文に含まれる全品目の合計金額よりも合計金 額が少ない品目を検出して、その品目を含むすべての注文についての情報を取り出 します。 SELECT order_num, stock_num, manu_code, total_price FROM items WHERE total_price < ALL (SELECT total_price FROM items WHERE order_num = 1023) 図 302. 問合せ order_num stock_num manu_code total_price 1003 1005 1006 1010 1013 1013 1018 9 6 6 6 5 6 302 ANZ SMT SMT SMT ANZ SMT KAR $20.00 $36.00 $36.00 $36.00 $19.80 $36.00 $15.00 図 303. 問合せ結果 ANY の使用 副問合せが戻す値の少なくとも 1 つについて比較条件が TRUE であることを判定 するには、副問合せの前にキーワード ANY (またはそのシノニム SOME)を指定し ます。副問合せが値を戻さない場合の探索条件は、FALSE です。値がなにも存在し ないため、その値の 1 つについて条件が TRUE になることはありません。 図 304 は、注文番号が 1005 である品目のいずれか 1 つ の合計価格よりも合計価 格が大きい品目を含む、すべての注文の注文番号を検索します。 SELECT DISTINCT order_num FROM items WHERE total_price > ANY (SELECT total_price FROM items WHERE order_num = 1005) 図 304. 問合せ 第 5 章 高度な SELECT 文の作成 133 order_num 1001 1002 1003 1004 .. . 1020 1021 1022 1023 図 305. 問合せ結果 一価副問合せ 副問合せが外部レベルの問合せに必ず 1 つ の値を戻すことがわかっている場合 は、キーワード ALL または ANY を指定する必要はありません。値を 1 つだけ戻 す副問合せは、関数として扱うことができます。このような副問合せでは、集計関 数を使用して値を 1 つ戻す副問合せが作成されます。 図 306 は、副問合せ内で集計関数 MAX を使用して、最大のバレーボール ネット 数を持つ注文の order_num を検索します。 SELECT order_num FROM items WHERE stock_num = 9 AND quantity = (SELECT MAX (quantity) FROM items WHERE stock_num = 9) 図 306. 問合せ order_num 1012 図 307. 問合せ結果 図 308 は、副問合せに集計関数 MIN を使用して、合計金額がその最小価格の 10 倍よりも多い品目を取り出します。 SELECT order_num, stock_num, manu_code, total_price FROM items x WHERE total_price > (SELECT 10 * MIN (total_price) FROM items WHERE order_num = x.order_num) 図 308. 問合せ 134 IBM Informix: SQL ガイド: チュートリアル order_num stock_num manu_code 1003 1018 1018 1018 8 307 110 304 ANZ PRC PRC HRO total_price $840.00 $500.00 $236.00 $280.00 図 309. 問合せ結果 相関副問合せ 図 310 は、表 orders から出荷日を日付の新しい順に 10 番目まで検出して戻す相 関副問合せの例です。副問合せ内には ORDER BY を指定することができないた め、この例では、副問合せの後に ORDER BY 節を配置して結果を並べ替えていま す。 SELECT po_num, ship_date FROM orders main WHERE 10 > (SELECT COUNT (DISTINCT ship_date) FROM orders sub WHERE sub.ship_date < main.ship_date) AND ship_date IS NOT NULL ORDER BY ship_date, po_num 図 310. 問合せ この副問合せが作成する数値は、外側の SELECT 文が作成する値 main.ship_date によって異なるため、これは相関副問合せです。したがって、この副問合せは外側 の SELECT 文が調べる各行について、1 回ずつ実行されなければなりません。 図 310 では、COUNT 関数を使用して、メインの問合せに値を戻しています。次 に、ORDER BY 節を使用してデータを並べ替えます。この問合せは、最新の 10 の 出荷日から 16 の行を検索して戻します。結果を図 311 に示します。 po_num ship_date 4745 278701 429Q 8052 B77897 LZ230 B77930 PC6782 DM354331 S22942 MA003 W2286 Z55709 C3288 KF2961 W9925 06/21/1998 06/29/1998 06/29/1998 07/03/1998 07/03/1998 07/06/1998 07/10/1998 07/12/1998 07/13/1998 07/13/1998 07/16/1998 07/16/1998 07/16/1998 07/25/1998 07/30/1998 07/30/1998 図 311. 問合せ結果 第 5 章 高度な SELECT 文の作成 135 図 310 のような相関副問合せを大規模な表に使用する場合は、列 ship_date にイ ンデックスを付けて効率を向上させる必要があります。これを行わない場合、この SELECT 文は、表の各行ごとに副問合せを 1 回ずつ実行するため、効率が低下する 可能性があります。インデックス付けとパフォーマンスに関する情報については、 「IBM Informix: 管理者ガイド」と「IBM Informix: パフォーマンス ガイド」を参照 してください。 EXISTS の使用 キーワード EXISTS は存在作用素 と呼ばれます。これは、図 312 に示すように、 外部 SELECT 文が行を少なくとも 1 つ検索した場合にのみ副問合せが TRUE にな るためです。 SELECT UNIQUE manu_name, lead_time FROM manufact WHERE EXISTS (SELECT * FROM stock WHERE description MATCHES ’*shoe*’ AND manufact.manu_code = stock.manu_code) 図 312. 問合せ 通常、IN を使用する問合せと同等の問合せを、EXISTS を使用して構築することが できます。 図 313 では、IN 述部を使用して、図 312 と同じ結果を戻す問合せを構 築しています。 SELECT UNIQUE manu_name, lead_time FROM stock, manufact WHERE manufact.manu_code IN (SELECT manu_code FROM stock WHERE description MATCHES ’*shoe*’) AND stock.manu_code = manufact.manu_code 図 313. 問合せ 図 312 と図 313 は両方とも、特定の種類の靴を製造するメーカーおよびこの製品の 注文に関するリード タイムの行を戻します。 図 314 に戻される値を示します。 manu_name lead_time Anza Hero Karsten Nikolus ProCycle Shimara 5 4 21 8 9 30 図 314. 問合せ結果 上述の問合せのいずれかと反対の検索条件を作成するには、キーワード NOT を IN または EXISTS に追加します。また、NOT IN の代わりに !=ALL を使用すること もできます。 図 315 で示すように、同じ操作を 2 つの方法で行うことができます。データベース の設計と表のサイズによって、一方の方法が他方よりもデータベース サーバに対す 136 IBM Informix: SQL ガイド: チュートリアル る負担が少ない場合があります。どちらの問合せが適切かを知るには、SET EXPLAIN コマンドを使用して問合せ計画のリストを表示してください。 SET EXPLAIN については、「IBM Informix: パフォーマンス ガイド」と 「IBM Informix: SQL ガイド: 構文」を参照してください。 SELECT customer_num, company FROM customer WHERE customer_num NOT IN (SELECT customer_num FROM orders WHERE customer.customer_num = orders.customer_num) SELECT customer_num, company FROM customer WHERE NOT EXISTS (SELECT * FROM orders WHERE customer.customer_num = orders.customer_num) 図 315. 問合せ 図 315 の文は両方とも、図 316 の結果を戻します。これは、注文をまだ行っていな い顧客を示します。 customer_num company 102 103 105 107 108 109 113 114 118 125 128 Sports Spot Phil’s Sports Los Altos Sports Athletic Supplies Quinn’s Sports Sport Stuff Sportstown Sporting Place Blue Ribbon Sports Total Fitness Sports Phoenix University 図 316. 問合せ結果 キーワード EXISTS および IN は、積 と呼ばれる集合演算に使用され、キーワー ド NOT EXISTS および NOT IN は、差 と呼ばれる集合演算に使用されます。こ れらの概念については、142 ページの『集合演算』で説明しています。 図 317 は、表 items に対して副問合せを実行し、まだ注文されていない表 stock 内のすべての品目を示します。 SELECT * FROM stock WHERE NOT EXISTS (SELECT * FROM items WHERE stock.stock_num = items.stock_num AND stock.manu_code = items.manu_code) 図 317. 問合せ 図 317 は、図 318 に示す行を戻します。 第 5 章 高度な SELECT 文の作成 137 stock_num manu_code description unit_price unit unit_descr 101 102 102 105 PRC SHM PRC PRC bicycle bicycle bicycle bicycle tires brakes brakes wheels $88.00 $220.00 $480.00 $53.00 box case case pair 4/box 4 sets/case 4 sets/case pair .. . 312 HRO 313 SHM 313 ANZ racer goggles swim cap swim cap $72.00 box $72.00 box $60.00 box 12/box 12/box 12/box 図 318. 問合せ結果 SELECT 文が持つことができる副問合せの数に論理的な制限はありませんが、どん な文のサイズも、文字列と見なされる場合には物理的に制限されます。しかし、こ の制限は通常作成する文の長さよりも長いため問題にはなり得ません。 データベースに情報が正しく入力されたか確認が必要な場合があります。データベ ース内のエラーを検出する方法の 1 つは、エラーが存在するときにのみ出力を戻す 問合せを作成することです。このタイプの副問合せは、一種の監査問合せ として機 能します。例を図 319 に示します。 SELECT * FROM items WHERE total_price != quantity * (SELECT unit_price FROM stock WHERE stock.stock_num = items.stock_num AND stock.manu_code = items.manu_code) 図 319. 問合せ 図 319 は、注文された品目の合計金額がその品目の単価と数量を掛けたものと一致 しない行のみを戻します。値引きが適用されていない場合、それらの戻された行 は、データベースに正しく入力されなかったと考えられます。この問合せでは、エ ラーが発生したときにのみ行を戻します。情報が正しくデータベースに挿入されて いれば、行は戻されません。 item_num order_num stock_num manu_code quantity total_price 1 2 1004 1006 1 HRO 5 NRG 1 5 $960.00 $190.00 図 320. 問合せ結果 SELECT 文でのコレクションの処理 (IDS のみ) データベース サーバでは、コレクション (COLLECTION) 型の式を処理するため に、次の SQL 機能が提供されています。 v コレクション (COLLECTION) 型の副問合せ を実行すると、副問合せの結果であ る仮想表がコレクション (COLLECTION) 型に変換されます。 コレクション (COLLECTION) 型の副問合せは、常にマルチセット (MULTISET) 型のコレクション (COLLECTION) 型データを戻します。コレクション 138 IBM Informix: SQL ガイド: チュートリアル (COLLECTION) 型の副問合せを使用すると、リレーショナル データの問合せ結 果をマルチセット (MULTISET) 型のコレクション (COLLECTION) 型データに変 換できます。コレクション (COLLECTION) 型の詳細については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。 v コレクション (COLLECTION) 型導出表 は、コレクションを仮想表に変換しま す。 コレクション (COLLECTION) 型の各要素は、コレクション (COLLECTION) 型 導出表の行として構築されます。コレクション (COLLECTION) 型導出表を使用 すると、個々のコレクション (COLLECTION) 型の要素にアクセスできます。 コレクション (COLLECTION) 型副問合せとコレクション (COLLECTION) 型導出 表は、反対の操作を行います。コレクション (COLLECTION) 型副問合せでは、関 係表の行の値をコレクション (COLLECTION) 型に変換しますが、コレクション (COLLECTION) 型導出表では、コレクション (COLLECTION) 型の要素を関係表の 行に変換します。 コレクション (COLLECTION) 型副問合せ コレクション (COLLECTION) 型の副問合せを使用すれば、副問合せの式からコレ クション (COLLECTION) 型の式を構築できます。コレクション (COLLECTION) 型の副問合せでは、キーワード MULTISET を副問合せの直前に指定し、マルチセ ット (MULTISET) 型コレクションに戻された値を変換します。ただし、キーワード MULTISET を副問合せ式の前で指定すると、基礎表の行は変更されずに、表の行の コピーのみが修正されます。例えば、コレクション (COLLECTION) 型を修正する ユーザ定義ルーチンにコレクション (COLLECTION) 型の副問合せを渡すと、コレ クション (COLLECTION) 型データのコピーは修正されますが基礎表は修正されま せん。 コレクション (COLLECTION) 型の副問合せ式は次のどのフォームでも使用できま す。 MULTISET(SELECT expression1, expression2... FROM tab_name...) または MULTISET(SELECT ITEM expression FROM tab_name...) コレクション (COLLECTION) 型の副問合せでのキーワード ITEM の省略 コレクション (COLLECTION) 型の副問合せの式でキーワード ITEM を省略する と、コレクション (COLLECTION) 型の副問合せはマルチセット (MULTISET) 型に なり、その要素の型は常に名前なし行 (unnamed row) 型になります。名前なし行 (unnamed row) 型のフィールドは、副問合せの射影リストに指定されている式と一 致します。 マルチセット (MULTISET) 型の列を含む次の表を作成すると仮定します。 CREATE TABLE tab2 ( id_num INT, ms_col MULTISET(ROW(a INT) NOT NULL) ) 第 5 章 高度な SELECT 文の作成 139 図 321 では、WHERE 節でコレクション (COLLECTION) 型副問合せを使用し、副 問合せが マルチセット (MULTISET) 型コレクションに戻す値 INT の行を変換しま す。この例では、表 tab2 の列 ms_col がコレクション (COLLECTION) 型副問合 せ式の結果に等しい場合に、行が戻されます。 SELECT id_num FROM tab2 WHERE ms_col = (MULTISET(SELECT int_col FROM tab1)) 図 321. 問合せ 図 321 では、コレクション (COLLECTION) 型副問合せのキーワード ITEM を省略 し、副問合せが戻す INT 値がマルチセット (MULTISET) 型 (ROW(a INT) NOT NULL) であり、tab2 の列 ms_col のデータ型と一致するようにします。 コレクション (COLLECTION) 型の副問合せでのキーワード ITEM の指定 副問合せの射影リストに 1 つの式が含まれている場合は、副問合せの射影リストの 前にキーワード ITEM を置いて、マルチセット (MULTISET) 型の要素の型が副問 合せの結果のデータ型と一致するよう指定できます。つまり、キーワード ITEM を 指定すると、射影リストの周囲に行ラッパが置かれません。例えば、(キーワード MULTISET の直後に続く) 副問合せが INT 値を戻す場合、そのコレクション (COLLECTION) 型副問合せはマルチセット (MULTISET) 型 (INT NOT NULL) で す。 マルチセット (MULTISET) 型 (INT NOT NULL) の引数を受け入れる関数 int_func() を作成すると仮定します。 図 322 に示すコレクション (COLLECTION) 型副問合せは、整数 (INT) 型値をマルチセット (MULTISET) 型に変換し、 int_func() の引数として使用されます。 EXECUTE FUNCTION int_func(MULTISET(SELECT ITEM int_col FROM tab1 WHERE int_col BETWEEN 1 AND 10)) 図 322. 問合せ 図 322 では、キーワード ITEM が副問合せで指定されているため、問合せが戻す値 int_col はコレクション (COLLECTION) 型の MULTISET (INT NOT NULL) に変 換されます。キーワード ITEM が指定されない場合、コレクション (COLLECTION) 型副問合せは マルチセット (MULTISET) 型 (ROW(a INT) NOT NULL) のコレクションを戻します。 コレクション (COLLECTION) 型副問合せの構文および制約事項の詳細について は、「IBM Informix: SQL ガイド: 構文」を参照してください。 コレクション (COLLECTION) 型導出表 コレクション (COLLECTION) 型導出表 を使用すると、コレクション (COLLECTION) 型の式の要素を仮想表の行として処理することができます。 SELECT 文の FROM 節でキーワード TABLE を使用し、コレクション 140 IBM Informix: SQL ガイド: チュートリアル (COLLECTION) 型導出表を作成できます。データベース サーバは、 SELECT、 INSERT、 UPDATE、および DELETE 文でのコレクション (COLLECTION) 型導出 表の使用をサポートします。 図 323 では、c_table という名前のコレクション (COLLECTION) 型導出表を使用 して、データベース superstores_demo の表 sales_rep の列 sales にある要素 にアクセスしています。列 sales は、売上情報を格納する month および amount フィールドを持つ、名前なし行 (unnamed row) 型のコレクションです。 図 323 で は、sales.amount が 98-03 の場合、sales.amount の要素を戻します。内部選択 は、それ自体が式であるため、外部問合せの反復ごとに 1 つの列の値以外戻すこと ができません。外側の SELECT 文は、表 sales_rep で評価する行数を指定しま す。 SELECT (SELECT c_table.amount FROM TABLE (sales_rep.sales) c_table WHERE c_table.month = ’98-03’) FROM sales_rep 図 323. 問合せ (expression) $47.22 $53.22 図 324. 問合せ結果 図 325 では、コレクション (COLLECTION) 型導出表を使用して、列 rep_num が 102 である sales コレクション型列の要素にアクセスします。コレクション (COLLECTION) 型導出表を使用して、表および列の別名を指定できます。コレクシ ョン (COLLECTION) 型導出表で表の名前が指定されていない場合は、データベー ス サーバによって自動的に作成されます。この例では、コレクション (COLLECTION) 型導出表 c_table について、導出列のリスト s_month および s_amount を指定します。 SELECT * FROM TABLE((SELECT sales FROM sales_rep WHERE sales_rep.rep_num = 102)) c_table(s_month, s_amount) 図 325. 問合せ s_month s_amount 1998-03 1998-04 $53.22 $18.22 図 326. 問合せ結果 図 327 では、コレクション (COLLECTION) 型導出表を作成しますが、導出表や導 出列の名前は指定していません。 図 327 は、図 325 と同じ結果を戻します。ただ 第 5 章 高度な SELECT 文の作成 141 し、導出列が表 sales_rep の列 sales のデフォルト フィールド名を想定している という点が異なります。 SELECT * FROM TABLE((SELECT sales FROM sales_rep WHERE sales_rep.rep_num = 102)) 図 327. 問合せ month amount 1998-03 1998-04 $53.22 $18.22 図 328. 問合せ結果 重要: コレクション (COLLECTION) 型導出表は読取り専用であるため、INSERT、 UPDATE、DELETE 文、あるいは更新可能なカーソルまたはビューの基礎表 のターゲット表としては指定できません。 コレクション (COLLECTION) 型導出表の構文および制約事項の説明は、 「IBM Informix: SQL ガイド: 構文」に記載されています。 集合演算 標準の集合演算である和集合、積、差 を使用することで、データベース情報を操作 することができます。この 3 つの演算では、更新、挿入または削除を実行した後に データベースの整合性をテストするために SELECT 文を使用します。これらの演算 は、例えばデータを履歴表に転送して、元の表からデータを削除する前に履歴表に 正しいデータが入っていることを確認する場合に便利です。 和集合 和集合は、キーワード UNION または演算子 を使用して、2 つの問合せを 1 つの 複合問合せ に結合します。キーワード UNION を複数の SELECT 文の間に使用す れば、それらを結合して 元の表の一部または全部に存在する行を含む一時表を作成 できます。ビューの定義の中で UNION 演算子を使用することもできます。 Dynamic Server 副問合せ内では、UNION 演算子を使用できません。 Dynamic Server では行 (ROW) 型へのソートがサポートされていません。和演算で は重複した値を削除するのにソートを必要とするため、和演算の問合せに行 (ROW) 型データが含まれていると UNION 演算子を使用できません。ただし、データベー ス サーバでは、行 (ROW) 型データに対してキーワード UNION ALL がサポート されていません。このデータ型の演算にはソートが必要ないためです。 Dynamic Server の終り 図 329 に、和集合演算を図解します。 142 IBM Informix: SQL ガイド: チュートリアル 図 329. 和集合演算 キーワード UNION は、2 つの問合せが取り出す行をすべて結合し、重複行を削除 して、残った行を戻します。問合せの結果は単一の結果に結合されるため、各問合 せでの選択対象の並びは、同じ数の列を持っていなければなりません。また、各表 から選択された対応する列には同じデータ型が含まれている必要なあり、さらに、 文字 (CHARACTER) 型の列は同じ長さである必要があります。また、これらの対応 する列では、すべてにおいて NULL が許可されるか、あるいは、すべてにおいて NULL が許可されないかのどちらかになります。 SELECT 文の構文と UNION 演算子については、「IBM Informix: SQL ガイド: 構 文」を参照してください。IBM Informix ESQL/C 製品固有の情報、および INTO 節 と複合問合せに関する制約事項については、「IBM Informix: ESQL/C Programmer’s Manual」を参照してください。 図 330 は、表 stock と表 items の列 stock_num と列 manu_code に対して和 集合演算を実行します。 SELECT DISTINCT stock_num, manu_code FROM stock WHERE unit_price < 25.00 UNION SELECT stock_num, manu_code FROM items WHERE quantity > 3 図 330. 問合せ 図 330 は、単価が $25.00 未満の品目、または注文数量が 4 以上の品目を選択し て、これらの品目の stock_num および manu_code をリストします。結果を図 331 に示します。 第 5 章 高度な SELECT 文の作成 143 stock_num manu_code 5 5 5 9 103 106 201 301 302 302 ANZ NRG SMT ANZ PRC PRC NKL KAR HRO KAR 図 331. 問合せ結果 UNION と ORDER BY の使用 図 332 に示すように、ORDER BY 節を記述する場合は、最後の SELECT 文の後に 指定してください。また、ソートする列の参照には、識別子ではなく整数を使用し てください。ソートは集合演算が完了した後で行われます。 SELECT DISTINCT stock_num, manu_code FROM stock WHERE unit_price < 25.00 UNION SELECT stock_num, manu_code FROM items WHERE quantity > 3 ORDER BY 2 図 332. 問合せ 図 332 の複合問合せは、図 330 と同じ行を選択しますが、表示される行は 図 333 に示すように製造者コード順に並べ替えられています。 stock_num manu_code 5 9 302 301 302 201 5 103 106 5 ANZ ANZ HRO KAR KAR NKL NRG PRC PRC SMT 図 333. 問合せ結果 UNION ALL の使用 キーワード UNION は、重複する行をデフォルトで除外します。重複した値を残す 場合は、オプションのキーワード ALL を図 334 に示すように追加します。 144 IBM Informix: SQL ガイド: チュートリアル SELECT stock_num, manu_code FROM stock WHERE unit_price < 25.00 UNION ALL SELECT stock_num, manu_code FROM items WHERE quantity > 3 ORDER BY 2 INTO TEMP stock item 図 334. 問合せ 図 334 は、キーワード UNION ALL を使用して 2 つ の SELECT文の和をとり、 最後の SELECT の後に INTO TEMP 節を追加して結果を一時表に格納します。こ れは図 332 と同じ行を戻しますが、重複値も含みます。 stock_num manu_code 9 5 9 5 9 ANZ ANZ ANZ ANZ ANZ 5 5 103 106 5 5 NRG NRG PRC PRC SMT SMT . . . 図 335. 問合せ結果 異なる列名の使用 複合問合せの場合は、選択リスト内の対応する列それぞれのデータ型に互換性がな ければなりませんが、同じ列名を使用する必要はありません。 図 336 は、表 customer から列 state を選択して、表 state から対応する列 code を選択します。 SELECT DISTINCT state FROM customer WHERE customer_num BETWEEN 120 AND 125 UNION SELECT DISTINCT code FROM state WHERE sname MATCHES ’*a’ 図 336. 問合せ 図 337 は、顧客番号が 120 から 125、または sname の末尾が a である州の州コ ードの省略形が戻されます。 第 5 章 高度な SELECT 文の作成 145 state AK AL AZ CA DE . . . SD VA WV 図 337. 問合せ結果 複合問合せでは、最初の SELECT 文に含まれる列名または表示ラベルが、問合せ結 果に使用されます。したがって、図 336 では、2 番目の SELECT 文からの列名 code の代わりに、最初の SELECT 文からの列名 state が使用されます。 複数の表に対する UNION の使用 図 338 は、3 つの表に関して和集合を実行します。結合できる表の最大数は、実際 に使用するアプリケーションやメモリ制限によって異なります。 SELECT stock_num, manu_code FROM stock WHERE unit_price > 600.00 UNION ALL SELECT stock_num, manu_code FROM catalog WHERE catalog_num = 10025 UNION ALL SELECT stock_num, manu_code FROM items WHERE quantity = 10 ORDER BY 2 図 338. 問合せ 図 338 は、表 stock 内の unit_price が $600 より大きいか、表 catalog 内の catalog_num が 10025 であるか、または表 items 内の quantity が 10 である品 目を選択して、manu_code 順に並べ替えます。 図 339 に、戻される値を示しま す。 stock_num manu_code 5 9 8 4 1 203 5 106 113 ANZ ANZ ANZ HSK HSK NKL NRG PRC SHM 図 339. 問合せ結果 146 IBM Informix: SQL ガイド: チュートリアル 選択リスト内でのリテラルの使用 図 340 では、選択リスト内にリテラルを使用し、和集合の部分の出力にタグを付け て、後で区別できるようにしています。タグには sortkey というラベルが与えられ ています。問合せは sortkey を使用して抽出された行を並び替えます。 SELECT ’1’ sortkey, lname, fname, company, city, state, phone FROM customer x WHERE state = ’CA’ UNION SELECT ’2’ sortkey, lname, fname, company, city, state, phone FROM customer y WHERE state <> ’CA’ INTO TEMP calcust; SELECT * FROM calcust ORDER BY 1 図 340. 問合せ 図 340 は、カリフォルニアからの顧客を最初に並べた 図 341 のようなリストを戻 します。 sortkey lname fname company city state phone 1 Baxter Dick Blue Ribbon Sports Oakland CA 415-655-0011 sortkey lname fname company city state phone . . . sortkey lname fname company city state phone 1 Beatty Lana Sportstown Menlo Park CA 415-356-9982 2 Wallack Jason City Sports Wilmington DE 302-366-7511 図 341. 問合せ結果 FIRST 節の使用 Extended Parallel Server では FIRST 節を使用して、ユニオン問合せに戻された最初 の行を選択できます。 図 342 では、FIRST 節を使用して、表 stock および表 items の和集合の最初の 5 行を戻します。 第 5 章 高度な SELECT 文の作成 147 SELECT FIRST 5 DISTINCT stock_num, manu_code FROM stock WHERE unit_price < 55.00 UNION SELECT stock_num, manu_code FROM items WHERE quantity > 3 図 342. 問合せ stock_num manu_code 5 5 6 6 9 NRG ANZ SMT ANZ ANZ 図 343. 問合せ結果 積 2 つの行のセットの積 をとると、元の表の両方に存在する行を含む表が作成されま す。 2 つのセットの積を示す副問合せを導入するには、キーワード EXISTS また は IN を使用します。 図 344 に、積集合演算を図解します。 図 344. 積集合演算 図 345 は、表 stock と表 items の積を示す入れ子になった SELECT 文の例で す。 図 346 には両方のセットに含まれるすべての要素が含まれており、以下の行を 戻します。 SELECT stock_num, manu_code, unit_price FROM stock WHERE stock_num IN (SELECT stock_num FROM items) ORDER BY stock_num 図 345. 問合せ 148 IBM Informix: SQL ガイド: チュートリアル stock_num manu_code unit_price 1 1 1 2 3 3 HRO HSK SMT HRO HSK SHM $250.00 $800.00 $450.00 $126.00 $240.00 $280.00 306 307 309 309 SHM PRC HRO SHM $190.00 $250.00 $40.00 $40.00 . . . 図 346. 問合せ結果 差 2 つの行セット間の差 をとると、最初のセットには存在するが 2 番目のセットに は存在しない行からなる表が生成されます。 2 つの集合間の差を示す副問合せを導 入するには、キーワード NOT EXISTS または NOT IN を使用します。 図 347 に、差集合演算を図解します。 図 347. 差集合演算 図 348 に示す入れ子になった SELECT 文は、表 stock と表 items の差を示しま す。 SELECT stock_num, manu_code, unit_price FROM stock WHERE stock_num NOT IN (SELECT stock_num FROM items) ORDER BY stock_num 図 348. 問合せ 図 349 には、17 行を戻す最初のセットのみのすべての要素が含まれています。 第 5 章 高度な SELECT 文の作成 149 stock_num manu_code unit_price 102 PRC 102 SHM 106 PRC $480.00 $220.00 $23.00 . . . 312 312 313 313 HRO SHM ANZ SHM $72.00 $96.00 $60.00 $72.00 図 349. 問合せ結果 サマリ この章は、第 2 章で紹介した概念に基づいて書かれたものです。リレーショナル データベースに対して問合せを行うためのより高度な SELECT 文について、構文と 結果の例を示しています。以下に、この章で説明した内容をまとめます。 v 集計関数とともに使用して行のグループを戻し、これらのグループに条件を適用 する GROUP BY 節および HAVING 節の紹介 v セルフ結合で表をそれ自体に結合し、同じ列内の他の値と比較して、重複行を識 別する方法についての説明 v 外部結合が複数の表を非対称に扱う方法に関する説明、および Informix 拡張と ANSI 結合構文を使用した 4 種類の外部結合の例示 v 他の SELECT 文の WHERE 節内で SELECT 文を入れ子にして相関および無相 関副問合せを作成する方法、および副問合せでの集計関数の使用方法の説明 v キーワード ALL、ANY、EXISTS、IN、および SOME を使用した副問合せの作 成、およびキーワード NOT または関係演算子を使用した場合の影響の説明 v リレーショナル データをコレクション (COLLECTION) 型のマルチセット (MULTISET) 型に変換するのに使用するコレクション (COLLECTION) 型副問合 せの使用方法、およびコレクション (COLLECTION) 型内の要素にアクセスする ためのコレクション (COLLECTION) 型導出表の使用方法についての説明 v 和、積、および差などの集合演算についての説明 v キーワード UNION および UNION ALL を使用して複数の SELECT 文から構成 される複合問合せを作成する方法の説明 150 IBM Informix: SQL ガイド: チュートリアル 第 6 章 データの変更 データベースの変更 . . . . . . . . . . . . . . . . . . . . . . . . . . . 行の削除 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 表のすべての行の削除 . . . . . . . . . . . . . . . . . . . . . . . . . TRUNCATE TABLE を使用したすべての行の削除 . . . . . . . . . . . . . . . . TRUNCATE TABLE を使用した上位表からの行の削除 . . . . . . . . . . . . . 指定された行の削除 . . . . . . . . . . . . . . . . . . . . . . . . . . 選択された行の削除 . . . . . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型を含む行の削除 (IDS のみ) . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型を含む行の削除 (IDS のみ) . . . . . . . . . . . . 上位表からの行の削除 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . 複雑な削除条件. . . . . . . . . . . . . . . . . . . . . . . . . . . . 削除結合の使用 (XPS のみ) . . . . . . . . . . . . . . . . . . . . . . . 行の挿入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 単一行. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . VALUES 節に指定できる値 . . . . . . . . . . . . . . . . . . . . . . 列値の制約事項. . . . . . . . . . . . . . . . . . . . . . . . . . . シリアル (SERIAL) 型 . . . . . . . . . . . . . . . . . . . . . . . . 特定の列名と値の指定 . . . . . . . . . . . . . . . . . . . . . . . . 型付き表への行の挿入 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型への挿入 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . 名前付き行 (named row) 型を含む行. . . . . . . . . . . . . . . . . . . . 名前なし行 (unnamed row) 型を含む行 . . . . . . . . . . . . . . . . . . . 行 (ROW) 型への NULL 値の指定 . . . . . . . . . . . . . . . . . . . . 上位表への行の挿入 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . 列へのコレクション (COLLECTION) 型値の挿入 (IDS のみ) . . . . . . . . . . . . 単純コレクション (COLLECTION) 型および入れ子コレクション (COLLECTION) 型への挿入 行 (ROW) 型を含むコレクション (COLLECTION) 型への NULL 値の挿入 . . . . . . . スマート ラージ オブジェクトの挿入 (IDS のみ) . . . . . . . . . . . . . . . . 複数の行の挿入および式の使用 . . . . . . . . . . . . . . . . . . . . . . INSERT 文に SELECT 文を使用する場合の制約. . . . . . . . . . . . . . . . . 行の更新 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 更新対象の行の選択 . . . . . . . . . . . . . . . . . . . . . . . . . . 一様値を使用する更新 . . . . . . . . . . . . . . . . . . . . . . . . . 更新の制限 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 選択値を使用する更新 . . . . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型の更新 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . 名前付き行 (named row) 型を含む行の更新 . . . . . . . . . . . . . . . . . 名前なし行 (unnamed row) 型を含む行の更新. . . . . . . . . . . . . . . . . 行 (ROW) 型のフィールドに対する NULL 値の指定 . . . . . . . . . . . . . . コレクション (COLLECTION) 型の更新 (IDS のみ) . . . . . . . . . . . . . . . 上位表の行の更新 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . . CASE 式による列の更新. . . . . . . . . . . . . . . . . . . . . . . . . SQL 関数を使用したスマート ラージ オブジェクトの更新 (IDS のみ) . . . . . . . . . 結合を使用した列の更新. . . . . . . . . . . . . . . . . . . . . . . . . データベースでのアクセス権 . . . . . . . . . . . . . . . . . . . . . . . . データベース レベル アクセス権. . . . . . . . . . . . . . . . . . . . . . 表レベル アクセス権 . . . . . . . . . . . . . . . . . . . . . . . . . . 表アクセス権の表示 . . . . . . . . . . . . . . . . . . . . . . . . . . データ整合性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . エンティティ保全性 . . . . . . . . . . . . . . . . . . . . . . . . . . © Copyright IBM Corp. 1996, 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 153 153 154 154 154 154 155 156 156 156 157 157 157 158 158 158 159 159 160 160 160 161 162 162 162 163 163 164 164 166 166 166 167 168 168 168 169 169 169 170 171 171 172 172 172 172 173 174 174 151 意味整合性 . . . . . . . . . . . . . . . . 参照整合性 . . . . . . . . . . . . . . . . ON DELETE CASCADE オプションの使用 . . . . カスケード削除中のロック . . . . . . . . . 複数の子表に対する影響. . . . . . . . . . ログ機能をオンにする必要性 . . . . . . . . カスケード削除の例 . . . . . . . . . . . . カスケード削除に対する制約 . . . . . . . . . オブジェクトモードと違反の検出. . . . . . . . . オブジェクト モードの定義 . . . . . . . . . 有効モード (IDS のみ) . . . . . . . . . . 停止モード (IDS のみ) . . . . . . . . . . フィルタ モード . . . . . . . . . . . . データ操作ステートメントのモード例 . . . . . . 制約が有効な場合の挿入操作の結果 . . . . . . 制約が無効な場合の挿入操作の結果 . . . . . . 制約がフィルタ モードの場合の挿入操作の結果 . . 1 つの違反行に対する複数の診断行 . . . . . . 違反表と診断表. . . . . . . . . . . . . . 違反表とデータベース オブジェクト モードの関係. START VIOLATIONS TABLE 文の例 . . . . . 名前を指定しない診断表の開始 . . . . . . . 名前を指定した違反表と診断表の開始 . . . . . 診断表の最大行数の指定. . . . . . . . . . 違反表に対するアクセス権の例 . . . . . . . 診断表に対するアクセス権の例 . . . . . . . 中断された変更. . . . . . . . . . . . . . . . トランザクション . . . . . . . . . . . . . . トランザクション ログ . . . . . . . . . . . . Extended Parallel Server のトランザクション ログ機能 ロギングおよびカスケード削除 . . . . . . . . トランザクションの指定. . . . . . . . . . . . Informix データベース サーバを使用したバックアップとログ 並行性およびロック . . . . . . . . . . . . . . IBM Informix データ レプリケーション (IDS のみ) . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 175 176 176 176 177 177 177 178 178 178 178 178 179 179 179 179 180 181 181 182 182 182 182 183 183 184 185 185 186 187 187 188 189 190 191 本章について この章では、データベース内のデータを変更する方法について説明します。データ の変更は、データの問合せとは基本的に異なるものです。データを問い合わせる場 合は、表の内容を調査しますが、データを変更する場合は、表の内容を変更 しま す。 データベースの変更 データを変更する文は、次のとおりです。 v DELETE v INSERT v UPDATE これらの SQL 文は、より高度な SELECT 文と比べると比較的単純ですが、データ ベースの内容を変更する文であるため、注意して使用してください。 152 IBM Informix: SQL ガイド: チュートリアル 問合せ中にシステムのハードウェアやソフトウェアに障害が発生した場合を考えて みます。この場合、アプリケーションには非常に大きい影響がありますが、データ ベース自体は被害を受けません。ただし、変更を行っている最中にシステムに障害 が発生すると、データベースの状態は不確かなものとなります。不確かな状態にあ るデータベースが、広範囲に影響を与えることは明らかです。データベースの行を 削除、挿入、または更新する前に、次の点を確認してください。 v データベースや表に対するユーザアクセス権の設定は適切か。つまり、特定のユ ーザに対してデータベースや表レベルのアクセス権が制限されているか。 v 変更されたデータは、データベースの既存の整合性を維持しているか。 v データベースを構築しているシステムは、システムやハードウェアの障害の原因 となり得る外部のイベントから十分保護されているか。 上記のそれぞれの項目に当てはまらなくても、問題ではありません。 Informix デー タベース サーバの機能を上手に利用すれば、これらの問題のすべてを解決すること ができます。この章では、データを変更する文を紹介した後、その解決策について 解説します。より詳細な説明は、「IBM Informix: データベース設計および実装 ガ イド」に記載されています。 行の削除 DELETE 文は、任意の行や行の組合せを表から削除します。トランザクションがコ ミットされた後は、削除した行は復旧できません。(トランザクションについては、 184 ページの『中断された変更』を参照してください。ここでは、トランザクショ ンは SQL 文と同じものとみなすことができます。) from という表から行を削除す る場合は、まず DELIMIDENT 環境変数を設定します。 行を削除する場合は、その削除する行に値が依存している他の表の行に対しても、 細心の注意を払って削除の操作を行わなければなりません。データベースが参照制 約を強制する場合は、CREATE TABLE 文または ALTER TABLE 文の ON DELETE CASCADE オプションを使用して、ある表から別の表への関係によって、 カスケード削除することができます。参照制約と ON DELETE CASCADE オプシ ョンについては、 175 ページの『参照整合性』を参照してください。 表のすべての行の削除 DELETE 文を使用するときは通常、表のどの行を削除するかを WHERE 節で指定 します。 WHERE 節を指定しない場合、すべての行が削除されます。次の文は実行 しないでください。 DELETE FROM customer DELETE 節には、FROM キーワードを含めずに使用することもできます。 DELETE customer これらの DELETE 文には WHERE 節が含まれていないため、表 customer 内の すべての行が削除されます。 DB–Access メニュー オプションを使用して無条件に 削除する場合は、警告および確認メッセージが表示されます。ただし、プログラム 中で無条件削除が指定されている場合は、この警告が表示されずに削除が実行され ます。 第 6 章 データの変更 153 TRUNCATE TABLE を使用したすべての行の削除 TRUNCATE TABLE 文を使用すると、表からすべての行を素早く削除できます。ま た、対応するインデックス データもすべて削除されます。トランザクションがコミ ットされた後は、削除した行を復旧できません。 TRUNCATE TABLE 文は、スマ ート ラージ オブジェクトを含む、いかなる型の列を含む表に対しても使用できま す。 TRUNCATE TABLE 文は、以下の理由で、DELETE 文よりも速く行を削除できま す。 v 表の切捨てでは、表の DELETE トリガを実行しない。トリガの使用に関して は、 333 ページの『第 12 章 トリガの作成と使用』 を参照してください。 v 切捨てを行う表の行ごとに論理ログを行わない。ロギングに関しては、185 ペー ジの『トランザクション ログ』を参照してください。 TRUNCATE TABLE 文を使用した場合の、パフォーマンスに対する影響について は、「IBM Informix: パフォーマンス ガイド」を参照してください。構文の詳細 は、「IBM Informix: SQL ガイド: 構文」を参照してください。 TRUNCATE TABLE を使用した上位表からの行の削除 階層の上位表に対して TRUNCATE TABLE 文を使用する場合は、キーワード ONLY により、その上位表のみに切捨てを実行するか、上位表とその副表に切捨て を実行するか指定できます。デフォルト (ONLY を使用しない) では、上位表とそ の副表のすべてが切捨ての対象になります。上位表 person を作成し、その下に 2 つの副表 employee および sales_rep を定義すると仮定します。次の TRUNCATE TABLE 文では、表 person、employee、および sales_rep から行を 削除します。 TRUNCATE TABLE person 上位表の行のみを削除する場合は、TRUNCATE TABLE 文でONLY キーワードを 使用します。例えば次の文では、表 person の行のみが削除されます。 TRUNCATE TABLE ONLY person 警告: TRUNCATE TABLE を使用して上位表の行を削除する場合は、ONLY キーワ ードを使用する場合を除き、その削除範囲に上位表とそのすべての副表が含 まれることに注意してください。 指定された行の削除 DELETE 文内の WHERE 節は、SELECT 文内の WHERE 節と同じフォームをして います。 WHERE 節を使用すると、どの行を削除するかを正確に指定できます。次 の例が示しているように、特定の顧客番号を持つ顧客を削除できます。 DELETE FROM customer WHERE customer_num = 175 この例では、列 customer_num が一意性制約を持っているため、複数の行が削除 されないことを保証できます。 選択された行の削除 また、次の例が示しているように、インデックスの付いていない列をベースにして いる行を選択することもできます。 154 IBM Informix: SQL ガイド: チュートリアル DELETE FROM customer WHERE company = ’Druid Cyclery’ テストされる列は一意性制約を持っていないため、この文は複数の行を削除する場 合があります。 Druid Cyclery は名前は同じで、顧客番号が異なる 2 つの店舗を持 っているかもしれません。 DELETE 文が影響を与える行数を知るには、Druid Cyclery の表 customer から修 飾行のカウント数を選択します。 SELECT COUNT(*) FROM customer WHERE company = ’Druid Cyclery’ また、行を選択して表示し、削除する行であることを確認することもできます。 ただし、複数のユーザが並行して使用できるデータベースの場合、SELECT 文を使 用するテストの結果はおおよそのものでしかありません。 SELECT 文を実行してか ら次に DELETE 文を実行するまでの間に、行を削除しようとしている表に他のユー ザが操作を加えた可能性があるからです。この例の場合、他のユーザが次の操作を する可能性があります。 v Druid Cyclery という名前で顧客番号が異なる別の顧客の行を、表に挿入する。 v 行を挿入する前に 1 つ以上の Druid Cyclery の行を削除する。 v Druid Cyclery の行を別の新しい会社名に更新したり、あるいは他の顧客の行の会 社名を Druid Cyclery に更新したりする。 この短い時間に他のユーザがこれらの操作を行う可能性は非常に低いものですが、 その可能性がまったくないわけではありません。この問題は、UPDATE 文にも影響 を与えます。この問題に対する処置については、 189 ページの『並行性およびロッ ク』に記載しています。より詳細な説明が必要な場合は、 235 ページの『第 10 章 マルチユーザ環境のためのプログラミング』を参照してください。 発生し得るもう 1 つの問題は、この文が終了する前にハードウェア障害またはソフ トウェア障害が発生することです。このような障害が発生すると、データベースが まったく行を削除しなかったか、いくつかの行を削除したか、または指定されたす べての行を削除したかがわからなくなります。データベースの状態 は不明であり、 この状況は望ましくありません。このような状態を避けるには、184 ページの『中 断された変更』で説明されているように、トランザクション ログ機能を使用しま す。 行 (ROW) 型を含む行の削除 (IDS のみ) 行 (ROW) 型に対して定義された列が行に含まれる場合は、ピリオド表記を使用し て、特定のフィールド値を含む行のみが削除されるように指定することができま す。例えば、次の文によって削除されるのは、表 employee で、列 address のフ ィールド city の値が San Jose である行のみです。 DELETE FROM employee WHERE address.city = ’San Jose’ 前の文では、列 address は、名前付き行 (named row) 型または名前なし行 (unnamed row) 型です。行 (ROW) 型のフィールド値を指定する構文は同じです。 第 6 章 データの変更 155 コレクション (COLLECTION) 型を含む行の削除 (IDS のみ) コレクション (COLLECTION) 型に定義された列が行に含まれる場合は、コレクシ ョン (COLLECTION) 型内の特定の要素を検索し、その要素を検出した行を削除す ることができます。例えば、次の文は、Baker という要素を持つコレクションが列 direct_reports に存在する場合、その列を含む行を削除します。 DELETE FROM manager WHERE ’Baker’ IN direct_reports 上位表からの行の削除 (IDS のみ) ある上位表の行を削除する場合、削除する範囲は上位表およびその副表になりま す。上位表 person を作成し、その下に 2 つの副表 employee および sales_rep を定義すると仮定します。表 person に対する次の DELETE 文を実行すると、表 person、表 employee、および表 sales_rep のすべてから行を削除することがで きます。 DELETE FROM person WHERE name =’Walker’ 上位表の行のみを削除する場合は、DELETE 文で ONLY キーワードを使用しま す。例えば次の文では、表 person の行のみが削除されます。 DELETE FROM ONLY(person) WHERE name =’Walker’ 警告: 上位表から行を削除する場合は、その削除範囲に上位表とそのすべての副表 が含まれることに注意してください。 複雑な削除条件 DELETE 文内の WHERE 節は、SELECT 文内の場合と同じくらい複雑になること があります。この文には、複数の条件を AND および OR で接続して指定するか、 副問合せを指定することができます。 表 stock に間違ったメーカー コードの行が含まれていることを検出した場合を考 えます。それらの行を更新するのではなく、削除してから再入力すると仮定しま す。正しい行とは異なり、これらの行は表 manufact に一致する行がありません。 これらの誤った行が表 manufact に一致する行を持っていないことから、次の例の ように DELETE 文を書くことができます。 DELETE FROM stock WHERE 0 = (SELECT COUNT(*) FROM manufact WHERE manufact.manu_code = stock.manu_code) この文に含まれている副問合せ文は、表 stock のメーカー コードと一致する値を 持つ表 manufact の行の数をキーワード COUNT(*) で取り出します。副問合せは 表 stock の各行に対して行われるため、この値はメーカー コードが正しい場合は 1、正しくない場合は 0 になります。 ヒント: DELETE 文を複雑な条件で使用する方法の 1 つは、削除する行のみを正確 に戻す SELECT 文を最初に使用することです。この文は SELECT * のよう に記述します。この文が目的の行セットを戻す場合は、SELECT * を DELETE に変更して、もう 1 度実行します。 156 IBM Informix: SQL ガイド: チュートリアル DELETE 文の WHERE 節では、同じ表をテストする副問合せを使用することがで きません。 つまり、表 stock の行を削除する場合は、WHERE 節内で、 stock の 行を選択する副問合せを使用できません。 このルールの重要な点は FROM 節にあります。表の名前が DELETE 文の FROM 節で指定されている場合は、この名前を DELETE 文の副問合せの FROM 節に使用 することができません。 削除結合の使用 (XPS のみ) Extended Parallel Server では、WHERE 節に副問合せを記述する代わりに削除結合 を使用することができます。この削除結合によってさまざまな表の行を結合し、結 合結果に基づいてそれらの行をターゲット表から削除できます。 上記の例にあるように、表 stock のいくつかの行に間違ったメーカー コードが含 まれているのを検出した場合を考えます。それらの行を更新するのではなく、削除 してから再入力すると仮定します。その場合には、次の例にあるような削除結合問 合せを使用することができます。 DELETE FROM stock USING stock, manufact WHERE stock.manu_code != manufact.manu_code 結合される表はすべて、USING 節に表示される必要があります。ターゲット表につ いては、結合に使用されない場合でも、using 節に表示される必要があります。削除 結合の詳細については、「IBM Informix: SQL ガイド: 構文」の DELETE 文の説明 を参照してください。 行の挿入 INSERT 文は、1 つ以上の新しい行を表に追加します。この文には、2 つの基本的 な機能があります。列の値を指定して単一の新しい行を作成することができます。 また、他の表から選択したデータを使用して複数の新しい行を作成することもでき ます。 単一行 もっとも簡単な形式の INSERT 文は、VALUES 節に列の値の並びを 1 行記述し、 それを表に追加するものです。次の文に、表 stock に行を追加する方法を示しま す。 INSERT INTO stock VALUES (115, ’PRC’, ’tire pump’, 108, ’box’, ’6/box’) 表 stock の各列を以下に示します。 v stock_num (商品の型を示す取扱品目番号) v manu_code (表 manufact への外部キー) v description (商品の内容を示す品目内容) v unit_price (商品の単価である単価) v unit (商品の販売単位である最小販売単位) v unit_descr (販売単位表記である単位内容) 第 6 章 データの変更 157 上記の例の VALUES 節でリストされる値は、表 stockの列と 1 対 1 の対応関係 を持っています。 VALUES 節は、表の各列の名前とデータ型、および順番がわか っていないと正確に記述することはできません。 VALUES 節に指定できる値 VALUES 節では定数値のみ を受け入れ、式を受け入れません。指定できる値は以 下のとおりです。 v リテラル番号 v リテラル日時 (DATETIME) 型値 v リテラル時間隔 (INTERVAL) 型値 v 引用符付き文字列または文字 v NULL 値を表す単語 NULL v 現在日付を表す単語 TODAY v 現在日時を表す単語 CURRENT v ユーザ名を表す単語 USER v データベース サーバが実行されているコンピュータ名を表す単語 DBSERVERNAME (または SITENAME) 列値の制約事項 表には、NULL が許可されない列が含まれている場合があります。このような列に NULL を挿入すると、拒否されます。また、表の列の中には、重複値が許可されてい ないものもあります。このような列の中にすでにある値と重複する値を指定する と、その文は拒否されます。列の中には、使用が許可されている列値でさえ制限 す るものがあります。列を制限するには、データ整合性制約を使用します。詳しく は、174 ページの『データ整合性』を参照してください。 金額 (MONEY) 型の値を含む列には、通貨記号を指定しないでください。金額を示 す数値のみを指定してください。 データベース サーバは、数値 (NUMERIC) 型と文字 (CHARACTER) 型の変換を実 行できます。数値 (numeric) 型列の値として、数値の文字列 (’-0075.6’など) を指定 することができます。データベース サーバは、この数値文字列を数値に変換するこ とができます。この文字列が数値を表していない場合に限り、エラーが発生しま す。 文字 (CHARACTER) 型列の値として、数値または日付を指定できます。データベー ス サーバは、その値を文字列に変換します。例えば、TODAY を文字 (CHARACTER) 型列の値として指定すると、現在の日付を表す文字列が使用されま す (使用される書式は、DBDATE 環境変数で指定されます)。 シリアル (SERIAL) 型 シリアル (SERIAL) 型 および 8 バイト シリアル (SERIAL8) 型 データを設定で きるのは、それぞれ表内の 1 つの列のみです。シリアル列の値は、データベース サーバによって生成されます。値を挿入する時に、シリアル列に値ゼロを指定しま す。データベース サーバは、次の実際の値を続けて生成します。シリアル型の列 は、NULL を許可しません。 158 IBM Informix: SQL ガイド: チュートリアル シリアル (SERIAL) 型の列に対しては、その列の既存の値と同じでない限り非ゼロ 値を指定することができ、データベース サーバはその値を使用します。この非ゼロ 値によって、データベース サーバが生成する値に新しい開始値が設定される場合が あります。(データベース サーバが生成する次の値は、列内の最大値より 1 大きい 値になります。) 特定の列名と値の指定 INSERT 文には、表のすべての列の値を指定する必要はありません。代わりに、表 名の後に列名をリストして、指定したそれらの列のみに値を指定することができま す。次の例では、表 stock に新しい行を挿入する文を示します。 INSERT INTO stock (stock_num, description, unit_price, VALUES (115, ’tyre pump ’, 114, ’SHM’) manu_code) 在庫番号、説明、単価およびメーカー コードのデータのみが提供されています。デ ータベース サーバは次のルールに従って、残りの列に値を提供します。 v リストされていないシリアル (SERIAL) 型の列の場合は、シリアル番号を生成し ます。 v 列に固有なデフォルト値が存在する場合は、その値を生成します。 v NULL を許可する列には NULL 値が生成されますが、デフォルト値として NULL を指定する列にはデフォルト値の指定は行われません。 つまり、デフォルト値を指定しない列や、NULL を許可しない列に対しては、必 ず値を指定する必要があります。 それらの列は、値が同じ順序でリストされる限りは、どんな順序でもリストできま す。列に対して NULL 値またはデフォルト値を指定する方法については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。 前例の INSERT 文が実行された後、次に示す新しい行が表 stock に挿入されま す。 stock_num manu_code 115 SHM description unit_price unit unit_descr tyre pump 114 unit と unit_descr はどちらも空白で、この 2 つの列に NULL があることを示し ます。列 unit は NULL を許可するため、$114 で購入できるタイヤ ポンプの数は 不明です。もちろん、box のデフォルト値がこの列に対して指定された場合は、box が販売単位になります。いずれにしても、表の特定の列に値を挿入する場合は、そ の行にどんなデータが必要であるかに注意を払ってください。 型付き表への行の挿入 (IDS のみ) 行 (ROW) 型に基づかない表に行を挿入する場合と同じ方法で、型付き表に行を挿 入することができます。 型付き表に行 (ROW) 型列が含まれる場合、つまり、型付き表を定義する名前付き 行 (named row) 型に入れ子の行 (ROW) 型が含まれる場合、その行 (ROW) 型列へ の行の挿入は、行 (ROW) 型に基づかない表の行 (ROW) 型列に挿入するのと同じ 方法で行います。 160 ページの『行 (ROW) 型への挿入 (IDS のみ)』では、行 (ROW) 型列への挿入の方法を説明します。 第 6 章 データの変更 159 ここでは、例に行 (ROW) 型 zip_t、address_t、および employee_t、そして型付 き表 employee を使用します。 図 350 に、行 (ROW) 型および表を作成する SQL 構文を示します。 CREATE ROW TYPE zip_t ( z_code CHAR(5), z_suffix CHAR(4) ); CREATE ROW TYPE address_t ( street VARCHAR(20), city VARCHAR(20), state CHAR(2), zip zip_t ); CREATE ROW TYPE employee_t ( name VARCHAR(30), address address_t, salary INTEGER ); CREATE TABLE employee OF TYPE employee_t; 図 350. 行 (ROW) 型への挿入 (IDS のみ) 次の構文規則は、名前付き行 (named row) 型または名前なし行 (unnamed row) 型に ついて定義される列への挿入に適用されます。 v ROW コンストラクタを挿入するフィールド値の前に指定します。 v 行 (ROW) 型のフィールド値を括弧で囲みます。 v 行式を適切な名前付き行 (named row) 型にキャストします (名前付き行 (named row) 型の場合)。 名前付き行 (named row) 型を含む行 次の文は、161 ページの図 351 の表 employee に行を挿入する方法を示します。 INSERT INTO employee VALUES (’Poole, John’, ROW(’402 High St’, ’Willits’, ’CA’, ROW(69055,1450))::address_t, 35000 ) 表 employee の列 address は名前付き行 (named row) 型なので、キャスト演算 子、および行 (ROW) 型の名前である address_t を使用して、address_t 型の値 を挿入する必要があります。 名前なし行 (unnamed row) 型を含む行 図 351 に示す表を作成すると仮定します。表 student は、列 s_address を名前 なし行 (unnamed row) 型として定義します。 160 IBM Informix: SQL ガイド: チュートリアル CREATE TABLE student ( s_name VARCHAR(30), s_address ROW(street VARCHAR (20), city VARCHAR(20), state CHAR(2), zip VARCHAR(9)), grade_point_avg DECIMAL(3,2) ); 図 351. 次の文は、表 student に行を追加する方法を示します。名前なし行 (unnamed row) 型列 s_address に挿入するには、行 (ROW) 型コンストラクタを使用しますが、 行 (ROW) 型値のキャストは行いません。 INSERT INTO student VALUES (’Keene, Terry’, ROW(’53 Terra Villa’, ’Wheeling’, ’IL’, ’45052’), 3.75) 行 (ROW) 型への NULL 値の指定 行 (ROW) 型列のフィールドには、NULL 値を含めることができます。 NULL 値 は、列またはフィールドのどちらのレベルでも指定することができます。 次の文では、列レベルで NULL 値を指定して、列 s_address のすべてのフィール ドに NULL 値を挿入します。列レベルで NULL 値を挿入する場合は、行 (ROW) 型コンストラクタを含めることができません。 INSERT INTO student VALUES (’Brauer, Howie’, NULL, 3.75) 行 (ROW) 型の特定のフィールドに NULL 値を挿入する場合は、行 (ROW) 型コン ストラクタを含める必要があります。次の INSERT 文は、表 employee の列 address の特定フィールドに NULL 値を挿入する方法を示しています。ここで、 列 address は、名前付き行 (named row) 型として定義されています。 INSERT INTO employee VALUES ( ’Singer, John’, ROW(NULL, ’Davis’, ’CA’, ROW(97000, 2000))::address_t, 67000 ) 行 (ROW) 型のフィールドに NULL 値を指定する場合、行 (ROW) 型が INSERT 文および UPDATE 文の実行、またはプログラム変数の代入によって発生するので あれば、NULL 値を明示的にキャストする必要はありません。 次の INSERT 文は、表 student の列 s_address のフィールド street および zip に NULL 値を挿入する方法を示しています。 INSERT INTO student VALUES( ’Henry, John’, ROW(NULL, ’Seattle’, ’WA’, NULL), 3.82 ) 第 6 章 データの変更 161 上位表への行の挿入 (IDS のみ) 上位表に行を挿入する場合、特別な注意事項はありません。 INSERT 文は、その文 で指定される表のみに適用されます。例えば次の文を実行すると、上位表に値が挿 入されますが、副表には挿入されません。 INSERT INTO person VALUES ( ’Poole, John’, ROW(’402 Saphire St.’, ’Elmondo’, ’CA’, ’69055’), 345605900 ) 列へのコレクション (COLLECTION) 型値の挿入 (IDS のみ) ここでは、DB–Access で列にコレクション (COLLECTION) 型値を挿入する方法を 説明します。個々の要素をコレクション (COLLECTION) 型列に挿入する方法につ いては説明しません。コレクションの個々の要素にアクセスまたは修正を加える場 合は、ESQL/C プログラムまたは SPL ルーチンを使用します。ESQL/C プログラム を作成してコレクションに挿入する方法については、「IBM Informix: ESQL/C Programmer’s Manual」を参照してください。SPL ルーチンを作成してコレクション に挿入する方法については、第 11 章を参照してください。 ここで示す例は、図 352 の表 manager に基づいています。表 manager には、単 純コレクション (COLLECTION) 型と、入れ子コレクション (COLLECTION) 型が 含まれています。 CREATE TABLE manager ( mgr_name VARCHAR(30), department VARCHAR(12), direct_reports SET(VARCHAR(30) NOT NULL), projects LIST(ROW(pro_name VARCHAR(15), pro_members SET(VARCHAR(20) NOT NULL)) NOT NULL) ); 図 352. 単純コレクション (COLLECTION) 型および入れ子コレクション (COLLECTION) 型への挿入 コレクション (COLLECTION) 型列を含む行に値を挿入する場合は、そのコレクシ ョン (COLLECTION) 型が含むすべての要素の値を、他の列の値と同様に挿入しま す。例えば次の文は、単一の行を表 manager に挿入します。この表には、単純コ レクション (COLLECTION) 型列と、入れ子コレクション (COLLECTION) 型列の 両方が含まれます。 INSERT INTO manager(mgr_name, department, direct_reports, projects) VALUES ( ’Sayles’, ’marketing’, "SET{’Simonian’, ’Waters’, ’Adams’, ’Davis’, ’Jones’}", LIST{ ROW(’voyager_project’, SET{’Simonian’, ’Waters’, 162 IBM Informix: SQL ガイド: チュートリアル ’Adams’, ’Davis’}), ROW (’horizon_project’, SET{’Freeman’, ’Jacobs’, ’Walker’, ’Smith’, ’Cannan’}), ROW (’saphire_project’, SET{’Villers’, ’Reeves’, ’Doyle’, ’Strongin’}) } ) 行 (ROW) 型を含むコレクション (COLLECTION) 型への NULL 値 の挿入 行 (ROW) 型であるコレクション (COLLECTION) 型に値を挿入するには、行 (ROW) 型の各フィールドに対して値を指定する必要があります。 一般に、コレクション (COLLECTION) 型では NULL 値は許可されていません。た だし、コレクション (COLLECTION) 型の要素の型が行 (ROW) 型である場合は、 行 (ROW) 型の個々のフィールドに NULL 値を挿入することができます。 空のコレクション (COLLECTION) 型を指定することもできます。空のコレクショ ン (COLLECTION) 型 は、要素を含みません。空のコレクション (COLLECTION) 型を指定するには、中括弧 ({}) を使用します。例えば次の文は、表 manager の行 にデータを挿入しますが、列 direct_reports および projects が空のコレクション (COLLECTION) 型になるように指定します。 INSERT INTO manager VALUES (’Sayles’, ’marketing’, "SET{}", "LIST{ROW(NULL, SET{})}" ) コレクション (COLLECTION) 型列に NULL の要素を含めることはできません。次 の文を実行するとエラーが戻されますが、これは、コレクション (COLLECTION) 型の要素として NULL 値が指定されているためです。 INSERT INTO manager VALUES (’Cole’, ’accounting’, "SET{NULL}", "LIST{ROW(NULL, ""SET{NULL}"")}" 次の構文規則は、コレクション (COLLECTION) 型に対して挿入または更新を行う 場合に適用されます。 v 中括弧 ({}) を使用して、各コレクション (COLLECTION) 型に含まれる要素を区 別します。 v コレクション (COLLECTION) 型が入れ子になっている場合は、中括弧 ({}) を使 用して、内部コレクション (COLLECTION) 型および外部コレクション (COLLECTION) 型両方の要素を区別します。 スマート ラージ オブジェクトの挿入 (IDS のみ) INSERT 文を使用してバイナリ ラージ オブジェクト (BLOB) 型または文字ラージ オブジェクト (CLOB) 型列にオブジェクトを挿入する場合、データベース サーバ は表ではなく、SB 領域に、そのオブジェクトを格納します。データベース サーバ には、INSERT 文の中から呼び出すことができ、スマート ラージオブジェクトとし て知られるバイナリ ラージ オブジェクト (BLOB) 型または文字ラージ オブジェ クト (CLOB) 型のデータをインポートまたはエクスポートできる 4 つの SQL 関数 があります。これらの関数については、97 ページを参照してください。 第 6 章 データの変更 163 次の INSERT 文では、 filetoblob() 関数および filetoclob() 関数を使用して、表 inmate の行を挿入します。 (表 inmate は、98 ページの図 216 で定義していま す。) INSERT INTO inmate VALUES (437, FILETOBLOB(’datafile’, ’client’), FILETOCLOB(’tmp/text’, ’server’)) この例では、FILETOBLOB() 関数と FILETOCLOB() 関数の最初の引数が、それぞ れ、表 inmate のバイナリ ラージ オブジェクト (BLOB) 型および文字ラージ オ ブジェクト (CLOB) 型列にコピーされるソース ファイルのパスを指定します。そ れぞれの関数の 2 番目の引数で、ソース ファイルがクライアント コンピュータ (’client’) とサーバ コンピュータ (’server’) のどちらに配置されているのかを示しま す。ファイル名のパスを関数の引数で指定する場合は、次のルールが適用されま す。 v ソース ファイルがサーバ コンピュータに存在する場合は、現在の作業ディレク トリへの相対パス名ではなく、そのファイルへのフルパス名を指定する必要があ ります。 v ソース ファイルがクライアント コンピュータに存在する場合は、そのファイル へのフルパス名または相対パス名のどちらでも指定することができます。 複数の行の挿入および式の使用 INSERT 文では、VALUES 節を SELECT 節に置き換えることもできます。この形 式の特徴は、次のようなデータを挿入できることです。 v 文が 1 つだけある複数の行。SELECT 文が 1 行を戻すたびに 1 行が挿入される v 計算値 (VALUES 節は定数のみを許可)。選択対象リストは式を含むことができる 例えば、決済は済んだが出荷が済んでいない注文について、出荷要求の電話連絡を 行う必要が生じたと仮定します。次の例の INSERT 文は、該当する注文を検出し、 各注文に対応する行を表 cust_calls に挿入します。 INSERT INTO cust_calls (customer_num, call_descr) SELECT customer_num, order_num FROM orders WHERE paid_date IS NOT NULL AND ship_date IS NULL この SELECT 文は 2 つの列を戻します。表 orders から選択された各行のこれらの 列のデータは、表 cust_calls の指定された列に挿入されます。次に、シリアル (SERIAL) 型の列 order_num からの注文番号が呼出し記述に挿入されますが、こ れは文字 (CHAR) 型の列です。整数値を文字 (CHAR) 型の列に挿入することは可 能です。データベース サーバが自動的にシリアル値を 10 進数の文字列に変換しま す。 INSERT 文に SELECT 文を使用する場合の制約 SELECT 文を使用して行を挿入する場合、以下の制約事項があります。 v INTO 節を使用できない。 v INTO TEMP 節を使用できない。 v ORDER BY 節を使用できない。 v 行を挿入する表を参照できない。 164 IBM Informix: SQL ガイド: チュートリアル Extended Parallel Server Extended Parallel Server では、INSERT SELECT 文に、ORDER BY 節を含む SELECT 文を使用できます。 Extended Parallel Server の終り INTO、INTO TEMP、および ORDER BY 節に関する制約事項は、マイナーなもの です。ただし、このコンテキストでは INTO 節はあまり役立ちません。 (詳しく は、第 8 章を参照してください。) INTO TEMP 節の制約を回避するには、まず、 一時表に挿入するデータを選択し、INSERT 文を使用して、そのデータを一時表か ら挿入します。同様に、ORDER BY 節を使用できないことも大きな問題ではありま せん。新しい行を表内で物理的に順序付ける必要がある場合は、まずこれらの行を 選択して一時表に入れて順序付け、次に一時表から挿入することができます。ま た、すべての挿入が完了した後でクラスタ化インデックスを使用し、物理的な順序 を表に適用することもできます。 重要: 最後制限により、INSERT 文の INTO 節と SELECT 文の FROM 節の両方に 同じ表を指定できなくなるため、この制限はより重要です。 INSERT 文の INTO 節と、SELECT 文の FROM 節に同じ表を指定すると、データベース サーバはエンドレス ループに陥り、挿入された各行の選択と挿入が繰り返さ れます。 しかし、データを挿入しなければならない表そのものから選択したい場合もありま す。例えば、Nikolus 社が Anza 社と同じ製品を半額で提供していることがわかった 場合を考えます。この 2 つの会社の相違を反映するために、表 stock に行を追加 したいと考えるでしょう。表 stock の行から Anza 社のすべてのデータを選択し、 それを Nikolus 社のメーカー コードで再び挿入するのが最良の方法です。しかし、 挿入対象の表から選択することはできません。 この制限を回避するには、一時表に挿入するデータを選択します。そして、次の例 に示すように、INSERT 文にあるその一時表から選択します。 SELECT stock_num, ’NIK’ temp_manu, description, unit_price/2 half_price, unit, unit_descr FROM stock WHERE manu_code = ’ANZ’ AND stock_num < 110 INTO TEMP anzrows; INSERT INTO stock SELECT * FROM anzrows; DROP TABLE anzrows; この SELECT 文は、表 stock から既存の行を取り出し、メーカー コードを定数値 で、単価を計算値で置き換えます。次に、これらの行を一時表 anzrows に保存し ます。これは、ただちに表 stock に挿入されます。 複数の行を挿入する場合は、1 行でも無効なデータが含まれていると、データベー ス サーバがエラーをレポートします。この種のエラーが発生すると、この文は早期 に終了します。たとえエラーが発生しない場合でも、この文の実行中にハードウェ アまたはソフトウェアの障害が発生する危険性が、非常に低いとはいえ存在しま す。例えば、ディスクがフルになる可能性があります。 第 6 章 データの変更 165 いずれの場合でも、新しい行が何行挿入されたかは簡単にはわかりません。文全体 を繰り返し実行すると、行が重複して作成されてしまうことがあるかもしれませ ん。データベースの状態がわからないため、対処方法も判断できません。この問題 を解決するには、トランザクションを使用します。184 ページの『中断された変 更』で説明します。 行の更新 表に含まれる既存の行の列の内容を変更するには、UPDATE 文を使用します。この 文には、基本的に異なる 2 つの形式があります。 1 つの形式では、特定の値を名 前によって列に割り当てることができます。もう 1 つの形式では、SELECT 文によ って戻される値の並びを列の並びに割り当てることができます。いずれの形式で も、行を更新している場合にいくつかの列にデータ整合性制約が設定されていれ ば、変更するデータはこれらの制約を満たすものでなければなりません。詳しく は、174 ページの『データ整合性』を参照してください。 更新対象の行の選択 UPDATE 文のいずれの書式も、末尾に、変更する行を決定する WHERE 節を指定 できます。 WHERE を省略した場合、すべての行が変更されます。変更が必要な行 セットを正確に選択する場合は、WHERE 節が非常に複雑になることがあります。 WHERE 節に対する唯一の制限は、更新中の表を副問合せ文の FROM 節の中では 指定できないということです。 UPDATE 文の最初の形式は、次の例が示しているように、一連の代入節を使用して 新しい列の値を指定します。 UPDATE customer SET fname = ’Barnaby’, lname = ’Dorfler’ WHERE customer_num = 103 WHERE 節で更新する行を選択します。デモンストレーション データベースでは、 列 customer.customer_num はその表の主キーであるため、この文で更新できる のは 1 行のみです。 WHERE 節では、副問合せも使用できます。 Anza 社がテニスボールの不良品を回 収する場合を考えます。その結果、次の例が示しているように、在庫番号 6 を含む メーカー ANZ からの未出荷の注文は、受注残に加えられなければなりません。 UPDATE orders SET backlog = ’y’ WHERE ship_date IS NULL AND order_num IN (SELECT DISTINCT items.order_num FROM items WHERE items.stock_num = 6 AND items.manu_code = ’ANZ’) この UPDATE 文の副問合せ文は、ゼロまたはいくつかの注文番号を戻します。 UPDATE 文は、表 orders の各行をこの注文番号と突き合わせ、その行の注文番号 が一致すれば更新を実行します。 一様値を使用する更新 キーワード SET の後の代入式は、列に新しい値を指定します。その値は、更新する どの行にも一様に適用されます。前の項の例では新しい値は定数でしたが、その列 166 IBM Informix: SQL ガイド: チュートリアル の値自体をベースにした式も含め、どんな式でも割り当てることができます。メー カー コード HRO がすべての価格を 5% 上げたため、この値上げを反映するため に、表 stock を更新しなければならないと仮定します。次の文を使用します。 UPDATE stock SET unit_price = unit_price * 1.05 WHERE manu_code = ’HRO’ 式の一部に副問合せ文を使用することもできます。式の一部として副問合せ文を使 用する場合、その文は値を 1 つだけ戻すものでなければなりません。1 つというの は、1 列からなる 1 行のみということです。おそらく、どの在庫番号に対しても、 その製品についてはどのメーカーよりも高い価格を付けなければならないことを決 定するでしょう。この場合、未出荷の注文すべてについて価格を更新しなければな りません。次の例では、SELECT 文で基準を指定します。 UPDATE items SET total_price = quantity * (SELECT MAX (unit_price) FROM stock WHERE stock.stock_num = items.stock_num) WHERE items.order_num IN (SELECT order_num FROM orders WHERE ship_date IS NULL) 最初の SELECT 文は、特定の製品に関して表 stock 内で最も高い価格を表す値を 1 つ戻します。最初の SELECT 文は、相関副問合せです。これは、最初の SELECT 文の WHERE 節に表 items の値が現れたときに、更新対象の行ごとにそ れを実行する必要があるためです。 2 つ目の SELECT 文は、未出荷の注文の注文番号を取り出します。この SELECT 文は非相関副問合せ文のため、1 回実行されるのみです。 更新の制限 データを変更する場合の副問合せ文の使用については、いくつかの制限がありま す。特に重要なのは、変更されている表に対しては問合せができないことです。列 unit_price を 5% 増加させた例のように、列の現在の値を式の中で参照することが できます。表 stock を更新する例 (表 items を更新して items.stock_num を結 合式内で使用する) のように、副問合せ の WHERE 節内の列値を参照することが できます。 Extended Parallel Server Extended Parallel Server では、UPDATE 文の SET 節で副問合せを使用できませ ん。 Extended Parallel Server の終り 適切に設計されたデータベースでは、同じ表に対する更新と問合せが同時に行われ ることはほとんどありません。 (データベース設計の詳細については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。) し かし、データベースを初めて設計するときには、データベース設計を熟考する前 に、更新と問合せを同時に実行したいと考えるでしょう。一意でなければならない 列の中に重複値がある行が表内にいくつか誤って含まれているような場合に、典型 的な問題が発生します。この場合には、重複行を削除するか、重複行のみを更新す 第 6 章 データの変更 167 る必要が生じます。いずれの方法でも、重複行をテストする場合は、UPDATE 文ま たは DELETE 文で許可されていない、同じ表に対する副問合せが必要になります。 第 9 章では、UPDATE カーソル を使用して、この種の変更を実行する方法につい て説明します。 選択値を使用する更新 2 つ目の形式の UPDATE 文は、一連の代入を 1 つの代入にまとめて置き換えたも のです。ここでは、列の並び順が値の並び順と等しくなるように設定してくださ い。次の例が示しているように、値が簡単な定数の場合には、この形式はその部分 が再配置されている上記の例の形式と大差がありません。 UPDATE customer SET (fname, lname) = (’Barnaby’, ’Dorfler’) WHERE customer_num = 103 文を前記のように記述しても利点はまったくありません。実際には、どの列にどの 値が代入されるかが明らかでないために、読みにくくなります。 ただし、代入される値が 1 つの SELECT 文から取得できるのであれば、この形式 を使用する意味があります。次の例では、数人の顧客の住所を変更しています。住 所の変更があるたびに表 customer を更新せずに、新しい住所を newaddr という 名前の一時表にいったん格納してあると仮定します。この一時表は、表 customer の顧客番号と住所に関連するフィールドから構成されています。この一時表に格納 された新しい住所を、ある時点で一括して表 customer に反映します。 UPDATE customer SET (address1, address2, city, state, zipcode) = ((SELECT address1, address2, city, state, zipcode FROM newaddr WHERE newaddr.customer_num=customer.customer_num)) WHERE customer_num IN (SELECT customer_num FROM newaddr) 1 つの SELECT 文により、複数の列値が生成されます。この例を、更新対象の各列 ごとに 1 つの代入文を使用するもう 1 つの形式で書き直すには、更新する個々の 列ごとに 1 つずつ、合計で 5 つの SELECT 文を記述しなければなりません。その ような文の記述は難しいだけではなく、実行時間も長くなります。 ヒント: SQL API プログラムでは、レコードまたはホスト変数を使用して値を更新 できます。詳しくは、第 8 章を参照してください。 行 (ROW) 型の更新 (IDS のみ) 行 (ROW) 型値を更新する構文は、対象の列が名前付き行 (named row) 型か名前な し行 (unnamed row) 型かによって多少異なります。ここでは、それらの違いについ て説明します。また、行 (ROW) 型のフィールドに NULL 値を指定する方法につい ても説明します。 名前付き行 (named row) 型を含む行の更新 名前付き行 (named row) 型に対して定義された列を更新するには、その行 (ROW) 型のすべてのフィールドを指定する必要があります。例えば次の文は、表 employee にある列 address のフィールド street および city のみを更新します が、その行 (ROW) 型の各フィールドには値が含まれている必要があります。この 値には NULL 値も指定できます。 168 IBM Informix: SQL ガイド: チュートリアル UPDATE employee SET address = ROW(’103 California St’, San Francisco’, address.state, address.zip)::address_t WHERE name = ’zawinul, joe’ この例では、フィールド state および zip の値が読み取られ、その後ただちに行に 再挿入されます。更新されるのは、列 address のフィールド street および city のみです。 名前付き行 (named row) 型に対して定義された列のフィールドを更新する場合は、 行 (ROW) 型コンストラクタを使用して、行の値を適切な名前付き行 (named row) 型にキャストする必要があります。 名前なし行 (unnamed row) 型を含む行の更新 名前なし行 (unnamed row) 型に対して定義された列を更新するには、その行 (ROW) 型のすべてのフィールドを指定する必要があります。例えば次の文は、表 student にある列 address のフィールド street および city のみを更新します が、その行 (ROW) 型の各フィールドには値が含まれている必要があります。この 値には NULL 値も指定できます。 UPDATE student SET s_address = ROW(’13 Sunset’, ’Fresno’, s_address.state, s_address.zip) WHERE s_name = ’henry, john’ 名前なし行 (unnamed row) 型に対して定義された列のフィールドを更新するには、 フィールド値が挿入される前に必ず行 (ROW) 型コンストラクタを指定する必要が あります。 行 (ROW) 型のフィールドに対する NULL 値の指定 行 (ROW) 型列のフィールドには、NULL 値を含めることができます。 NULL 値 を持つ行 (ROW) 型フィールドに対して挿入または更新を行う場合は、その値を、 そのフィールドのデータ型にキャストする必要があります。 次の UPDATE 文は、名前付き行 (named row) 型列の特定のフィールドに NULL 値を指定する方法を示しています。 UPDATE employee SET address = ROW(NULL::VARCHAR(20), ’Davis’, ’CA’, ROW(NULL::CHAR(5), NULL::CHAR(4)))::address_t) WHERE name = ’henry, john’ 次の UPDATE 文は、表 student に対して、列 address の street および zip フ ィールドに NULL 値を指定する方法を示します。 UPDATE student SET address = ROW(NULL::VARCHAR(20), address.city, address.state, NULL::VARCHAR(9)) WHERE s_name = ’henry, john’ 重要: 行 (ROW) 型列に対して NULL 値を指定することはできません。NULL 値を 指定できるのは、行 (ROW) 型の個々のフィールドに対してのみです。 コレクション (COLLECTION) 型の更新 (IDS のみ) DB–Access を使用してコレクション (COLLECTION) 型を更新する場合、コレクシ ョン全体を更新する必要があります。次の文は、列 projects を更新する方法を示 第 6 章 データの変更 169 しています。更新する必要のある行を探すには、IN キーワードを使用して、列 direct_reports に対する検索を実行します。 UPDATE manager SET projects = "LIST { ROW(’brazil_project’, SET{’Pryor’, ’Murphy’, ’Kinsley’, ’Bryant’}), ROW (’cuba_project’, SET{’Forester’, ’Barth’, ’Lewis’, ’Leonard’}) }" WHERE ’Williams’ IN direct_reports この文で SET キーワードが最初に現れるのは、UPDATE 文の中です。 ヒント: UPDATE 文の SET キーワードと、コレクションがセット (SET) 型である ことを示す SET コンストラクタを混同しないようにしてください。 キーワード IN を使用して、単純コレクション (COLLECTION) 型の特定の要素を 探すことはできますが、コレクション (COLLECTION) 型列の個々の要素を DB–Access で更新することはできません。ただし、ESQL/C プログラムおよび SPL ルーチンを作成して、コレクション内の要素を更新することは可能です。 ESQL/C プログラムを作成してコレクションを更新する方法については、「IBM Informix: ESQL/C Programmer’s Manual」を参照してください。SPL ルーチンを作成してコレ クションを更新する方法については、295 ページの『コレクションの処理 (IDS の み)』を参照してください。 上位表の行の更新 (IDS のみ) 上位表の行を更新する場合、その更新範囲は上位表とその副表になります。 上位表に対して UPDATE 文を作成すると、その上位表にあるすべての列と、その 上位表から継承を行う副表の列を更新することができます。例えば次の文では、表 employee および表 sales_rep の行が更新されます。これらは、上位表 person の副表です。 UPDATE person SET salary=65000 WHERE address.state = ’CA’ ただし、上位表を更新しても、その副表の列が上位表にない場合は、その列は更新 されません。例えば前に示した UPDATE 文では、表 sales_rep の列 region_num を更新することができません。これは、列 region_num が表 employee に存在し ないためです。 上位表に対する更新を実行する場合は、その更新の範囲について注意する必要があ ります。例えば、表 person に対する UPDATE 文に、更新する行を制限する WHERE 節が含まれない場合、その UPDATE 文は、表 person、表 employee、 および表 sales_rep のすべての行を変更します。 上位表の行のみを更新するには、UPDATE 文でキーワード ONLY を使用する必要 があります。例えば次の文では、表 person の行のみが更新されます。 UPDATE ONLY(person) SET address = ROW(’14 Jackson St’, ’Berkeley’, address.state, address.zip) WHERE name = ’Sallie, A.’ 170 IBM Informix: SQL ガイド: チュートリアル 警告: 上位表の行を更新する場合は、その更新範囲に上位表とそのすべての副表が 含まれることに注意してください。 CASE 式による列の更新 CASE 式により、いくつかの条件テストのどれが TRUE と評価されるかによって、 文はいくつかの可能な結果の 1 つを戻すことができます。 次の例は、UPDATE 文の CASE 文を使用して、表 stock にある項目の単価を上げ る方法を示しています。 UPDATE stock SET unit_price = CASE WHEN stock_num = 1 AND manu_code = "HRO" THEN unit_price = unit_price * 1.2 WHEN stock_num = 1 AND manu_code = "SMT" THEN unit_price = unit_price * 1.1 ELSE 0 END CASE 式には、必ず 1 つ以上の WHEN 節をインクルードします。後続の WHEN 節および ELSE 節はオプションです。WHEN 条件が TRUE と評価しない限り、結 果の値は NULL です。 SQL 関数を使用したスマート ラージ オブジェクトの更新 (IDS のみ) UPDATE 文の中で SQL 関数を呼び出して、スマート ラージ オブジェクトをイン ポートまたはエクスポートすることができます。これらの関数については、97 ペー ジを参照してください。 次の UPDATE 文は、LOCOPY() 関数を使用して、バイナリ ラージ オブジェクト (BLOB) 型データを、表 fbi_list の列 mugshot から表 inmate の列 picture に コピーします (表 inmate および表 fbi_list は、98 ページの図 216 で定義してい ます)。 UPDATE inmate (picture) SET picture = (SELECT LOCOPY(mugshot, ’inmate’, ’picture’) FROM fbi_list WHERE fbi_list.id = 669) WHERE inmate.id_num = 437 LOCOPY() の最初の引数は、このオブジェクトのエクスポート元の列 mugshot を 指定するものです。 2 番目と 3 番目の引数では、新しく作成されるオブジェクト で使用する格納特性を持つ表 inmate および列 picture の名前を指定します。 UPDATE 文を実行すると、列 mugshot のデータが列 picture に格納されます。 関数の引数でファイル名のパスを指定する場合には、次のルールが適用されます。 v ソース ファイルがサーバ コンピュータに存在する場合は、現在の作業ディレク トリへの相対パス名ではなく、そのファイルへのフルパス名を指定する必要があ ります。 v ソース ファイルがクライアント コンピュータに存在する場合は、そのファイル へのフルパス名または相対パス名のどちらでも指定することができます。 第 6 章 データの変更 171 結合を使用した列の更新 Extended Parallel Server により、表の結合を使用して、どの列を更新するかを決定 することができます。更新する列と行の値を指定するために、SET 節の FROM 節 にリスト表示されたどの表からも列を使用できます。 FROM 節を使用する場合、更新が実行される表の名前を含めなければなりません。 その他の場合は、エラーとなります。次の例に、FROM を含む UPDATE 文の使用 方法を示します。 UPDATE t SET a = t2.a FROM t, t2 WHERE t.b = t2.b この例の文では、FROM 節が省略される場合と同じ処理を実行します。 UPDATE 文の FROM 節には、複数の表を指定できます。しかし、表を 1 つだけ指定する場 合、それはターゲット表になります。 データベースでのアクセス権 次のデータベース アクセス権を使用して、データベースへのアクセスを制御できま す。 v データベース レベル アクセス権 v 表レベル アクセス権 v 列レベル アクセス権 v ルーチン レベル アクセス権 ここでは、データベース レベル アクセス権と表レベル アクセス権について、簡単 に説明します。データベース アクセス権の詳細については、「IBM Informix: デー タベース設計および実装 ガイド」を参照してください。アクセス権のリスト、およ び GRANT 文と REVOKE 文の説明については、「IBM Informix: SQL ガイド: 構 文」を参照してください。 データベース レベル アクセス権 データベースを作成する場合は、データベースの所有者またはデータベース管理者 (DBA) がデータベース レベル アクセス権を付与しない限り、他のユーザはデータ ベースにアクセスできません。次に、データベース レベル アクセス権を示しま す。 アクセス権 内容 Connect データベースのオープン、問合せの発行、および一時表のインデッ クスの作成と配置を行うことができます。 Resource 永続表を作成することができます。 DBA DBA として、いくつかの追加機能を実行することができます。 表レベル アクセス権 ANSI 標準に準拠しないデータベースに表を作成すると、表の所有者が特定のユー ザからの表レベルのアクセス権を取り消さない限り、すべてのユーザがその表への アクセス権を持つことになります。次の表は、ユーザが表へアクセスする場合の4つ のアクセス権を示しています。 172 IBM Informix: SQL ガイド: チュートリアル アクセス権 内容 Select 表ごとに与えられる権限で、表から行を選択することができます。 このアクセス権は、表の特定の列のみに制限することもできます。 Delete 行を削除することができます。 Insert 行を挿入することができます。 Update 既存の行を更新する、つまり行の内容を変更することができます。 多くの場合、データベースと表を作成したユーザは、Connect アクセス権および Select アクセス権を public に与えて、すべてのユーザがそれらの権限を保有でき るようにします。表に対して問合せができるということは、そのデータベースと表 について少なくとも Connect アクセス権と Select アクセス権を持っていることにな ります。 データを変更するには、その他の表レベルアクセス権が必要です。多くの場合、表 の所有者だけがこれらの権限を持っているか、または特定のユーザだけに付与され ています。その結果、自由に問合せができる一部の表を変更できない場合がありま す。 これらのアクセス権は表ごとに設定できるため、例えばある表については Insert ア クセス権のみを持ち、他の表については Update アクセス権のみを持っているとい うこともあります。 Update アクセス権は、表の特定の列のみに制限することもで きます。 上記、または上記以外の表レベル アクセス権の詳細については、「IBM Informix: データベース設計および実装 ガイド」を参照してください。 表アクセス権の表示 表の所有者、つまり作成者は、その表についてのすべてのアクセス権を持っていま す。表の所有者でない場合は、システム カタログへの問合せによって、その表に対 して持っているアクセス権を調べることができます。システム カタログは、データ ベース構造を記述するシステム表で構成されています。個々の表に対して付与され たアクセス権は、システム表 systabauth に記録されています。これらのアクセス 権を表示するには、この表の一意な識別子番号を知っていなければなりません。こ の番号は、システム表 systables に指定されています。表 orders に対して付与さ れているアクセス権を表示するには、次の SELECT 文を入力します。 SELECT * FROM systabauth WHERE tabid = (SELECT tabid FROM systables WHERE tabname = ’orders’) この問合せの出力は、次のようになります。 grantorgrantee tabid tfecitmutator 101 tfecitprocrustes101 tfecitpublic 101 tabauth su-i-x-s--idx-s--i-x-- grantor (権限授与者) はアクセス権を付与 したユーザです。通常、権限授与者はそ の表の所有者ですが、権限授与者によって権限を与えられた別のユーザが所有者で ある場合もあります。列 grantee に表示されるユーザは、アクセス権を付与された 第 6 章 データの変更 173 被権限授与者であり、grantee public とは、「Connect アクセス権を持つすべてのユ ーザ」です。ユーザ名がここに記載されていないユーザは、パブリックに与えられ たアクセス権以外は所有していません。 列 tabauth に表示される文字列は、付与されたアクセス権を示します。この列の各 行の文字はアクセス権の名前の頭文字を表しますが、例外的に i は挿入 (Insert) を 意味し、 x はインデックス (Index) を意味します。この例では、public に Select、 Insert、および Index のアクセス権が与えられています。 Update アクセス 権を持つのはユーザ mutator のみで、Delete アクセス権を持つのはユーザ procrustes のみです。 DELETE 文の実行など、ユーザが何らかの処理を行う場合、データベース サーバは その処理を実行する前に、この例のように問合せを行います。ユーザが表の所有者 でない場合、またデータベース サーバがユーザ名に対してもパブリックに対しても 表に対する必要なアクセス権を与えていない場合は、その処理の実行は拒否されま す。 データ整合性 INSERT、UPDATE、および DELETE 文は、既存データベース内のデータを修正し ます。既存のデータを変更すると、データの整合性 が影響を受ける可能性がありま す。例えば、存在しない製品に対する注文が表 orders に入力されていたり、その 注文が未処理である顧客が表 customer から削除されていたり、注文番号が表 orders で更新されていても表 items では更新されていない ということが起こりま す。このいずれの場合も、格納されているデータの整合性は失われたことになりま す。 実際には、データ整合性は次の部分によって構成されています。 v エンティティ保全性 表の各行には、行を一意にする識別子が必要です。 v 意味整合性 列内のデータは、列が保持すべき情報を正しく反映するものでなければなりませ ん。 v 参照整合性 表と表の間の関係により強制される制約です。 例えば、存在しない行を参照することはできません。正しく設計されたデータベー スでは、これらの原則が守られ、データを変更する際にデータの整合性が失われな いような構造になっています。 エンティティ保全性 エンティティとは、データベースに記録されるあらゆる人、場所、または物のこと です。個々の表はエンティティを表し、表の各行はエンティティのインスタンスを 表します。例えば、注文 がエンティティであれば、表 orders は注文の概念を表 し、表の各行 は特定の注文を表します。 表の各行を識別するには、表に主キーが必要です。主キーは各行を識別するための 一意な値です。この要件は、実体整合性制約 と呼ばれます。 174 IBM Informix: SQL ガイド: チュートリアル 例えば、表 orders の主キーは rder_num です。列 order_num はシステムによ って生成された、表内の各行を表す一意な番号を保持しています。表 orders のデ ータの行にアクセスするには、次の SELECT 文を使用します。 SELECT * FROM orders WHERE order_num = 1001 注文番号の値が一意になっているため、WHERE 節でこの値を使用して簡単に特定 の行にアクセスすることができます。表内の注文番号に重複が許される場合は、こ の表の他のすべての列に重複する値が存在することになるため、ある単一行にアク セスすることはほぼ不可能です。 主キーおよびエンティティ保全性の詳細については、「IBM Informix: データベース 設計および実装 ガイド」を参照してください。 意味整合性 意味整合性とは、ある行に入力されたデータが確実にその行の許容値を反映するよ うにするためのものです。この値は、その列について、定義域 内の値、つまり許容 可能な値の集合である必要があります。例えば、表 items の列 quantity では、数 字のみが許されます。定義域外の値を列に入力できた場合には、そのデータの意味 整合性に違反することになります。 意味整合性は、次の制約によって強制されます。 v データ型 データ型は、列に格納することのできる値の型を定義します。例えば、小桁整数 (SMALLINT) 型の列には、-32,767 から 32,767 の値を入力することができます。 v デフォルト値 デフォルト値は、明示的に値が指定されなかった場合に列に挿入される値です。 例えば、表 cust_calls の列 user_id は、名前が入力されなかった場合デフォル トのログイン名になります。 v チェック制約 チェック制約は、列に挿入するデータの条件を指定します。表に挿入される各行 は、この条件を満たしていなければなりません。例えば、表 items の列 quantity では 1 以上の数量であるかをチェックします。 データベース設計において意味整合性の制約を使用する方法については、 「IBM Informix: データベース設計および実装 ガイド」を参照してください。 参照整合性 参照整合性は、表間 の関係を表します。データベース内の各表には主キーがなけれ ばならないため、他の表内のデータとの関係のために、この主キーが他の表に現れ る場合があります。ある表の主キーが他の表に現れる場合、これは外部キー と呼ば れます。 外部キーは複数の表を結合 し、表間の依存関係を確立します。表と表の依存性は、 階層的に形成することができます。ある表の行を変更または削除すると、他の表の 行の意味がなくなることがあります。例えば、図 353 は、表 customer の列 customer_num はその表の主キーであり、表 orders と表 cust_call の外部キー であることを示しています。顧客番号 106 の George Watson は、表 orders と表 第 6 章 データの変更 175 cust_calls の両方で参照 されています。顧客 106 が表 customer から削除され ると、3 つの表のリンクとこの特定の顧客は意味を失います。 図 353. デモンストレーション データベースの参照整合性 主キーを含んでいる行を削除したり、別の主キーで更新したりすると、その値を外 部キーとして含んでいる行の意味を破壊することになります。参照整合性とは、主 キーに対する外部キーの論理的依存性のことです。外部キーを含む行の整合性 は、 それが参照 する行、つまり一致する主キーを含む行の整合性に依存します。 デフォルトでは、データベース サーバは参照整合性に違反することを許可しませ ん。子表から行を削除する前に親表から行を削除しようとすると、エラー メッセー ジが表示されます。ただし、オプション ON DELETE CASCADE を使用すれば、 親表からのみ削除を実行し、子表の削除を実行しないことができます。 176 ページ の『ON DELETE CASCADE オプションの使用』を参照してください。 主キーと外部キーを定義し、これらの関係を定義するには、CREATE TABLE 文お よび ALTER TABLE 文を使用します。これらの文の詳細については、 「IBM Informix: SQL ガイド: 構文」を参照してください。外部キーおよび主キーに よるデータ モデルの構築方法については、「IBM Informix: データベース設計およ び実装 ガイド」を参照してください。 ON DELETE CASCADE オプションの使用 表に対して主キーから行を削除した場合に参照整合性を維持するには、CREATE TABLE の REFERENCES 節で ON DELETE CASCADE オプションを使用する か、ALTER TABLE 文を使用します。このオプションを使用すると、1 回の削除コ マンドで、親表の行と対応する子表の一致している行を削除することができます。 カスケード削除中のロック: 削除の実行中に、親表および子表の修飾されている行 がすべてロックされます。削除を指定すると、親表から要求される削除は何らかの 参照動作が実行される前に発生します。 複数の子表に対する影響: 一方の子にはカスケード削除が指定され、もう一方の子 にはカスケード削除が指定されていない 2 つの子側の制約を持つ親表があり、この 両方の子表に適用されている親表から行を削除しようとすると、DELETE 文は失敗 し、親表からも子表からも行は削除されません。 176 IBM Informix: SQL ガイド: チュートリアル ログ機能をオンにする必要性: カスケード削除を実行するには、現行データベース でログ機能をオンにする必要があります。ロギングとカスケード削除については、 185 ページの『トランザクション ログ』に記載されています。 カスケード削除の例 参照整合性規則が適用されている 2 つの表 (親表 accounts と子表 sub_accounts) が あると仮定します。次の CREATE TABLE 文は、参照制約を定義しています。 CREATE TABLE accounts ( acc_num SERIAL primary key, acc_type INT, acc_descr CHAR(20)); CREATE TABLE sub_accounts ( sub_acc INTEGER primary key, ref_num INTEGER REFERENCES accounts (acc_num) ON DELETE CASCADE, sub_descr CHAR(20)); accounts 表の主キー acc_num column は、シリアル (SERIAL) 型を使用します。ま た、sub_accounts 表の外部キー ref_num column は、整数 (INTEGER) 型を使用しま す。主キーのシリアル (SERIAL) 型と外部キーの整数 (INTEGER) 型の組合せは許 されています。この条件においてのみ、データ型を混用したり、一致させたりでき ます。シリアル (SERIAL) 型は整数 (INTEGER) 型であり、データベースは自動的 に列の値を生成します。このデータ型以外の主キーと外部キーの組合せは、データ 型がすべて明確に一致していなければなりません。例えば、文字 (CHAR) 型として 定義された主キーは、文字 (CHAR) 型として定義された外部キーに一致しなければ なりません。 表 sub_accounts、列 ref_num の外部キーの定義にはオプション ON DELETE CASCADE が含まれます。このオプションを指定すると、親表 accounts のどの行 を削除しても、子表 sub_accounts の対応する行が自動的に削除されます。 表 accounts から行を削除し、表 sub_accounts をカスケード削除するには、ログ機 能をオンにする必要があります。次の例が示しているように、ログ機能をオンにし た後両方の表からアカウント番号 2 を削除することができます。 DELETE FROM accounts WHERE acc_num = 2 カスケード削除に対する制約 自己参照型問合せおよび循環型問合せでの削除を含む、ほとんどの削除にカスケー ド削除を使用することができます。唯一の例外は、相関副問合せです。相関副問合 せとは、副問合せ文 (または内側の SELECT 文) が生成する値が、その文自身が含 まれている外側の SELECT 文によって生成された値に依存していることです。カス ケード削除を実行した場合、相関副問合せ文で子表を使用する削除を記述すること はできません。相関副問合せ文から削除を実行しようとすると、エラーが発生しま す。 重要: ON DELETE CASCADE で参照制約を定義している表では、DELETE トリガ イベントを定義できません。 第 6 章 データの変更 177 オブジェクトモードと違反の検出 データベースのオブジェクトモード機能と違反の検出機能は、データの整合性の監 視に役立ちます。この 2 つの機能は、スキーマの変更中に両方の機能を組み合わせ て使用したり、短期間に大量のデータに対して挿入、削除、更新などの操作が実行 されるときに使用したりすると特に効果的です。 オブジェクト モード機能を説明する文中でのデータベース オブジェクトとは、制 約、インデックス、およびトリガのことで、これらはそれぞれ異なるモードを持ち ます。オブジェクトモード機能に関係のあるデータベース オブジェクトを、一般的 な意味のデータベース オブジェクトと混同しないでください。一般的なデータベー ス オブジェクトは、表およびシノニムのようなものです。 オブジェクト モードの定義 制約または一意性インデックスについて、停止モード、有効モード、またはフィル タ モードを設定することができます。トリガまたは重複インデックスについて、停 止モードまたは有効モードを設定することができます。データベース オブジェクト モードを使用して、INSERT、DELETE、および UPDATE 文の影響を制御できま す。 有効モード (IDS のみ): 効になっています。 制約、インデックス、およびトリガは、デフォルトでは有 あるデータベース オブジェクトが有効の場合、データベース サーバではそのデー タベース オブジェクトの存在が認識され、INSERT 文、DELETE 文、または UPDATE 文の実行中には、そのデータベース オブジェクトが考慮に入れられま す。したがって、トリガ イベントが発生すると、有効な制約が実行され、有効なイ ンデックスが更新され、有効なトリガが実行されます。 制約および一意性インデックスを有効にするときに違反行が存在すると、データ操 作ステートメントが失敗して行の変更が行われず、エラー メッセージが戻されま す。 違反表と診断表の情報を分析すると、障害の原因を特定することができます。原因 が特定できたら、修正処置をとるか、その操作をロール バックします。 停止モード (IDS のみ): あるデータベース オブジェクトが停止している場合は、 INSERT 文、DELETE 文、または UPDATE 文の実行中に、そのデータベース オブ ジェクトは考慮に入れられません。トリガ イベントが発生しても、停止している制 約は実行されず、停止しているインデックスも更新されず、停止しているトリガも 実行されません。制約および一意性インデックスを停止すると、制約または一意性 インデックスの制限に違反するすべてのデータ操作ステートメントが正常に機能し てターゲット行が変更され、エラー メッセージも戻されません。 フィルタ モード: 制約または一意性インデックスがフィルタ モードの場合、各文 は正常に機能し、INSERT 文、DELETE 文、または UPDATE 文の実行中に、制約 または一意性インデックスの要件が実行されます。このとき、ターゲット表に関連 付けられた違反表に、失敗した行が書き込まれます。制約違反に関する診断情報 は、ターゲット表に関連付けられた診断表に書き込まれます。 178 IBM Informix: SQL ガイド: チュートリアル データ操作ステートメントのモード例 INSERT 文を使用する例で、有効モード、停止モード、およびフィルタ モードの違 いを説明することができます。 INSERT 文を使用して、表の整合性制約を満足しな い行を追加する場合を考えます。例えば、ユーザ joe が表 cust_subset を作成 し、この表が、ssn (顧客の社会保障番号)、fname (顧客の名)、lname (顧客の 姓)、city (顧客の居住する市) という 4 つの列で構成されるとします。列 ssn は 整数 (INT) 型であり、他の 3 列は文字 (CHAR) 型であるとします。 ユーザ joe は列 lname を非 NULL として定義しましたが、NULL 値不可制約に 名前を割り当てなかったため、データベース サーバによって、この制約に n104_7 という名前が暗黙的に割り当てられました。最後にユーザ joe は、列 ssn に対し て unq_ssn という一意性インデックスを作成しました。 ここで、表 cust_subset に対して Insert アクセス権を持つユーザ linda が、次の INSERT 文をこの表に対して入力します。 INSERT INTO cust_subset (ssn, fname, city) VALUES (973824499, "jane", "los altos") 有効モード、停止モード、および フィルタ モードの違いがよくわかるように、こ の INSERT 文の結果を以下の 3 つの節で説明します。 制約が有効な場合の挿入操作の結果: 表 cust_subset に対する NULL 値不可制 約が有効な場合は、INSERT 文を使用してもこの表に新しい行を挿入することがで きません。ユーザ linda は、INSERT 文を入力すると、次のエラー メッセージを 受け取ります。 -292 追加しようとした列 (%s) には NULL は許されていません。 制約が無効な場合の挿入操作の結果: 表 cust_subset に対する NULL 値不可制 約が無効な場合、ユーザ linda が発行する INSERT 文によって、この表に新しい 行が正常に挿入されます。表 cust_subset の新しい行には、次の列値がありま す。 ssn fname lname city 973824499 jane NULL los altos 制約がフィルタ モードの場合の挿入操作の結果: 表 cust_subset に対する NULL 値不可制約がフィルタ モードに設定されている場合、ユーザ linda が発行 する INSERT 文では、この表に新しい行を挿入することができません。代わりに、 その新しい行は違反表に挿入され、その整合性違反を説明する診断行が診断表に追 加されます。 ユーザ joe が、表 cust_subset に対する違反表と診断表を起動した場合を考えま す。違反表の名前は cust_subset_vio で、診断表の名前は cust_subset_dia で す。ユーザ linda がターゲット表 cust_subset に対して INSERT 文を発行したと きに、違反表 cust_subset_vio に追加される新しい行は、次の列値をもちます。 ssn fname lname city informix_tupleid informix_optype informix_recowner 973824499 jane NULL los altos 1 I linda 第 6 章 データの変更 179 違反表 cust_subset_vio のこの新しい行には、次のような特徴があります。 v 違反表の最初の 4 つの列は、ターゲット表の列と完全に一致します。これら 4 つの列は、ターゲット表の対応する列と同じ名前および同じデータ型を持ち、ま た、ユーザ linda が入力した INSERT 文によって与えられた列値を持ちます。 v 列 informix_tupleid の値 1 は、不一致行に割り当てられた、一意のシリアル識 別子です。 v 列 informix_optype の値 I は、この、不一致行を作成した操作の種類を識別す るコードです。特に、I は挿入操作を表します。 v 列 informix_recowner の値 linda は、この不一致行を作成した文を発行したユ ーザを識別するものです。 ユーザ linda がターゲット表 cust_subset に対して発行した INSERT 文によって も、診断表 cust_subset_dia に診断行が 1 行追加されます。診断表に追加された この新しい診断行には、次の列値があります。 informix_tupleid objtype objowner objname 1 C joe n104_7 診断表 cust_subset_dia のこの新しい診断行には、次のような特徴があります。 v 診断表のこの行は、違反表の対応する行にリンクしています。これは、列 informix_tupleid が両方の表に存在することで実現しています。値 1 は、両方 の表でこの列に表示されます。 v 列 objtype の値 C は、違反表の対応する行の発生要因になった整合性違反の種 類を識別するものです。特に、値 C は制約違反を表します。 v 列 objowner の値 joe は、整合性違反が検出された制約の所有者を識別するも のです。 v 列 objname の値 n104_7 は、整合性違反が検出された制約の名前を示していま す。 違反表と診断表を結合することにより、ターゲット表 cust_subset と、それに関 連付けられた特別な表の所有者であるユーザ joe、または DBA は、列 informix_tupleid に 1 という値を持つ行が INSERT 文実行の後で違反表に作成さ れたこと、および、この行が制約に違反していることがわかります。表の所有者ま たは DBA は、sysconstraints システム カタログ表に問合せることで、この制約 が NULL 値不可制約であると判別します。 INSERT 文の失敗が判明したため、ユ ーザ joe または DBA は修正処置を実行できます。 1 つの違反行に対する複数の診断行: 前の例では、診断表の 1 つの行だけが、違 反表の新しい行に対応していました。しかし、単一の新しい行が違反表に追加され たときに、複数の診断行を診断表に追加することも可能です。例えば、ユーザ linda が INSERT 文で入力した ssn の値 (973824499) が、ターゲット表 cust_subset の列 ssn にすでにある値と同じだった場合、違反表に表示される新 しい行は 1 つのみですが、診断表 cust_subset_dia には次の 2 つの診断行が表 示されます。 180 IBM Informix: SQL ガイド: チュートリアル informix_tupleid objtype objowner objname 1 C joe n104_7 1 I joe unq_ssn どちらの診断表の行も列 informix_tupleid に 1 の値を持つため、違反表の同じ行 に対応しています。ただし、1 番目の診断行は、ユーザ linda が発行した INSERT 文による制約違反を識別するのに対し、2 番目の診断行は、同じ INSERT 文による 一意性インデックス違反を識別します。この 2 番目の診断行では、列 objtype の 値 I が一意性インデックス違反を表し、列 objname の値 unq_ssn が、整合性違 反が検出されたインデックスの名前を示します。 データベース オブジェクト モードの設定方法については、「IBM Informix: SQL ガイド: 構文」のSET DATABASE OBJECT MODE 文に関する説明を参照してくだ さい。 違反表と診断表 ターゲット表に対する違反表を起動すると、ターゲット表に対する挿入、更新、ま たは削除の操作中に制約または一意性インデックスに違反する行があった場合、全 体の操作に支障はありませんが、それらは違反表に出力されます。診断表には、違 反表の各行によって発生した整合性違反の情報が格納されます。これらの表を調査 することにより、障害の原因を識別し、違反を修正したり、操作をロール バックし たりするなどの修正処置をとることができます。 ターゲット表に対する違反表を作成した後は、基本表または違反表の列やフラグメ ント化を変更することができません。違反表を起動した後にターゲット表に対する 制約を変更した場合は、一致しない行が違反表に出力されます。 Extended Parallel Server Extended Parallel Server でターゲット表に対する違反表を作成すると、すべての制 約がフィルタ モードになります。違反表には診断情報を記録したフィールドが含ま れるため、単独の診断表はありません。 Extended Parallel Server の終り 違反表の開始および停止方法については、「IBM Informix: SQL ガイド: 構文」の START VIOLATIONS TABLE および STOP VIOLATIONS TABLE 文を参照してく ださい。 違反表とデータベース オブジェクト モードの関係: 表に対して定義された制約ま たは一意性インデックスをフィルタ モードに設定しても、このターゲット表に対す る違反表および診断表を作成しない場合は、挿入、更新、または削除の操作中に制 約または一意性インデックスの要件に違反した行があっても違反表に出力されませ ん。代わりに、そのターゲット表に対する違反表を起動することを求めるエラー メ ッセージが表示されます。 第 6 章 データの変更 181 同様に、停止モードの制約または一意性インデックスを有効モードまたはフィルタ モードに設定して、その制約または一意性インデックスの要件を満足しない既存の 行を識別できるようにするには、SET DATABASE OBJECT MODE 文を発行する前 に違反表を作成する必要があります。 START VIOLATIONS TABLE 文の例: 次の例では、START VIOLATIONS TABLE 文を実行する、異なる方法を示します。 名前を指定しない診断表の開始: デモンストレーション データベースで、ターゲ ット表 customer に対する違反表および診断表を起動するには、次の文を入力しま す。 START VIOLATIONS TABLE FOR customer この START VIOLATIONS TABLE 文には USING 節が含まれていないため、違反 表にはデフォルト名 customer_vio が付けられ、診断表にはデフォルト名 customer_dia が付けられます。表 customer_vio には、次の列が含まれます。 customer_num fname lname company address1 address2 city state zipcode phone informix_tupleid informix_optype informix_recowner 表 customer_vio には、表 customer と同じ表定義が含まれます。異なるのは、 表 customer_vio の方にさらに 3 つの列が追加されていることで、これらには、 不正な行の原因になった操作に関する情報が含まれています。 表 customer_dia には、次の列が含まれます。 informix_tupleid objtype objowner objname この、列のリストには、ターゲット表に対する診断表と違反表の重要な違いが示さ れています。違反表には、ターゲット表のすべての列に対して一致する列がありま すが、診断表の列は、ターゲット表のどの列とも一致しません。 START VIOLATIONS TABLE 文で作成される診断表には、同じ列名とデータ型を持つ同じ 列が必ず含まれます。 名前を指定した違反表と診断表の開始: 次の文を実行すると、items というターゲ ット表に対する違反表と診断表が起動されます。 USING 節は、違反表と診断表に 明示的な名前を割り当てます。違反表は exceptions と名付けられ、診断表は reasons と名付けられます。 START VIOLATIONS TABLE FOR items USING exceptions, reasons 診断表の最大行数の指定: 次の文を実行すると、ターゲット表 orders に対する違 反表と診断表が起動されます。 MAX ROWS 節を使用すると、 INSERT 文や SET 182 IBM Informix: SQL ガイド: チュートリアル DATABASE OBJECT MODE 文のような単一の文をターゲット表に対して実行する ときに、診断表に挿入できる行の最大数を指定できます。 START VIOLATIONS TABLE FOR orders MAX ROWS 50000 違反表を作成するときに MAX ROWS の値を指定しない場合は、ディスク領域以外 の制限はかかりません。 違反表に対するアクセス権の例: 次の例に、違反表に対するアクセス権の初期セッ トが、ターゲット表の現在のアクセス権から導出される様子を示します。 例えば、表 cust_subset を作成し、この表が、ssn (顧客の社会保障番号)、fname (顧客の名)、lname (顧客の姓)、city (顧客の居住する市) という 4 つの列で構成さ れるとします。 表 cust_subset に対しては、次のアクセス権があります。 v ユーザ alvin はこの表の所有者です。 v ユーザ barbara は、この表に対して Insert アクセス権および Index アクセス権 を持っています。また、列 ssn および lname に対しては、Select アクセス権も 持っています。 v ユーザ carrie は、列 city に対して Update アクセス権を持っています。また、 列 ssn に対しては、Select アクセス権も持っています。 v ユーザ danny は、この表に対する Alter アクセス権を持っています。 ここで、ユーザ alvin が次のように、表 cust_subset に対する違反表 cust_subset_viols および診断表 cust_subset_diags を起動します。 START VIOLATIONS TABLE FOR cust_subset USING cust_subset_viols, cust_subset_diags データベース サーバにより、違反表 cust_subset_viols に対する次の初期アクセ ス権が許可されます。 v ユーザ alvin はこの違反表の所有者なので、この表に対するすべての表レベルの アクセス権を持っています。 v ユーザ barbara は、この違反表に対して、Insert、Delete、および Index の各ア クセス権を持っています。また、違反表の列 ssn、lname、informix_tupleid、 informix_optype、および informix_recowner に対しては、Select アクセス権も 持っています。 v ユーザ carrie は、この違反表に対して Insert アクセス権および Delete アクセス 権を持っています。また、違反表の列 city、informix_tupleid、 informix_optype、および informix_recowner に対しては、Select アクセス権も 持っています。また、違反表の列 ssn、informix_tupleid、informix_optype、 および informix_recowner に対しては、Select アクセス権も持っています。 v ユーザ danny は、この違反表に対してアクセス権を持っていません。 診断表に対するアクセス権の例: 次の例に、診断表に対するアクセス権の初期セッ トが、ターゲット表の現在のアクセス権から導出される様子を示します。 例えば、表 cust_subset が、ssn (顧客の社会保障番号)、fname (顧客の名)、 lname (顧客の姓)、city (顧客の居住する市) という 4 つの列で構成されるとしま す。 第 6 章 データの変更 183 表 cust_subset に対しては、次のアクセス権があります。 v ユーザ alvin はこの表の所有者です。 v ユーザ barbara は、この表に対して Insert アクセス権および Index アクセス権 を持っています。また、列 ssn および lname に対しては、Select アクセス権も 持っています。 v ユーザ carrie は、列 city に対して Update アクセス権を持っています。また、 列 ssn に対しては、Select アクセス権も持っています。 v ユーザ danny は、この表に対する Alter アクセス権を持っています。 ここで、ユーザ alvin が次のように、表 cust_subset に対する違反表 cust_subset_viols および診断表 cust_subset_diags を起動します。 START VIOLATIONS TABLE FOR cust_subset USING cust_subset_viols, cust_subset_diags データベース サーバにより、診断表 cust_subset_diags に対する次の初期アクセ ス権が許可されます。 v ユーザ alvin はこの診断表の所有者なので、この表に対するすべての表レベルの アクセス権を持っています。 v ユーザ barbara は、この診断表に対して、Insert、Delete、Select および Index の各アクセス権を持っています。 v ユーザ carrie は、この診断表に対して Insert、Delete、Select、および Update の 各アクセス権を持っています。 v ユーザ danny は、この診断表に対してアクセス権を持っていません。 中断された変更 どのソフトウェアにもエラーがなく、すべてのハードウェアが完全に信頼できる場 合でも、コンピュータ外部の環境から干渉を受ける場合があります。落雷による停 電で、UPDATE 文の実行中にコンピュータが停止する事態が起こらないとも限りま せん。もっと可能性があるのは、ディスクがフルになったり、ユーザが誤ったデー タを入力したりしたために、複数行の挿入がエラーのために途中で停止する場合な どです。いずれにしても、データを変更する場合は、予想外のイベントによって変 更が中断される可能性を想定する必要があります。 外部の原因によって変更が中断された場合は、どの段階まで操作が完了しているの か判断できません。 1 行を対象にした操作の場合でも、データがディスクに格納さ れたか、またはインデックスが完全に更新されたかなどを確認することはできませ ん。 複数行の変更が問題となる場合は、複数文の変更はさらに大きな問題を発生させま す。複数文は通常プログラムの中に埋め込まれているため、個々の SQL 文の実行 はユーザにはわかりません。例えば、デモンストレーション データベースに新しい 注文を入力するには、次の手順を実行します。 1. 表 orders に行を挿入する。この挿入操作によって注文番号が生成されます。 2. 注文された各品目について、表 items に行を挿入する。 注文入力アプリケーションのプログラミングには、2 通りの方法があります。その 1 つは、プログラムを完全に対話 (interactive) 型にする方法です。これにより、最 184 IBM Informix: SQL ガイド: チュートリアル 初の行がただちに挿入され、その後オペレータがデータを入力するたびに各品目が 挿入されるようになります。ただし、この方法では、顧客からの電話の切断、オペ レーターの誤入力、オペレーターによる端末電源の切断などの不測のイベントが処 理中に多数発生する可能性があります。 次に、注文入力アプリケーションの正しい作成方法を説明します。 v すべてのデータを対話的に受け入れる。 v データの妥当性を検査し、表 stock や表 manufact のコードを参照するなどし て必要な値を補う。 v オペレータが確認できるように、情報を画面に表示する。 v オペレータが最終的な確定操作を行うまで待つ。 v 挿入を迅速に実行する。 このような手順を踏んでも、予測不能な状況が発生して、注文は挿入したものの、 まだ項目の挿入が終わらないうちにプログラムが停止してしまう場合があります。 このような障害が発生した場合には、データベースの状態は予測できないものとな り、データ整合性 が損なわれます。 トランザクション これまで述べてきたような潜在的な問題すべてに対する解決策は、トランザクショ ン と呼ばれています。トランザクションとは、完全に遂行されるか、あるいはまっ たく遂行されないかのどちらか一連の変更のことです。データベース サーバは、ト ランザクションの範囲内で実行された操作が、完全にディスクにコミットされた か、またはデータベースがトランザクションが開始される前の状態に復元されたか のいずれかを保証します。 トランザクションの役割は、予想外の障害からの保護だけではありません。プログ ラムが論理エラーを検出したときのエスケープの方法も提供します。 トランザクション ログ データベース サーバは、トランザクションの実行中にデータベースに対して行われ た個々の変更内容を記録することができます。トランザクションをキャンセルする ようなイベントが発生すると、データベース サーバは自動的にその記録を使用して 変更前の状態に戻します。トランザクションの失敗には、多くの原因が考えられま す。例えば、SQL 文を発行するプログラムが失敗または強制終了することがありま す。トランザクションの失敗 (この失敗は、コンピュータおよびデータベース サー バが再起動された後にのみ発生する場合がある) を検出すると、すぐにデータベー ス サーバはトランザクションのレコードを使用して、データベースを以前と同じ状 態に戻します。 トランザクションのレコードを記録するプロセスを、トランザクション ログ また は単にロギング と呼びます。ログ レコード と呼ばれるトランザクションの記録 は、データベースとは別のディスク領域に格納されます。ログ レコードがトランザ クションの論理装置を表すため、この領域を論理ログ と呼んでいます。 Dynamic Server Dynamic Server は以下のアクションをサポートします。 第 6 章 データの変更 185 v ログ付きデータベースにログなし (ロウ) 表またはログ付き (標準) 表を作成す る。 v ALTER TABLE 文を使用して、ログなし表をログ付き表に、ログ付き表をログな し表に変更する。 Dynamic Server では、非常に大きい表を速くロードするためにログなし表をサポー トします。トランザクションではログなし表を使用しないことをお勧めします。並 行性の問題を回避するには、トランザクションで使用する前に ALTER TABLE 文 を使用して、表を標準 (つまりログ付き) にします。 Dynamic Server におけるログなし表の詳細については、「IBM Informix: 管理者ガ イド」を参照してください。ログなし表のパフォーマンス上の優位性については、 「IBM Informix: Dynamic Server パフォーマンス ガイド」を参照してください。 ALTER TABLE 文については、「IBM Informix: SQL ガイド: 構文」を参照してく ださい。 Dynamic Server の終り Extended Parallel Server トランザクション レコードを自動的に生成するのは、Extended Parallel Server のデ ータベースのみです。 Extended Parallel Server の終り 多くの Informix データベースは、トランザクション レコードを自動的には生成し ません。 DBA は、データベースがトランザクション ログ機能を使用するかどうか 決定します。トランザクション ログ機能を使用しない場合、トランザクションをロ ール バックすることはできません。 Extended Parallel Server のトランザクション ログ機能 Extended Parallel Server では、論理ログ ファイルのほかに ログスライス の作成が 可能で、これを変更することによって論理ログをいつでも追加できます。ログスラ イスは、DB 領域を占めるログファイルのセットです。これらのログ ファイルは、 DB 領域当たり 1 つのログファイルの割合で、複数のコサーバが所有します。ログ スライスは、1 セットのログ ファイルを単一のエンティティとして扱うため、ログ ファイルの追加と削除のプロセスを単純化します。 DB スライスを作成、変更、ま たは削除するには、onutil ユーティリティを使用します。ログスライスの詳細につ いては、「IBM Informix: 管理者ガイド」を参照してください。 Extended Parallel Server のデータベースは必ずログ付きデータベースである必要が あり、ログ機能をオフにすることはできません。しかし、個々の表がログ付き表で あるかログなし表であるかを指定できます。ログ付き表とログなし表の両方のニー ズに合致するため、Extended Parallel Server は、次のタイプの永続表と一時表をサ ポートします。 v ロウ永続表 (ログなし) v 静的永続表 (ログなし) v 操作可能永続表 (ログあり) v 標準永続表 (ログあり) 186 IBM Informix: SQL ガイド: チュートリアル v スクラッチ一時表 (ログなし) v Temp 一時表 (ログあり) Extended Parallel Server がサポートする表タイプに関する詳細は、「IBM Informix: データベース設計および実装 ガイド」に記載されています。 ロギングおよびカスケード削除 カスケード削除を実行するためには、データベースでログ機能をオンにしなければ なりません。これは、カスケード削除を指定すると、削除はまず親表の主キーで実 行されるためです。親表の主キー行の削除が実行された後で、子表の外部キー行が 削除される前にシステムで障害が発生すると、参照整合性の違反となります。ログ 機能を一時的にでもオフにすると、削除処理はカスケードされません。しかし、ロ グ機能をオンに戻すと、再びカスケード削除にすることができます。 Extended Parallel Server Extended Parallel Server で作成したデータベースはすべて、ログ付きデータベース になります。 Extended Parallel Server の終り Dynamic Server Dynamic Server では、CREATE DATABASE 内の WITH LOG 節でログ機能を有効 にできます。 Dynamic Server の終り トランザクションの指定 SQL 文を使用してトランザクションの範囲を指定する方法は 2 つあります。最も 一般的な方法では、BEGIN WORK 文を実行することにより、複数文のトランザク ションの開始を指定します。オプション MODE ANSI を使用して作成されたデータ ベースでは、トランザクションの開始を指定する必要はありません。常にトランザ クションが開始されている状態にあるため、個々のトランザクションの終了のみを 指定してください。 どちらの方法を使用する場合でも、成功したトランザクションの終了を指定するに は、COMMIT WORK 文を実行します。この文は、すべてが完全に成功しなければ ならない一連の文の終わりに達したことをデータベース サーバに伝えます。データ ベース サーバは、すべての変更を正しく完了し、コミットされてディスクに格納さ れるために、必要な操作をすべて行います。 また、プログラムは、ROLLBACK WORK 文を実行することによって、トランザク ションを意図的にキャンセルすることもできます。この文は、現行のトランザクシ ョンをキャンセルし、すべての変更を取り消すようにデータベース サーバに指示し ます。 注文入力アプリケーションは、新しい注文の作成時に次のような方法を使用してト ランザクションを使用することができます。 第 6 章 データの変更 187 v すべてのデータを対話的に受け入れる。 v 妥当性を検査し、必要な値を補う。 v オペレータが最終的な確定操作を行うまで待つ。 v BEGIN WORK を実行する。 v 表 orders および表 items に行を挿入し、データベース サーバが戻すエラー コードをチェックする。 v エラーが発生しない場合は COMMIT WORK を、発生する場合は ROLLBACK WORK を実行する。 外部の障害によってトランザクションが完了できなかった場合でも、システムを再 起動すると、トランザクションの一部がロール バックされます。これによって、ど のような場合でもデータベースの状態は予測可能です。すなわち、新しい注文が完 全に入力されたか、あるいはまったく入力されていないかのいずれかの状態がわか ります。 Informix データベース サーバを使用したバックアップとログ トランザクションを使用することによって、データベースを常に一貫した状態に保 ち、変更内容を正しくディスクに記録することができます。しかし、ディスクその ものは必ず安全というわけではありません。ディスクは、機械的な障害や水害、火 災、また地震などの影響を受けやすいものです。このような障害に対する唯一の安 全措置は、データのコピーを複数作成し、保持することです。これらの冗長コピー は、バックアップ コピーと呼ばれます。 トランザクション ログ (論理ログとも呼ぶ) は、データベースのバックアップ コピ ーを補います。その内容は、最後にデータベースをバックアップしてから発生した すべての変更の履歴です。バックアップ コピーからデータベースを復元する必要が 発生した場合は、トランザクション ログを使用して、データベースを最新の状態に ロールフォワードすることができます。 データベース サーバには、バックアップ機能とログ機能をサポートする高性能機能 があります。ご使用のデータベース サーバのアーカイブとバックアップのガイドで これらの機能について説明しています。 データベース サーバには、例えばデータベースの使用中にはバックアップ コピー が作成される必要があるなど、パフォーマンスおよび信頼性について厳格な要件が あります。 データベース サーバは、ログ機能専用の自分自身のディスク領域を管理します。 データベース サーバは、少数のログ ファイル セットを使用して、すべてのデータ ベースのためにログ機能を同時に実行します。ログ ファイルは、トランザクション が有効な間に (バックアップされた) 別の媒体にコピーできます。 188 IBM Informix: SQL ガイド: チュートリアル これらの機能は通常、DBA によって中央設置場所から管理されるため、データベー スのユーザが関わることはありません。 Dynamic Server Dynamic Server は、onload および onunload ユーティリティをサポートします。 onunload ユーティリティを使用すると、単一のデータベースまたは表について個 人用バックアップ コピーを作成できます。このプログラムは、表またはデータベー スをテープにコピーします。出力は、データベース サーバで格納されたときのディ スク ページのバイナリ イメージから構成されています。その結果、コピーを簡単 に作成でき、対応するプログラム onload でもファイルを簡単に復元できます。た だし、他のプログラムではこのデータ フォーマットは無効です。 onload および onunload ユーティリティの使用方法については、「IBM Informix: 移行ガイド」を 参照してください。 Dynamic Server の終り Extended Parallel Server Extended Parallel Server は、外部表 を使用して、データのロードおよびアンロード を実行します。外部表を使用してデータをロードする方法については、 「IBM Informix: 管理者ガイド」を参照してください。 Extended Parallel Server の終り ご使用の DBA が ON–Bar を使用してバックアップを作成し、論理ログをバックア ップする場合、ON–Bar を使用して独自のバックアップ コピーを作成することもで きます。詳しくは、「IBM Informix: バックアップおよび復元 ガイド」を参照して ください。 並行性およびロック データベースが単一ユーザのワークステーションに含まれており、ネットワークを 経由して接続されているコンピュータがない場合、並行性は問題にはなりません。 その他の場合には、ユーザのプログラムがデータを変更している間に、他のプログ ラムが同じデータを読み込んだり変更したりしている可能性について考慮しなけれ ばなりません。並行性 は、同じデータを同時に複数の場所で別々に使用する場合に 発生します。 高度な並行性は、複数のユーザによって使用されるデータベースシステムのパフォ ーマンス向上に不可欠です。ただし、データの使用を十分に管理しないと、並行性 はさまざまな弊害をもたらすおそれがあります。プログラムが古いデータを読み込 んでしまったり、正しく入力した変更内容が失われてしまったりすることもありえ ます。 データベース サーバは、ロック を系統的に設定することによって、このようなエ ラーを防止します。ロックは、データの各部に対するプログラムからの使用予約で す。データベース サーバは、ロックされているデータについては、他のプログラム がそのデータを更新できないようにします。他のプログラムがそのデータを要求し 第 6 章 データの変更 189 た場合は、ロックが解除されるまでそのプログラムを待機させるか、あるいはエラ ー メッセージを発行してその要求を拒否します。 データ アクセスに対するロックの効果を制御するには、SET LOCK MODE と、 SET ISOLATION か SET TRANSACTION を組み合わせた SQL 文を使用します。 これらの文の詳細については、プログラム内部からカーソル を使用する方法の説明 を参照してください。カーソルについては、197 ページの『第 8 章 SQL を使用し たプログラミング』と 223 ページの『第 9 章 SQL プログラムによるデータの更 新』 に記載されています。ロックと並行性の詳細については、 235 ページの『第 10 章 マルチユーザ環境のためのプログラミング』を参照してください。 IBM Informix データ レプリケーション (IDS のみ) データ レプリケーション とは、広義では、データベース オブジェクトが、複数の 異なるサイトで複数の表現を持つことを意味します。例えば、元のデータベースを 使用しているクライアント アプリケーションを妨害せずに、データに対してレポー トを実行できるようにデータを複製する 1 つの方法として、データベースを別のコ ンピュータ上のデータベース サーバにコピーすることができます。 次に、データ レプリケーションの利点について説明します。 v 複製されていないリモート データではなく、複製されたデータにローカルにアク セスするクライアントは、ネットワークサービスを使用する必要がないためにパ フォーマンスが向上します。 v どのサイトのクライアントでも、複製されたデータを使用すると可用性が向上し ます。これは、ローカルの複製データが使用できない場合に、リモートからでも データのコピーを使用することができるためです。 これらの利点を得るには、コストもかかります。データ レプリケーションでは、デ ータを複製しない場合よりも複製データのためにより多くの記憶域が必要となり、 複製データの更新には、1 つのオブジェクトの更新よりも多くの処理時間がかかる ためです。 実際には、データ レプリケーションは、データの位置または更新位置を明示的に指 定することにより、クライアント アプリケーションのプログラム ロジックに実行 することができます。ただし、この方法によるデータ レプリケーションのアーカイ ブにはコストがかかり、エラーも発生しやすく、管理が難しくなります。むしろ、 データ レプリケーションの概念は、しばしばレプリケーションの透過性 と結び付 けられます。レプリケーションの透過性は、データの複製の自動配置および保持の 個々の処理を行うために (クライアント アプリケーションの代わりに) データベー ス サーバに組み込まれている機能です。 データ レプリケーションの幅広い枠内で、Informix データベース サーバはデータ ベース サーバ全体のほとんど透過的なデータ レプリケーションを実装します。 1 つの Informix データベース サーバによって管理されるすべてのデータは、通常、 リモート サイトにある別の Informix データベース サーバで複製され、動的に更新 されます。 Informix データベース サーバのデータ レプリケーションは、非常に重 大な障害が発生した場合にすばやく使用できる、データベース サーバ全体のバック アップ コピーを保持する手段を提供するため、ホットサイト バックアップ と呼ば れることもあります。 190 IBM Informix: SQL ガイド: チュートリアル データベース サーバではレプリケーションの透過性が提供されているので、通常は データ レプリケーションについて意識する必要はありません。DBA がデータ レプ リケーションを処理します。しかし、ユーザの組織がデータ レプリケーションの採 用を決定した場合は、データ レプリケーション環境では、クライアント アプリケ ーションに関して特殊なコネクティビティ問題があることを認識すべきです。これ らの考慮事項については、「IBM Informix: 管理者ガイド」で説明されています。 IBM Informix エンタープライズ レプリケーションは、異なるデータ レプリケーシ ョン機能を持ちます。この機能については、「IBM Informix: Dynamic Server エンタ ープライズ レプリケーション ガイド」を参照してください。 サマリ データベースに対するアクセスは、データベースの所有者が付与するアクセス権に よって制限されます。データに対する問合せを行うためのアクセス権は、多くの場 合自動的に与えられますが、データを変更するための権利は、表ごとに特定の Insert アクセス権、Delete アクセス権、Update アクセス権を付与することによって制限さ れます。 データベースにデータ整合性制約がある場合、データを変更するための権限は、こ れらの制約によって制限されます。データベース レベルおよび表レベルのアクセス 権は、すべてのデータ制約とともに、データを変更する方法とタイミングを制御し ます。更に、データベースのオブジェクト モードと違反検出機能は、ユーザがデー タを変更する方法、およびユーザがデータの整合性の維持を支援する方法に影響を 与えます。 DELETE 文を使用すると、表から 1 つ以上の行を削除することができます。この文 内の WHERE 節は行を選択します。削除内容を確認するには、同じ節を指定した SELECT 文を使用します。 INSERT 文を使用すると、行が表に追加されます。指定した列の値を含んでいる単 一の行を挿入することや、SELECT 文が生成する行のブロックを挿入することもで きます。 UPDATE 文を使用して、既存の行の内容を修正することができます。副問合せ文を 指定できる式で新しい内容を指定して、他の表や更新された表自体に基づくデータ を使用することができます。この文には 2 つの形式があります。最初の形式では、 列ごとに新しい値を指定します。もう 1 つの形式では、SELECT 文またはレコード 変数が一連の新しい値を生成します。 CREATE TABLE および ALTER TABLE 文の REFERENCES 節を使用して、複数 の表間の関係を作成できます。 REFERENCES 節の ON DELETE CASCADE オプ ションを使用して、1 つの DELETE 文で親表と子表の両方から行を削除できます。 トランザクションを使用すると、変更操作の実行中に予想外の障害が発生して、デ ータベースが不安定な状態になるのを防止することができます。トランザクション 内で変更が実行され、エラーが発生した場合、それらの変更はロール バックされま す。また、トランザクション ログは、定期的に作成されるデータベースのバックア ップ コピーも適用します。これにより、データベースを復元しなければならない場 合に、最新の状態に戻すことができます。 第 6 章 データの変更 191 ユーザに対して透過的に行われるデータ レプリケーションは、致命的な障害からの もう 1 つの保護対策です。 192 IBM Informix: SQL ガイド: チュートリアル 第 7 章 外部データベースのデータへのアクセスおよび修正 他のデータベース サーバへのアクセス . . . . ANSI データベースへのアクセス . . . . . 外部データベース サーバ間の結合の作成 . . 外部ルーチンへのアクセス . . . . . . . リモート データベース アクセスの制約事項 . . SQL 文およびロギング モード . . . . . 外部データベース オブジェクトへのアクセス . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 193 194 194 194 194 195 本章について (IDS のみ) この章では、現行のデータベースにない表およびルーチンに対する問合せについて 紹介します。 他のデータベース サーバへのアクセス 外部 データベースの表およびルーチンにアクセスするには、データベース オブジ ェクト (表、ビュー、シノニム、またはルーチン) 名を修飾します。 外部データベースが、現行データベースと同じデータベース サーバにある場合、オ ブジェクト名をデータベース名とコロンで修飾します。例えば、ローカル データベ ース以外のデータベースの表を参照するには、次の SELECT 文で外部データベース から情報にアクセスします。 SELECT name, number FROM salesdb:contacts この例の問合せでは、データベース salesdb 内の表 contacts のデータを戻しま す。 リモート データベース サーバは、現行データベース サーバ以外であればどのデー タベース サーバでもかまいません。外部データベースがリモート データベース サ ーバにある場合、オブジェクト名はデータベース オブジェクト名、データベース サーバ名、およびデータベース名で修飾する必要があります。次に例を示します。 SELECT name, number FROM salesdb@distantserver:contacts この例の問合せでは、リモート データベース サーバ distantserver 上のデータベ ース salesdb にある表 contacts からデータを戻します。 外部データベースにあるデータベース オブジェクト名を指定する方法に関する構文 およびルールについては、「IBM Informix: SQL ガイド: 構文」を参照してくださ い。 ANSI データベースへのアクセス ANSI データベースでは、ownername.objectname のように、オブジェクトの所有 者 (名) がオブジェクト名に含まれます。現行データベースおよび外部データベース © Copyright IBM Corp. 1996, 2003 193 が両方 ANSI データベースである場合は、ユーザがオブジェクトの所有者である場 合を除き、所有者名を含める必要があります。次の SELECT 文では、表の完全修飾 名を使用しています。 SELECT name, number FROM salesdb@aserver:ownername.contacts ヒント: オブジェクト名は、常に明示的に修飾することができます。つまり、完全 なオブジェクト名が必須でない場合も、 database@servername:ownername.objectname のような完全な名前を使用でき ます。 ANSI データベースの詳細については、「IBM Informix: データベース設計および実 装 ガイド」を参照してください。 外部データベース サーバ間の結合の作成 結合の中でも同じ表記を使用できます。データベース名を明示的に指定する場合 は、次の例に示すように、長い表名を別名を使用して短くしなければ扱いにくくな ります。 SELECT O.order_num, C.fname, C.lname FROM masterdb@central:customer C, sales@boston:orders O WHERE C.customer_num = O.Customer_num 外部ルーチンへのアクセス 現行データベース サーバ以外のデータベース サーバのルーチンを参照するには、 ルーチン名をデータベース サーバ名とデータベース名 (リモート データベースが ANSI 準拠の場合は所有者名も) で修飾します。次の SELECT 文で例示します。 SELECT name, salesdb@boston:how_long() FROM salesdb@boston:contacts リモート データベース アクセスの制約事項 ここでは、リモート データベース アクセスに関する制約事項の概要を示します。 SQL 文およびロギング モード 次の SQL 文を、データベース全体およびデータベース サーバ全体に対して実行で きます。 SELECT CREATE VIEW LOAD INSERT CREATE SYNONYM UNLOAD UPDATE DROP DATABASE LOCK TABLE DELETE RENAME DATABASE UNLOCK TABLE DATABASE EXECUTE FUNCTION INFO CREATE DATABASE EXECUTE PROCEDURE 各文をデータベースまたはデータベース サーバ全体に対して確実に実行するには、 ローカル データベースと外部データベースが同じロギング モードである必要があ ります。 194 IBM Informix: SQL ガイド: チュートリアル 外部データベース オブジェクトへのアクセス 外部データベース オブジェクトにアクセスするには、以下の条件があります。 v これらのオブジェクトに対して適切な権限を所有している。 v 両方のデータベースが同じロケールに設定されている。 第 7 章 外部データベースのデータへのアクセスおよび修正 195 196 IBM Informix: SQL ガイド: チュートリアル 第 8 章 SQL を使用したプログラミング プログラム中の SQL . . . . . . . . . . . . . SQL API 中の SQL . . . . . . . . . . . . アプリケーション言語の SQL . . . . . . . . . 静的埋込み . . . . . . . . . . . . . . . 動的文. . . . . . . . . . . . . . . . . プログラム変数とホスト変数 . . . . . . . . . データベース サーバの呼出し . . . . . . . . . . SQL 通信領域 . . . . . . . . . . . . . . SQLCODE フィールド . . . . . . . . . . . データの終わり. . . . . . . . . . . . . 負数コード . . . . . . . . . . . . . . SQLERRD 配列. . . . . . . . . . . . . . SQLWARN 配列 . . . . . . . . . . . . . SQLERRM 文字列 . . . . . . . . . . . . . SQLSTATE 値 . . . . . . . . . . . . . . 単一行の抽出 . . . . . . . . . . . . . . . データ型の変換. . . . . . . . . . . . . . NULL データの処理 . . . . . . . . . . . . エラーの処理 . . . . . . . . . . . . . . データの終わり. . . . . . . . . . . . . ANSI 標準準拠でないデータベースのデータの終り . 重大なエラー . . . . . . . . . . . . . 集計関数とデータの終り. . . . . . . . . . デフォルト値の使用 . . . . . . . . . . . 複数行の抽出 . . . . . . . . . . . . . . . カーソルの宣言. . . . . . . . . . . . . . カーソルのオープン . . . . . . . . . . . . 行の取出し . . . . . . . . . . . . . . . データの終りの検出 . . . . . . . . . . . INTO 節の位置決め . . . . . . . . . . . カーソル入力モード . . . . . . . . . . . . カーソルのアクティブ セット . . . . . . . . . アクティブ セットの作成 . . . . . . . . . 順カーソルのアクティブ セット . . . . . . . スクロール カーソルのアクティブ セット. . . . アクティブ セットと並行性 . . . . . . . . カーソルの使用: 部品展開 . . . . . . . . . . 動的 SQL. . . . . . . . . . . . . . . . . 文の PREPARE 文による処理 . . . . . . . . . PREPARE 文で処理された SQL 文の実行 . . . . . 動的ホスト変数. . . . . . . . . . . . . . PREPARE 文で処理された文の解放 . . . . . . . 実行の高速化 . . . . . . . . . . . . . . データ定義文の埋込み . . . . . . . . . . . . GRANT 文と EVOKE 文の埋込み . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . © Copyright IBM Corp. 1996, 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 198 199 199 200 200 201 201 202 202 203 203 204 205 205 206 206 207 208 208 208 208 208 209 209 210 210 211 211 211 212 213 213 213 214 214 215 216 217 218 218 219 219 219 220 222 197 本章について これまでの章では、SQL を対話 (interactive) 型コンピュータ言語として扱い、説明 してきました。つまりユーザが SELECT 文をデータベース サーバに直接入力し、 それに対してロール バックされる行が表示されると想定しました。 実際はもう少し複雑です。ユーザとデータベース サーバの間には、何層ものソフト ウェアが存在しています。データベース サーバはデータをバイナリ形式で保持して いるため、表示の前にデータのフォーマットが必要です。また、データベース サー バが、大量のデータを一度にユーザに戻すことはありません。プログラムの要求に 応じて、1 行ずつ戻します。 DB–Access でデータベースの情報にアクセスするには、対話式アクセスを使用しま す。これは、ESQL/C のような SQL API で記述されたアプリケーション プログラ ム、または SPL のようなアプリケーション言語を介して行われます。 ほとんどのプログラムでは、内部に SQL 文を埋め込んで実行し、データベース サ ーバからデータを抽出することができます。この章では、データベース操作をどの ように行うか、また、データベース操作を行うプログラムをどのように作成するか について説明します。 この章では、SQL プログラミングに使用するすべての言語に共通する概念を紹介し ます。特定のプログラム言語を使用して実用的なプログラムを作成するには、ま ず、その言語をよく理解していることが必要です。プログラム作成のプロセスは各 言語により異なるため、詳細については、ご使用の言語の IBM Informix SQL API のマニュアルを参照してください。 プログラム中の SQL プログラムは複数の言語のうち任意の言語で作成することができ、 SQL 文をその プログラム言語の通常の文として、プログラムの他の文の間に混合させることがで きます。これらの SQL 文は、プログラムに埋め込まれ、そのプログラムには埋込 み SQL (略して ESQL) が含まれます。 SQL API 中の SQL ESQL の製品は、IBM Informix SQL API (アプリケーション プログラム インター フェイス) です。 IBM では、C プログラミング言語用の SQL API を提供しま す。 図 354 に、SQL API が行う処理を示します。まず SQL 文を実行可能コードとして 扱い、ソース プログラムを作成します。ソース プログラムは、埋め込み SQL プ リプロセッサ、つまり埋め込み SQL 文を格納するプログラムによって処理され、 それらの文を一連のプロシジャ呼出しと特定のデータ構造に変換します。 198 IBM Informix: SQL ガイド: チュートリアル 図 354. ESQL 文を含むプログラムの処理概要 変換されたソース プログラムは、そのプログラム言語のコンパイラへ渡されます。 コンパイラ出力は、SQL API プロシジャの静的または動的 ライブラリとリンクし た後に、実行可能プログラムになります。プログラムが実行されると、 SQL API ライブラリ プロシジャが呼び出されます。これらは、データベース サーバとの通 信をセットアップして、SQL 操作を実行します。 実行可能プログラムをスレッド化ライブラリ パッケージとリンクさせると、 ESQL/C マルチスレッド アプリケーション を作成できます。マルチスレッド アプ リケーションは、制御スレッドを多く含むことができます。マルチスレッド アプリ ケーションは、プロセスを、それぞれ独立して実行できる複数の実行スレッドに分 割します。マルチスレッドの ESQL/C アプリケーションの最大の利点は、各スレッ ドがデータベース サーバに対して複数の実効接続を同時に確立できるという点で す。非スレッド ESQL/C アプリケーションが 1 つ以上のデータベースに対して複 数の接続を確立できるのに対し、マルチスレッドのアプリケーションは 1 回に 1 つの実効状態の接続のみ確立します。マルチスレッド ESQL/C アプリケーション は、スレッドあたり 1 つの実効状態の接続を確立でき、アプリケーションごとに複 数のスレッドを持つことができます。 マルチスレッド アプリケーションの詳細については、「IBM Informix: ESQL/C Programmer’s Manual」を参照してください。 アプリケーション言語の SQL SQL API 製品が SQL をホスト言語に埋め込むことができる一方、 SQL を一連の 文の一部に最初から含む言語もあります。 IBM Informix ストアド プロシジャ (SPL) は、SQL を、一連の文に本来含まれるものとして使用します。アプリケーシ ョン プログラムを作成するには、SQL API 製品を使用します。データベースに格 納され、アプリケーション プログラムによって呼び出されるルーチンは、SPL を使 用して作成します。 静的埋込み SQL 文は、静的埋込みまたは動的埋込みによりプログラム中に埋め込むことができ ます。より簡単で一般的な方法は、静的埋込み です。これは、SQL 文をコードの 一部として作成する方法です。この文は、ソース テキストの固定的な部分であるた め、静的 になります。静的埋込みの詳細については、206 ページの『単一行の抽 出』および 209 ページの『複数行の抽出』を参照してください。 第 8 章 SQL を使用したプログラミング 199 動的文 アプリケーションの中には、ユーザ入力に応答して動的に SQL 文を構成する機能 を必要とするものがあります。ユーザからの入力に応じて異なる列を選択したり、 異なる判断基準を行に適用したりしなければならないプログラムがその例です。 動的 SQL では、プログラムは SQL 文をメモリ内に文字の列として構成し、それを データベース サーバに受け渡して実行します。動的文は、ソース プログラムのテ キストの一部ではなく、プログラムを実行する時点でメモリ内に作成されます。詳 しくは、216 ページの『動的 SQL』を参照してください。 プログラム変数とホスト変数 アプリケーション プログラムでは、SQL 文の中でプログラム変数を使用できま す。 SPL では、プログラム変数を構文が許可するとおりに SQL 文に書き込みま す。例えば、DELETE 文では、その WHERE 節にプログラム変数を使用できま す。 次のコードの例は、SPL 内のプログラム変数を示しています。 CREATE PROCEDURE delete_item (drop_number INT) . . . DELETE FROM items WHERE order_num = drop_number . . . 埋込み SQL 文を使用するアプリケーションでは、SQL 文でプログラム変数の内容 を参照できます。埋込み SQL 文で名前が付けられたプログラム変数は、その SQL 文がプログラム内でゲスト と認識されるために、ホスト変数 と呼ばれます。 次の例は、IBM Informix ESQL/C ソース プログラムに埋め込まれる場合に表示さ れることがある DELETE 文です。 EXEC SQL delete FROM items WHERE order_num = :onum; このプログラムでは、第 6 章に記載したような、一般的な DELETE 文が使用され ます。 ESQL/C プログラムを実行すると、表 items の行を削除することができま す。複数行の削除も可能です。 この文には新しい機能が 1 つ含まれています。この機能は列 order_num を :onum と書き込まれた項目と比較します。これはホスト変数の名前を表します。 それぞれの SQL API 製品には、ホスト変数が SQL 文のコンテキストに表示され るときに、そのホスト変数の名前を区切る方法があります。 ESQL/C では、ホスト 変数はドル記号 ($) またはコロン (:) で導入できます。コロンには、ANSI との互 換性があります。この例文は、注文番号が :onum という名前のホスト変数の現在 の内容と等しい行を削除するよう、データベース サーバに要求しています。この数 値変数は、プログラム内のこれよりも前の部分で宣言され、値を設定されていま す。 IBM Informix ESQL/C では、SQL 文をドル記号 ($) または EXEC SQL で導入で きます。 200 IBM Informix: SQL ガイド: チュートリアル 前述の例に示すように構文上の違いは些細なものにすぎず、本質的なポイントは、 SQL API と SPL の言語では次のタスクを実行できるということです。 v SQL 文を、ホスト言語の実行可能文としてソース プログラムに埋め込むことが できる。 v SQL 式内で定数値と同様にプログラム変数を使用できる。 プログラミング経験のある方なら、すぐにその可能性を把握できます。例では、削 除対象の行の注文番号はホスト変数 onum から渡されます。この値は、プログラム からアクセス可能なソースであれば、どのソースからでも受け取ることができま す。ファイルから読み込んだ値、プログラムが発行したプロンプトに応じてユーザ が入力した値、あるいは、データベースから読み込んだ値の場合などが考えられま す。 DELETE 文自体がサブルーチンの一部である可能性があります。その場合は、 onum はそのサブルーチンのパラメータになります。そのサブルーチンは 1 回だ け、あるいは繰り返し呼び出されます。 つまり、SQL 文をプログラムに埋め込む場合、ホスト言語のすべての機能をそれら の文に適用できます。 SQL を多数のインターフェイスの下に隠して、さまざまな 方法でその機能を装飾することもできます。 データベース サーバの呼出し SQL 文を実行すると、データベース サーバがサブルーチンとして必ず呼び出され ます。プログラムとデータベース サーバの間で情報の受渡しが必要です。 プログラムとデータベース サーバとの間の通信の一部はホスト変数を介して行われ ます。 SQL 文の内部に指定したホスト変数は、データベース サーバにアクセスす るプロシジャ呼出しのパラメータと考えることができます。先の例では、ホスト変 数は WHERE 節のパラメータとして機能しています。 209 ページの『複数行の抽 出』で説明しているように、ホスト変数はデータベース サーバが戻すデータを受け 取ります。 SQL 通信領域 データベース サーバは、SQL 通信領域 (SQLCA) と呼ばれるデータ構造体に常に 結果コードを戻します。また、その操作の結果に関するその他の情報も戻すことが あります。データベース サーバが、ユーザ定義ルーチンで SQL 文を実行する場 合、呼出しアプリケーションの SQLCA には、そのルーチンで SQL 文によってト リガされた値が含まれます。 SQLCA の基本フィールドは、202 ページから 204 ページにリストされています。 SQLCA などのデータ構造体の説明に使用する構文や、そのデータ構造体のフィール ドの参照に使用する構文は、各プログラム言語によって異なります。詳細について は、SQL API の資料を参照してください。 特に、SQLERRD 配列と SQLWARN 配列の要素を命名するサブスクリプトは異な ります。配列要素の番号は、IBM Informix ESQL/C ではゼロから始まりますが、他 の言語では 1 から始まります。この説明では、「3 番目」などの語でフィールドに 特定の名前が付けられていますが、使用するプログラム言語の構文に合うように、 これらの語を変換することが必要です。 第 8 章 SQL を使用したプログラミング 201 また、GET DIAGNOSTICS 文の SQLSTATE 変数を使用して、エラーを検出、処 理、および診断することも可能です。 205 ページの『SQLSTATE 値』を参照して ください。 SQLCODE フィールド SQLCODE フィールドは、データベース サーバの 1 次復帰コードです。各 SQL 文の後は、202 ページに示すように、SQLCODE が整数値に設定されます。ゼロ (0) は文の実行が成功し、エラーがないことを示します。特に、データをホスト変数に 戻す文の場合は、コードが 0 ならば、データがホスト変数に戻されて使用可能であ ることを示します。コードが非ゼロ値のときは、データがホスト変数に戻されてお らず、使用不可であることを示します。有用なデータは、ホスト変数に戻されませ ん。 表 3. SQLCODE の値 戻り値 意味 値 < 0 エラー コードを指定する。 値 = 0 成功したことを示す。 0 < 値 < 100 DESCRIBE 文の後で、記述された SQL 文の型を示す整数値。 100 問合せが正常に実行され、行を戻さなかった場合にNOT FOUND 状態を 示す。NOT FOUND 状態は、ANSI 準拠のデータベースで INSERT INTO/SELECT、UPDATE、DELETE、または SELECT...INTO TEMP 文 が行を戻さなかった場合にも発生します。 データの終わり データベース サーバは、文が正常に実行され、行が検出されなかった場合、 SQLCODE を 100 に設定します。これには 2 つの状況が考えられます。 まず、問合せでカーソルを使用している場合です。 (209 ページの『複数行の抽 出』で、カーソルを使用する問合せについて説明しています。) このような問合せ では、FETCH 文により各値がアクティブ セットからメモリ内に抽出されます。最 後の行が抽出されると、以降の FETCH 文はデータを戻すことができません。この 状態になると、データベース サーバは SQLCODE を 100 に設定し、データの終わ りか、行が検出できない ことを示します。 もう 1 つのケースは、カーソルを使用しない問合せの場合です。このケースでは、 問合せ条件を満たす行がなかった場合、データベース サーバは SQLCODE を 100 に設定します。 ANSI 標準に準拠しないデータベースでは、SELECT 文が行を戻さ ない場合のみ、SQLCODE が 100 に設定されます。 米国規格協会 (ANSI) ANSI 標準準拠データベースでは、SELECT、DELETE、UPDATE、および INSERT 文のいずれの場合でも、行が戻されない場合には SQLCODE が 100 に設定されま す。 米国規格協会 (ANSI) の終り 202 IBM Informix: SQL ガイド: チュートリアル 負数コード 文の実行中に予期されなかった要素が発生して実行が失敗すると、データベース サ ーバはエラーを示す負の番号を SQLCODE に戻します。これらのコードの意味は、 オンライン エラー メッセージ ファイルに記述されます。 SQLERRD 配列 SQLCODEに設定されるエラー コードの一部は一般的なエラーを示します。データ ベース サーバでは、SQLERRD の 2 番目のフィールドに、より詳細なコードを設 定できます。これにより、データベース サーバ入出力ルーチンまたはオペレーティ ング システムで発生したエラーを確認できます。 SQLERRD 配列内の整数は、異なる文に続く異なる値に設定されます。配列の 1 番 目および 4 番目の要素は、IBM Informix ESQL/C でのみ使用されます。203 ペー ジの表 4 に、フィールドの使用方法を示します。 これらの補足的な詳細情報は便利です。例えば、3 番目のフィールドの値を使用し て、削除や更新された行が何行であったかを報告できます。ユーザが入力した SQL 文をプログラムが PREPARE 文で処理しているときにエラーが検出された場合は、 5 番目のフィールドの値を使用するとエラーの場所を特定することができます。 (DB–Access では、ユーザがエラー後に文を修正するよう要求するときに、この機能 を使用してカーソルを配置します。) 表 4. SQLERRD のフィールド フィールド 意味 1 番目 SELECT、UPDATE、INSERT、または DELETE 文のための PREPARE 文が正 常に実行された後、または選択カーソルがオープンされた後、影響を受けた行 の見積り数がこのフィールドに含まれる。 2 番目 SQLCODE にエラー コードが含まれている場合は、このフィールドに、ゼロも しくは ISAM エラー コードと呼ばれる追加のエラー コードのどちらかが含ま れる。これは、主なエラーの原因を示す。単一の行に対して挿入操作が成功し た後では、このフィールドに、その行に対して生成されたあらゆるシリアル (SERIAL) 型の値が含まれる。 3 番目 複数行に対して挿入、更新、または削除操作が成功した後では、このフィール ドに、処理された行の数が含まれる。複数行の挿入、更新、または削除操作が エラーで終了した後では、このフィールドに、エラーが検出される前に正常に 処理された行の数が含まれる。 4 番目 SELECT、UPDATE、INSERT、または DELETE 文のための PREPARE 文が正 常に実行された後、または選択カーソルがオープンされた後、ディスク アクセ ス数と処理された行の総数の加重値の見積りが、このフィールドに含まれる。 5 番目 PREPARE、EXECUTE IMMEDIATE、DECLARE、または静的 SQL 文での構文 エラーの後、このフィールドに、エラーが検出された文のテキストのオフセッ トが含まれる。 6 番目 選択された行の取出しが成功したか、あるいは挿入、更新、または削除操作が 成功した後では、このフィールドに、最後に処理された行の行識別子 (物理アド レス) が含まれる。この行識別子の値が、データベース サーバがユーザに戻す 行に対応するものかどうかは、データベース サーバが問合せ (特に SELECT 文についての問合せ) をどのように処理するかによる。 第 8 章 SQL を使用したプログラミング 203 SQLWARN 配列 SQLWARN 配列を構成する 8 つの文字 (CHAR) 型フィールドのフィールドは、空 白か W のどちらかに設定され、さまざまな状態を示します。これらの意味は直前に 実行された文によって異なります。 データベースがオープンされたとき、CONNECT、DATABASE、または CREATE DATABASE 文の後に、一連の警告フラグが表示されます。これらのフラグはデー タベース全体の特性を示します。 警告フラグ以外のフラグは、上記以外のすべての文を実行した後に表示されます。 これらのフラグは、その文の実行中に発生した異常なイベントを示します。フラグ により、SQLCODE だけでは十分に記述できないイベントを示す場合もあります。 SQLWARN 値の両方のセットの要約は、204 ページに記載しています。 表 5. SQLWARN のフィールド フィールド データベースに対してオープン または接続する場合 204 その他すべての操作の場合 1 番目 他の警告フィールドが W に設定され 他の警告フィールドが W に設定されてい ているときは、W に設定されます。 るときは、W に設定されます。 このフィールドが空白の場合、他の フィールドをチェックする必要はあ りません。 2 番目 現在オープンしているデータベース FETCH または SELECT...INTO 文を使用 がトランザクション ログを使用する して列値がホスト変数に取り出され、切 り捨てられた場合に W に設定されます。 場合は、W に設定されます。 REVOKE ALL 文の実行時、7 つの表レ ベル アクセス権すべてが取り消されない 場合に、W に設定されます。 3 番目 現在オープンしているデータベース が ANSI 標準準拠の場合、W に設定 されます。 FETCH または SELECT 文が、集計関数 (SUM、AVG、MIN、MAX) 値 NULL を 戻す場合、W に設定されます。 4 番目 データベース サーバが Dynamic Server の場合、W に設定されます。 SELECT...INTO、FETCH...INTO、または EXECUTE...INTO 文の実行時、選択リス トの項目数が、それを受け取るために INTO 節に渡されるホスト変数の数と異 なる場合に、W に設定されます。 GRANT ALL 文の実行時、7 つの表レベ ル アクセス権すべてが付与されない場合 に、W に設定されます。 5 番目 データベース サーバが 10 進数 (DECIMAL) 型フォームに実数 (FLOAT) 型を格納する場合に、W に 設定されます (ホスト システムに実 数 (FLOAT) 型のサポートがない場 合)。 WHERE 節をもたない UPDATE 文また は DELETE 文を PREPARE 文で処理し た場合、DESCRIBE 文の後で、W に設定 されます。 6 番目 予約済み。 ANSI 標準の SQL 構文を使用しない文 の実行後、W に設定されます。 (DBANSIWARN 環境変数が設定されて いることが前提となります。) IBM Informix: SQL ガイド: チュートリアル 表 5. SQLWARN のフィールド (続き) フィールド データベースに対してオープン または接続する場合 その他すべての操作の場合 7 番目 アプリケーションが、データ レプリ ケーション ペアの副サーバであるデ ータベース サーバに接続されている 場合、W に設定されます。これは、 このサーバが読取り操作のみに使用 できることを意味します。 問合せ処理中にデータ フラグメント (dbspace) がスキップされたとき (DATASKIP 機能がオンに設定されてい るとき) は W に設定されます。 8 番目 クライアントの DB_LOCALE がデ 予約済み。 ータベース ロケールと一致しない場 合、W に設定されます。詳しくは、 「IBM Informix: GLS ユーザーズ ガ イド」を参照してください。 SQLERRM 文字列 SQLERRM には 70 バイトまでの文字列を格納できます。 SQLERRM 文字列に は、エラー メッセージに使用する表名などの識別子が含まれます。一部のネットワ ーク アプリケーションでは、この配列に、ネットワーキング ソフトウェアによっ て生成されたエラー メッセージが含まれています。 制約違反によって INSERT 操作が失敗した場合は、違反の起きた制約の名前が SQLERRM に書き込まれます。 ヒント: エラー文字列が 70 バイトを超える場合は、オーバーフローが自動的に廃 棄されます。このため、コンテキストによっては、ランタイム エラーに関 する情報が失われる可能性があります。(例えばエラー文字列が 70 バイト を超える識別子を含む場合など。) SQLSTATE 値 IBM Informix ESQL/C のような特定の IBM Informix 製品では、X/Open および ANSI SQL 標準に準拠する SQLSTATE 値をサポートします。 GET DIAGNOSTICS 文は SQLSTATE 値を読み込み、SQL 文の実行後にエラーを診断し ます。データベース サーバは結果コードを 5 文字の文字列で戻し、この文字列は SQLSTATE 変数に格納されます。 SQLSTATE エラー コードまたは SQLSTATE 値は、実行された最新の SQL 文に関する情報を示します。 v 文の実行は成功した。 v 文の実行は成功したが、警告が生成された。 v 文の実行は成功したが、データが生成されなかった。 v 文の実行が失敗した。 GET DIAGNOSTICS 文、SQLSTATE 変数、および SQLSTATE 復帰コードの意味 については、「IBM Informix: SQL ガイド: 構文 」の GET DIAGNOSTICS 文に関 する説明を参照してください。 ヒント: ご使用の IBM Informix 製品が GET DIAGNOSTICS および SQLSTATE を サポートする場合は、それらをエラーの検出、処理、および診断に使用す 第 8 章 SQL を使用したプログラミング 205 る主構造体として利用することをお勧めします。 SQLSTATE は ANSI に 準拠しており、複数のエラーを検出することができます。 単一行の抽出 SELECT 文が戻す行のセットは、その文に対するアクティブ セット です。単一行 SELECT 文は、1 つの行を戻します。埋込み SELECT 文を使用すると、データベ ースから 1 行を抽出して、ホスト変数に代入することができます。ただし、 SELECT 文により複数行のデータが戻される場合は、カーソルを使用して、一度に それらの行が抽出されるようにする必要があります。複数行の選択操作について は、209 ページの『複数行の抽出』に記載しています。 1 行のデータを抽出する場合は、SELECT 文をプログラム中に埋め込むだけで済み ます。次の例では、IBM Informix ESQL/C を使用して埋込み SELECT 文を作成す る方法を示します。 EXEC SQL SELECT avg (total_price) INTO :avg_price FROM items WHERE order_num in (SELECT order_num from orders WHERE order_date < date(’6/1/98’) ); 第 2 章または第 5 章に示す例と、この文では、INTO 節のみが異なります。この 節を使用すると、生成されたデータを受け取るホスト変数を指定することができま す。 埋込み SELECT 文が実行されると、データベース サーバは問合せを実行します。 この例文では集計関数が戻す値が選択されるため、生成されるデータは 1 行です。 この行は1列のみで構成され、列の値は avg_price という名前のホスト変数に格納 されます。このプログラムの後続の行で、このホスト変数の値を使用できます。 この種の文を使用すると、単一行のデータを抽出してホスト変数に代入することが できます。その単一行は、必要な数の列を含みます。問合せにより、複数行のデー タが生成された場合には、データベース サーバはデータを戻すことができません。 代わりに、エラー コードを戻します。 INTO 節に指定するホスト変数の数は、必ず選択リストで指定する項目の数と同じ にしてください。ホスト変数の数と選択リストの項目の数が一致しない場合は、デ ータベース サーバはできるだけ多くの値を戻し、SQLWARN の 4 番目のフィール ドに警告フラグを設定します。 データ型の変換 次の ESQL/C の例は、それ自体が 10 進数 (DECIMAL) 型値である 10 進数 (DECIMAL) 型列の平均を抽出します。ただし、10 進数 (DECIMAL) 型列の平均が 格納されるホスト変数のデータ型は同じである必要はありません。 EXEC SQL SELECT avg (total_price) into :avg_price FROM items; ESQL/C コードの前述の例のデータを受け取る変数 avg_price の宣言は示していま せん。次の宣言のどれでも可能です。 206 IBM Informix: SQL ガイド: チュートリアル int avg_price; double avg_price; char avg_price[16]; dec_t avg_price; /* typedef of decimal number structure */ SQL 文で使用されている各ホスト変数のデータ型は、その文と一緒にデータベース サーバに渡されます。データベース サーバは、列の値をできるだけその受取り先の ホスト変数のデータ型に変換します。可能な限りの変換が実行されますが、一部の 変換では精度が落ちます。この例の結果は、ホスト変数のデータ型によって、次の ように変わります。 データ型 結果 実数 (FLOAT) 型 データベース サーバは 10 進数型の結果を実数 (FLOAT) 型に変換しま す。その場合、小数点以下の桁がいくつか切り捨てられることがありま す。 10 進数型の値が実数 (FLOAT) 型で表現可能な最大値を超える場合 はエラーが戻されます。 整数 (INTEGER) 型 データベース サーバは結果を整数 (INTEGER) 型に変換します。その場 合、必要に応じて小数点以下の桁が切り捨てられます。変換後の数値の整 数部が大きすぎてホスト変数に収まらない場合はエラーが戻されます。 文字 データベース サーバが 10 進数値を文字 (CHARACTER) 型文字列に変 (CHARACTER) 型 換します。文字列が長すぎてホスト変数に収まらない場合は、文字列の一 部が切り捨てられます。 SQLWARN の 2 番目のフィールドは W に設 定され、SQLSTATE 変数の値は 01004 になります。 NULL データの処理 プログラムが抽出した値が NULL の場合について説明します。 NULL 値はデータ ベースに格納できますが、プログラム言語でサポートされているデータ型は NULL を認識しません。プログラムは何らかの方法で NULL を識別して、NULL がデー タとして処理されるのを防ぐ必要があります。 標識変数 は、SQLAPI でこのニーズを満たします。標識変数は特別なホスト変数 で、NULL を受け取る可能性があるホスト変数と組み合わせて使用されます。主変 数にデータを入れるとき、データベース サーバはその変数が NULL かどうかを示 す特別な値を標識変数に入れます。次の IBM Informix ESQL/C 例では、1 行が選 択され、1 つの値がホスト変数 op_date に抽出されます。 EXEC SQL SELECT paid_date INTO :op_date:op_d_ind FROM orders WHERE order_num = $the_order; if (op_d_ind < 0) /* data was null */ rstrdate (’01/01/1900’, :op_date); その値が NULL の可能性があるため、op_d_ind という名前の標識変数がホスト変 数に関連付けられています。この標識変数は、プログラム内の任意の行で short int 型として宣言されていなければなりません。 SELECT 文の実行後に、標識変数の値が負かどうかがテストされます。負の値 (通 常は -1) は主変数に抽出された値が NULLであることを示します。この変数が NULL の場合は、ESQL/C ライブラリ関数によってホスト変数にデフォルト値が割 り当てられます。 rstrdate 関数は IBM Informix ESQL/C 製品の一部です。 第 8 章 SQL を使用したプログラミング 207 標識変数をホスト変数に関連付ける構文は、プログラム言語によって異なります が、ここで説明した原理はどの言語でも同じです。 エラーの処理 データ型間の変換はデータベース サーバが自動的に処理しますが、SELECT 文には 問題が発生する可能性がまだいくつかあります。 SQL プログラミングでは、他の プログラムと同様に、このような状況に備えてエラーの発生を予測し、エラーに対 し万全の対策を講じる必要があります。 データの終わり 問合せがまったく行を戻さないということも珍しくありません。このイベントは、 SELECT に続いて、SQLSTATE コード 02000 および SQLCODE 内のコード 100 でシグナル通知されます。このコードはエラーか単に行が存在しないことを示しま す。どちらを示すかはアプリケーションによって判断しなくてはなりません。例え ば、別の表から取り出したばかりのキー値を使用して行を読み込んでいるときのよ うに、行が存在しなければならないことがはっきりしている場合、データの終わり を示すコードはプログラムの論理に重大な障害があることを示しています。これに 対し、ユーザが入力した値や、プログラムより信頼性の少ないソースを基にして行 を選択している場合は、データがなくてもエラーではありません。 ANSI 標準準拠でないデータベースのデータの終り 使用しているデータベース が ANSI 標準準拠でない場合、データの終わりの復帰 コード 100 は SELECT 文に続く SQLCODE にのみ設定されます。また、 SQLSTATE 値は 02000 に設定されます。(INSERT、UPDATE、および DELETE な どの他の文は、それらの文によって影響を受けた行数を示すように SQLERRD の 3 つ目の要素を設定します。この内容については、第 9 章に記載しています。) 重大なエラー SQLCODE を負の値に設定したり、SQLSTATE を 00、01、または 02 以外の値で 始まる値に設定するようなエラーは、通常重大なエラーと考えられます。こうした エラーが、開発したプログラムや製品において報告されたことはごくまれです。し かし、稀有なケースだからといって、無視することはできません。 例えば、「指定された表がデータベースにない」という意味の -206 というエラー コードが戻ってきたとします。このエラーが発生するのは、プログラムが作成され てから後に誰かが表を削除した場合、あるいは論理エラーもしくは入力ミスによ り、プログラムが間違ったデータベースをオープンした場合です。 集計関数とデータの終り SUM、MIN、または AVG などの集計関数を使用する SELECT 文は、WHERE 節 の条件を満たす行がない場合でも、通常 1 つ以上のデータ行を戻します。条件を満 たす行がない場合の集計関数の値は NULL となりますが、NULL は値と見なされ ます。 条件を満たす行が 1 行以上あり、それらすべての行に NULL が入っている場合 も、集計関数の値は NULL になります。いずれの行にも基づかない集合値と、すべ てに NULL が含まれる複数行に基づく集合値の差を検出するには、文に COUNT 関数をインクルードし、集合値の値に対し標識変数を設定することが必要になりま す。これによって、次の場合を区別できます。 208 IBM Informix: SQL ガイド: チュートリアル Count の値 標識変数 意味 0 -1 ゼロ行を選択。 >0 -1 いくつかの行を選択。すべての値が NULL。 >0 0 いくつかの非 NULL 行を選択。 デフォルト値の使用 不可避のエラーの処理には、さまざまな方法があります。アプリケーションによっ ては、通常の状態を処理する機能より、エラー処理をする機能の方が多いこともあ ります。ここでは、デフォルト値を使用してエラーを処理する方法を例で示しま す。 avg_price = 0; /* set default for errors */ EXEC SQL SELECT avg (total_price) INTO :avg_price:null_flag FROM items; if (null_flag < 0) /* probably no rows */ avg_price = 0; /* set default for 0 rows */ この例は、状態に応じて次のように処理します。 v NULL 以外の行が 1 行以上選択された場合は、正しい値が戻され、使用されま す。この結果はもっとも頻繁に発生すると思われます。 v 問合せで 1 行も選択されなかった場合や、NULL が許されない列 total_price に NULL が含まれる行のみが選択された場合は、標識変数が設定され、デフォル ト値が割り当てられます。 v 重大なエラーが発生した場合は、ホスト変数の値は最初に指定したデフォルト値 のまま変わりません。プログラムのこの箇所では、プログラマはこのようなエラ ーをトラップし、報告する必要はありません。 複数行の抽出 問合せによって戻される行が 2 行以上になる可能性がある場合は、プログラム中の 問合せの実行方法を変えなければなりません。複数行を戻す問合せは 2 段階で処理 されます。まず、プログラムが問合せを開始します。すぐに戻されるデータはあり ません。次に、プログラムが一度に 1 行ずつデータを要求します。 これらの操作は、カーソル と呼ばれる特別のデータ オブジェクトを使って行われ ます。カーソルは、問合せの現行状態を表すデータ構造体です。通常のプログラム の操作の流れは、次のようになります。 1. プログラムは、カーソルとそれに関連した SELECT 文を宣言 します。これは、 単にカーソルを保留するための記憶域を割り当てるだけです。 2. カーソルがオープン され、これによってカーソルと関連付けられた SELECT 文 の実行が開始され、エラーがあれば検出されます。 3. プログラムは、1 行のデータをホスト変数に取り出して 処理します。 4. プログラムは、最後の行が取り出された後にカーソルをクローズ します。 5. カーソルが不要になると、プログラムではカーソルを解放 して、使用するリソ ースの割当てを解除します。 第 8 章 SQL を使用したプログラミング 209 これらの操作は、DECLARE、OPEN、FETCH、CLOSE、および FREE と呼ばれる SQL 文で実行されます。 カーソルの宣言 カーソルの宣言には DECLARE 文を使用します。この文はカーソルを命名し、その 用途を指定し、カーソルを文と関連付けます。次の例は、IBM Informix ESQL/C で 書かれています。 EXEC SQL DECLARE the_item CURSOR FOR SELECT order_num, item_num, stock_num INTO :o_num, :i_num, :s_num FROM items FOR READ ONLY; この宣言ではカーソルを the_item と命名し、カーソルを SELECT 文と関連付けて います。 (カーソルを INSERT 文と関連付ける方法については、第 9 章に記載し ています。) この例の SELECT 文には、INTO 節が含まれます。INTO 節は、どの変数がデータ を受け取るか指定します。また、FETCH 文を使用して、データを受け取る変数を指 定できます。これについては、211 ページの『INTO 節の位置決め』で説明しま す。 DECLARE 文は、データベースに対する操作を行うものではなく、カーソルの機能 を確立し、カーソルに記憶域を割り当てる文です。この例のカーソルを使用する と、表 items の行を始めから終わりまで 1 回読み込むことができます。カーソル の宣言方法によっては順方向にも逆方向にも読み込むことができます。詳細は、212 ページの『カーソル入力モード』を参照してください。このカーソルは、FOR UPDATE 節を指定して宣言されていないため FOR READ ONLY と指定され、デ ータの変更には使用されません。カーソルを使用するデータの修正については、第 9 章で説明します。 カーソルのオープン 使用準備ができると、カーソルはオープンされます。 OPEN 文がカーソルを起動し ます。このとき、カーソルに関連付けられた SELECT 文がデータベース サーバに 渡され、データベース サーバは一致する行の探索を始めます。データベース サー バは、表の最初の行が検出されるか構築されるまで問合せを処理します。データベ ース サーバは、実際にその行のデータを戻すのではなく、復帰コードを SQL API の SQLSTATE および SQLCODE に設定します。次の例に、ESQL/C 内の OPEN 文を示します。 EXEC SQL OPEN the_item; 文が実行されるとき初めて、データベース サーバが問合せを認識するため、エラー が検出される可能性があります。カーソルのオープン後、プログラムは SQLSTATE と SQLCODE をテストする必要があります。 SQLSTATE の値が 02000 を超える 場合、または SQLCODE に負の数値が含まれる場合は、そのカーソルを使用できま せん。 SELECT 文にエラーがあったり、他の問題がデータベース サーバに文を実 行させないようにしていたりする場合があります。 210 IBM Informix: SQL ガイド: チュートリアル SQLSTATE が 00000 と等しい場合、または SQLCODE にゼロが含まれる場合、 SELECT 文は構文上有効であり、カーソルを使用することができます。ただし、こ の時点ではカーソルが行を生成するかどうかはわかりません。 行の取出し プログラムは、FETCH 文を使用して、出力の各行を抽出します。 FETCH 文はカ ーソルを命名し、データを受け取るホスト変数も命名します。次に、完了した IBM Informix ESQL/C コードを示します。 EXEC SQL DECLARE the_item CURSOR FOR SELECT order_num, item_num, stock_num INTO :o_num, :i_num, :s_num FROM items; EXEC SQL OPEN the_item; while(SQLCODE == 0) { EXEC SQL FETCH the_item; if(SQLCODE == 0) printf("%d, %d, %d", o_num, i_num, s_num); } データの終りの検出 この例では、OPEN 文がエラーを戻すと、WHILE 節の条件によりループの実行を 回避します。同じ条件で、SQLCODE が 100 に設定され、データの終わりが示され る場合、ループが終了します。ただし、SQLCODE の値は、ループの内部でもテス トされています。これが必要なのは、SELECT 文が有効でも一致する行が検索され ない場合は、OPEN 文がゼロを戻すのに対し、最初の取出しでは 100 (データの終 わり) が戻されたり、全くデータが戻されないことがあるためです。この例のルー プは、次のように記述し直すことができます。 EXEC SQL DECLARE the_item CURSOR FOR SELECT order_num, item_num, stock_num INTO :o_num, :i_num, :s_num FROM items; EXEC SQL OPEN the_item; if(SQLCODE == 0) EXEC SQL FETCH the_item; /* fetch 1st row*/ while(SQLCODE == 0) { printf("%d, %d, %d", o_num, i_num, s_num); EXEC SQL FETCH the_item; } このように記述し直すと、戻される行が存在しない場合が先に処理されるため、ル ープ内で 2 回目の SQLCODE のテストは行われません。ただし、このように書き 直しても、測定には現れない程度のパフォーマンスの差しかありません。SQLCODE のテストに要する時間コストは、FETCH 文のコストに比べごくわずかに過ぎませ ん。 INTO 節の位置決め INTO 節には、データベース サーバが戻すデータを受け取るホスト変数の名前を指 定します。これは、SELECT 文または FETCH 文のいずれかで表示される必要があ りますが、INTO 節は、SELECT 文または FETCH 文のいずれかで表示される必要 がありますが、両方の文で指定することはできません。次の例は、ホスト変数を FETCH 文で指定するように前の例を記述し直したものです。 第 8 章 SQL を使用したプログラミング 211 EXEC SQL DECLARE the_item CURSOR FOR SELECT order_num, item_num, stock_num FROM items; EXEC SQL OPEN the_item; while(SQLCODE == 0) { EXEC SQL FETCH the_item INTO :o_num, :i_num, :s_num; if(SQLCODE == 0) printf("%d, %d, %d", o_num, i_num, s_num); } このフォームによって、別々の行を別々の配置に取り出すことができます。例え ば、このフォームを使用すると、連続する行を配列内の連続する要素に取り出すこ とができます。 カーソル入力モード 入力目的のため、カーソルは 2 つのモード (順次 または スクロール) のうちのい ずれかで作動します。順カーソルが取り出すことができるのは、カーソルが置かれ ている位置の次の行のみです。そのため、オープンするごとに 1 度しか表を読み通 すことができません。スクロール カーソルは、次の行だけでなく、カーソルより前 にある任意の行を取り出すことができます。したがって、行を何回でも読み込むこ とができます。次の例は、IBM Informix ESQL/C で宣言された順カーソルを示して います。 EXEC SQL DECLARE pcurs cursor for SELECT customer_num, lname, city FROM customer; 次の例で示しているように、カーソルはオープンされた後は、次の行のデータを抽 出する順次取出しでしか使用できません。 EXEC SQL FETCH p_curs into:cnum, :clname, :ccity; 順次取出しを行うたびに、新しい行が 1 行戻されます。 スクロール カーソルは、次の IBM Informix ESQL/C からの例に示すように、キー ワード SCROLL CURSOR で宣言されます。 EXEC SQL DECLARE s_curs SCROLL CURSOR FOR SELECT order_num, order_date FROM orders WHERE customer_num > 104 スクロール カーソルを宣言した場合、さまざまな取出しオプションが使用できま す。例えば ABSOLUTE オプションは、取り出す行の絶対位置を指定します。 EXEC SQL FETCH ABSOLUTE :numrow s_curs INTO :nordr, :nodat この文が取り出す行は、ホスト変数 numrow にその位置を指定されている行で す。現在取り出した行を再度取り出すこともでき、また、選択された複数の行を最 初の行から再び走査することもできます。ただし、これらの機能を実行すると、ア プリケーションの実行速度が遅くなる場合があります。これについては次のセクシ ョンで説明します。スクロール カーソルに適用する他のオプションについては、 「IBM Informix: SQL ガイド: 構文」の FETCH 文を参照してください。 212 IBM Informix: SQL ガイド: チュートリアル カーソルのアクティブ セット オープンされたカーソルは、選択された一群の行を表します。問合せが生成する行 すべての集合は、カーソルのアクティブ セット と呼ばれます。アクティブ セット を特定の条件を満たす行の集合、カーソルをその集合の 1 行を指すポインタと考え てください。同じデータを並行して変更するプログラムが他にない場合には、この ようなモデル化は誤りではありません。 アクティブ セットの作成 カーソルがオープンされるとデータベース サーバは、選択されたデータの最初の行 を検出しようとします。簡単に検出されるか、それともかなりの作業と時間を要す るかは、問合せの表現法により異なります。次のカーソルの宣言について考えてみ ます。 EXEC SQL DECLARE easy CURSOR FOR SELECT fname, lname FROM customer WHERE state = ’NJ’ データベース サーバは、問合せの条件を満たす行が存在するかどうかを迅速に認識 でき、最初の行をすぐに検出します。この時点でデータベース サーバが検出する行 は最初の 1 行のみです。アクティブ セットを構成する残りの他の行は、まだ不明 のままです。もう 1 つのカーソルの宣言について以下に示します。 EXEC SQL DECLARE hard SCROLL CURSOR FOR SELECT C.customer_num, O.order_num, sum (items.total_price) FROM customer C, orders O, items I WHERE C.customer_num = O.customer_num AND O.order_num = I.order_num AND O.paid_date is null GROUP BY C.customer_num, O.order_num この例のカーソルのアクティブ セットは、3 つの表を結合し、さらに出力の行をグ ループ化することによって生成されます。オプティマイザが行を正しい順番で生成 するときにインデックスを使用できることもあります。しかし、ORDER BY 節や GROUP BY 節が使用されている場合は、通常、データベース サーバは生成した行 を一時表にコピーし、その一時表をソートしないと、正しい順序で行を渡すことが できません。 アクティブ セットを完全に生成して一時表に保存する場合は、カーソルがオープン されるまでにかなりの時間がかかることがあります。一時表が作られる場合には、 データベース サーバは、アクティブ セットが何行から構成されているかを知るこ とができます。しかし、この情報をプログラムから利用することはできません。そ の理由の 1 つは、オプティマイザが選択する方法を、事前に予測するのは困難だか らです。ソートと一時表の作成を省くことができる場合には、オプティマイザはそ のようにします。しかし、問合せや表のサイズや利用可能なインデックスがわずか に変わるだけで、オプティマイザが使用する方法が変わってしまうことがありま す。 順カーソルのアクティブ セット データベース サーバはできるだけ少ないリソースを使用して、カーソルのアクティ ブ セットを保持しようとします。複数行を保持する必要がなければ、次に取り出さ れる 1 行だけしか保持しません。ほとんどの順カーソルについては、1 行だけ保持 すれば解決します。データベース サーバは、取出しが実行されるたびに現行行の内 容を戻し、次の行を検出します。 第 8 章 SQL を使用したプログラミング 213 スクロール カーソルのアクティブ セット スクロール カーソルのアクティブ セットの行は、カーソルがクローズされるまで すべて保持しておかなければなりません。すべての行を保持しておかなければなら ないのは、どの行をプログラムから要求されるか予測できないからです。 データベース サーバは多くの場合、スクロール カーソルのアクティブ セットを一 時表として実行します。ただし、問合せの処理のために一時表を作成する場合は別 として、一時表をすぐに生成しないこともあります。通常はカーソルがオープンさ れるときに一時表が作成されます。データベース サーバは行を取り出すと、その行 を一時表にコピーし、プログラムに戻します。同じ行が 2 度目に取り出されるとき は一時表からその行を取り出すことができます。この方法を用いると、すべての行 を取り出す前にプログラムが問合せを中止した場合のリソースが最小になります。 取り出されない行が作成されたり、保存されたりすることはありません。 アクティブ セットと並行性 データベース サーバにアクセスしているプログラムが 1 つのみの場合は、アクテ ィブ セットを構成する行が変化してしまうことはありません。これは、ほとんどの パーソナル コンピュータに当てはまるもっとも単純な状況です。しかし、多重プロ グラミングシステム用に設計しなければならないプログラムもあります。多重プロ グラミングシステムでは、数個あるいは数十個の異なるプログラムが、同じ表を同 時に処理することが考えられます。 あるプログラムのカーソルがオープンしているときに、他のプログラムがそのカー ソルの表を更新する可能性がある場合には、アクティブ セットの概念は信頼性が高 いとはいえません。表のすべての行が変化していても、プログラムが参照できるの は 1 回に 1 行のデータのみです。 アクティブ セットの 1 行のみがデータベース サーバに保持されるような問合せの 場合、他の行は変更される可能性があります。また、プログラムが行を取り出した 直後に、別のプログラムがその行を削除または更新すると、その行はもはやアクテ ィブ セットに存在しないことがあります。 アクティブ セットの全体、あるいはその一部が一時表に保存されている場合には、 失効したデータ という問題が起こる可能性があります。これは、アクティブ セッ トの元となった実際の表の行が変更される可能性がある、という問題です。元の表 が変わっても、アクティブ セットを構成している行には、現在の表の内容が反映さ れないものもあります。 プログラムのデータの読込みのみの場合、データの失効は問題になりません。アク ティブ セットは、一時点におけるデータの断片です。行の変更が翌日あるいはミリ 秒後でも問題はありません。したがって、プログラムの実行中に発生した変化とプ ログラムが終了する間際に適用される変化との間には実際的な差はありません。 データの失効が問題になるのは、プログラムが入力データを使用して同じデータベ ースを変更しようとする場合のみです。例えば、銀行業務のアプリケーションが勘 定残高をデータベースから読み込んで変更し、変更済みのデータを同じデータベー スに書き込む場合がこれにあたります。データを変更するプログラムについては、 第 9 章を参照してください。 214 IBM Informix: SQL ガイド: チュートリアル カーソルの使用: 部品展開 カーソルとプログラム ロジックを組み合わせることにより、SQL のみでは解決で きない問題を解決できます。このような問題の 1 つが、材料目録処理とも呼ばれる 部品展開です。この問題で重要となるのは、オブジェクト同士の再帰的関係です。 再帰的関係とは、オブジェクトは他のオブジェクトを含むことができ、そのオブジ ェクトもさらに他のオブジェクトを含むことができるという関係です。 例として、メーカーの在庫を取り上げます。さまざまな部品を製造している会社が あると仮定します。部品には、単独で構成される独立した部品と、他の部品の集合 で構成される組み立て品目があります。 これらの関係を 1 つの表に記述します。この表の名前が contains だとします。列 contains.parent に、組立て品のパーツ ナンバーが格納されます。列 contains.child には、親のコンポーネントであるパーツのパーツ ナンバーが格納さ れます。部品番号が 123400 の部品が 9 個の部品からなる組立て品の場合、最初の 列には 123400、2 番目の列には子の部品番号が格納された行が 9 行存在すること になります。 図 355 に、パーツ ナンバー 123400 を表す行の 1 つを示します。 図 355. 部品展開の問題 部品展開の問題は次のとおりです。パーツ・ナンバーが与えられると、そのパーツ のコンポーネントであるすべてのパーツのリストを作成します。次に IBM Informix ESQL/C でのこの問題の 1 つの解決策を示します。 int part_list[200]; boom(top_part) int top_part; { long this_part, child_part; int next_to_do = 0, next_free = 1; part_list[next_to_do] = top_part; EXEC SQL DECLARE part_scan CURSOR FOR SELECT child INTO child_part FROM contains WHERE parent = this_part; while(next_to_do < next_free) { this_part = part_list[next_to_do]; EXEC SQL OPEN part_scan; while(SQLCODE == 0) { EXEC SQL FETCH part_scan; if(SQLCODE == 0) { part_list[next_free] = child_part; next_free += 1; } } EXEC SQL CLOSE part_scan; 第 8 章 SQL を使用したプログラミング 215 next_to_do += 1; } return (next_free - 1); } 専門用語では、表 contains の各行は、方向をもつ非周期グラフ、つまりツリーの ヘッド ノードです。関数は、ツリーの横方向優先探索を実行します。ツリーのルー トは関数のパラメータとして渡される部品番号です。関数は、part_scan という名 前のカーソルを使用して、すべての行を、列 parent に特定の値が指定された状態 で戻します。一番内側の while ループはカーソル part_scan をオープンして、選 択セット内の各行を取り出し、各コンポーネントの部品番号が抽出されたときにカ ーソルをクローズします。 上記の関数は、部品展開問題の核心部を処理しますが、完全な解決策ではありませ ん。例えば、ツリーの複数のレベルに現れるコンポーネントでは使用できません。 さらに、実際の表 contains には、 列 count も含まれ、この列に、それぞれの parent で使用された child パーツのカウントが示されます。さらに、実際の表 contains には、列 count も含まれ、この列にそれぞれの parent で使用された child パーツのカウントが示されます。各要素部品の総カウント数を戻すプログラ ムは、さらに複雑になります。 前述した繰返し処理型のアプローチが、部品展開問題への唯一のアプローチではあ りません。世代の数に一定の制限がある場合は、入れ子になった外部セルフ結合を 使用する SELECT 文を 1 つ使用すると、この問題を解決できます。 トップレベルの部品に最大で 4 世代の部品が含まれている場合、次の SELECT 文 ではそれらの部品をすべて戻します。 SELECT a.parent, a.child, b.child, c.child, d.child FROM contains a OUTER (contains b, OUTER (contains c, outer contains d) ) WHERE a.parent = top_part_number AND a.child = b.parent AND b.child = c.parent AND c.child = d.parent この SELECT 文は、top_part_number として与えられた部品を祖先とする各世代 について 1 行を戻します。存在しないレベルについては NULL が戻されます。 NULL を検出するには標識変数を使用します。表 contains の入れ子になった外部 結合をもっと多く使用すれば、他のレベルに対しても行えます。また、各レベルで の部品の数を戻すように、このプログラムを記述し直すこともできます。 動的 SQL 静的 SQL は便利ですが、プログラムを作成するには SQL 文の内容を事前に完全に 理解していなければなりません。例えば、WHERE 節ではどの列をテストするの か、選択リストにはどの列を指定するのかをプログラム中に記述しなければなりま せん。 事前に十分に定義された特定のタスクを実行するプログラムを作成するのなら、こ れで十分です。しかし、事前に完全には定義できないデータベース操作を行うプロ グラムもあります。特に、ユーザの要求に対話的に応えなければならないプログラ ムの場合、ユーザからの入力に応じて SQL 文を作成することが必要になります。 216 IBM Informix: SQL ガイド: チュートリアル 動的 SQL を使用すると、プログラムの実行中に SQL 文が生成できるので、ユーザ の入力で文の内容が決定されます。この動作は、次の手順で実行されます。 1. プログラムは、SQL 文のテキストをプログラム変数に格納される文字列として 作成する。 2. プログラムは PREPARE 文を実行する。PREPARE 文はデータベース サーバに 対し、SQL 文のテキストを調べることと、そのテキストを実行できるように準 備することを要求する。 3. プログラムは EXECUTE 文を使用して、準備した文を実行する。 この方法を用いると、あらゆる種類のユーザ入力を基にして SQL 文を構築し実行 することができます。例えば、SQL 文のファイルを読み込み、それらを処理して実 行することができます。 DB–Access は SQL を対話的に実行するユーティリティで、SQL 文の構築、処理、 実行を動的に行う IBM Informix ESQL/C プログラムです。例えば、DB–Access に よって、簡単な対話式メニューを使用して表の列を指定することができます。ユー ザがメニューの指定を終えると、DB–Access は必要な CREATE TABLE 文か ALTER TABLE 文を動的に作成して、それを準備し実行します。 文の PREPARE 文による処理 動的 SQL 文も、構文的には他の SQL 文とほとんど同じです。ただ 1 つの違い は、動的 SQL 文にはホスト変数名を記述することができない点です。 動的 SQL 文には、2 つの制約事項があります。1 つ目は、それが SELECT 文であ る場合に、INTO 節を含めることができないという点です。 INTO 節には列のデー タを収めるホスト変数を指定しますが、ホスト変数の使用は、動的文では許可され ていません。 2 つ目は、式の内部でホスト変数名を使用する場所には、位置指定子 として疑問符 (?) を記述しなければならないという点です。 このフォームの文を PREPARE 文で処理する例を次に示します。次の例は、 IBM Informix ESQL/C で書かれています。 EXEC SQL prepare query_2 from ’SELECT * from orders WHERE customer_num = ? and order_date > ?’; この例の 2 つの疑問符は、文が実行されると、ホスト変数の値がこれらの 2 つの 場所で使用されることを示しています。 ほとんどの SQL 文は、動的に処理できます。 PREPARE 文で処理できない SQL 文は、PREPARE 文や OPEN 文などの、動的 SQL やカーソル管理に直接関係する 文のみです。 UPDATE または DELETE 文を処理した場合、SQLWARN の 5 番目 のフィールドをテストし、WHERE 節を使用したかどうか確認してください。(204 ページの『SQLWARN 配列』を参照)。 文を準備した結果は、その文を表すデータ構造体になります。このデータ構造体 は、その文を生成した文字列と同じではありません。 PREPARE 文の内部でデータ 構造体に名前を付けます。前の例の場合は query_2 がデータ構造体の名前です。 この名前が、処理済みの SQL 文を実行するのに使用されます。 第 8 章 SQL を使用したプログラミング 217 PREPARE 文で処理する文字列には、複数の文を含めることができます。複数の SQL 文を並べる場合は、セミコロン(;) で区切ります。次に、IBM Informix ESQL/C のトランザクションで記述した、かなり複雑な例を示します。 strcpy(big_query, "UPDATE account SET balance = balance + ? WHERE customer_id = ?; ¥ UPDATE teller SET balance = balance + ? WHERE teller_id = ?;"); EXEC SQL PREPARE big1 FROM :big_query; この例の文の並びが実行されるときに、6 個の位置指定子としての疑問符がホスト 変数の値で置換されます。複数の文の並びを設定するのは大変ですが、プログラム とデータベース サーバ間のやりとりの回数が減るため、パフォーマンスは改善され ます。 PREPARE 文で処理された SQL 文の実行 PREPARE 文で処理済みの SQL 文は複数回実行することができます。 SELECT 文 以外の 文と 1 行だけ戻す SELECT 文は、EXECUTE 文を使用して実行します。 次の IBM Informix ESQL/C のコードは、銀行の帳簿を更新する複数文を処理し実 行する PREPARE 文と EXECUTE 文を示します。 EXEC SQL BEGIN DECLARE SECTION; char bigquery[270] = "begin work;"; EXEC SQL END DECLARE SECTION; stcat ("update account set balance = balance + ? where ", bigquery); stcat ("acct_number = ?;’, bigquery); stcat ("update teller set balance = balance + ? where ", bigquery); stcat ("teller_number = ?;’, bigquery); stcat ("update branch set balance = balance + ? where ", bigquery); stcat ("branch_number = ?;’, bigquery); stcat ("insert into history values(timestamp, values);", bigquery); EXEC SQL prepare bigq from :bigquery; EXEC SQL execute bigq using :delta, :acct_number, :delta, :teller_number, :delta, :branch_number; EXEC SQL commit work; EXECUTE 文の USING 節には、ホスト変数の並びが指定されています。PREPARE 文によって処理された文の疑問符は、これらのホスト変数の値で置換されます。 SELECT 文 (または EXECUTE FUNCTION 文) が戻す行が 1 行のみの場合、 EXECUTE 文の INTO 節を使用してその値を受け取るホスト変数を指定できます。 動的ホスト変数 動的に割り当てられたデータ オブジェクトをサポートする SQL API では、動的 SQL 文をもう 1 段高いレベルで使用することができます。これによって、列デー タを受け取るホスト変数を動的に割り当てることができます。 変数の動的割当てによって、任意の SELECT 文をプログラム入力から取り出して、 この SELECT 文が生成する値の個数とデータ型を判断して、これらのデータを保持 する適切なデータ型のホスト変数を割り当てることができます。 このようなことを実現するために中心的な役割を果たすのが DESCRIBE 文です。 DESCRIBE 文は、PREPARE 文によって処理された SQL 文の名前を受け取り、そ の文に関する情報と内容を戻します。また、SQLCODE を設定して、その文がどの 動詞で始まっているかを示します。 PREPARE 文によって処理された文が SELECT 218 IBM Informix: SQL ガイド: チュートリアル 文の場合、 DESCRIBE 文は選択された出力データに関する情報も戻します。 PREPARE 文によって処理された文が INSERT 文の場合には、DESCRIBE 文は入力 パラメータに関する情報を戻します。 DESCRIBE 文によって情報を戻されるデー タ構造体は、この目的のために割り当てられ、システム記述子領域として知られて いる、あらかじめ定義されたデータ構造体です。 IBM Informix ESQL/C を使用し ている場合は、システム記述子領域あるいは sqlda 構造体を使用することができま す。 DESCRIBE 文が SELECT 文に対し戻すか参照するデータ構造体には、構造体の配 列が含まれています。各構造体は、SELECT 文の選択リストの各項目に対し、戻さ れるデータに関する情報を提供します。例えば、プログラムはこの一連の構造体を 調べ、戻されるデータが 10 進数値とある長さの文字値、そして整数からなること を知ることができます。 この情報を使用すると、プログラムは抽出された値を格納するための記憶域をメモ リに割り当て、データベース サーバに送るデータ構造体に記憶域を指すポインタを 設定することができます。 PREPARE 文で処理された文の解放 PREPARE 文で処理された SQL 文は、メモリ内の領域を占有します。一部のデータ ベース サーバでは、この SQL 文がプログラム側の領域だけでなく、データベース サーバの領域も占有することがあります。 SQL 文が占有する領域は、プログラム が終了するときに解放されますが、終了時よりも前に解放することが必要になる場 合があります。 FREE 文を使用して、この領域を解放できます。 FREE 文は、文の名前または文の 名前に対して宣言されたカーソルの名前を指定し、PREPARE 文で処理された文に 割り当てられた領域を解放します。 1 つの文に複数のカーソルが定義されている場 合、文を解放してもカーソルは解放されません。 実行の高速化 カーソルやホスト変数を必要としない単純な文の場合は、PREPARE 文、EXECUTE 文、FREE 文の処理をまとめて 1 回で行うことができます。次の例は、 EXECUTE IMMEDIATE 文が 1 つの操作で文字列を取り、PREPARE 文で処理して実行し、記 憶域を解放する方法を示しています。 EXEC SQL execute immediate ’drop index my_temp_index’; この機能により、単純な SQL 文の作成が容易になります。ただし、USING 節が使 用できないため、EXECUTE IMMEDIATE 文を SELECT 文に使用することはでき ません。 データ定義文の埋込み データベースの作成や表の定義の変更を行うような SQL 文、すなわちデータ定義 文は通常、プログラム中には記述されません。プログラム中に記述することがほと んどないのは、データ定義文はまれにしか実行されないためですが、問合せやデー タの変更は何回も行われます。データベースは 1 回作成されますが、問合せや更新 は何回も行われます。 第 8 章 SQL を使用したプログラミング 219 データベースとその表の作成は、通常は、DB–Access を使用して対話的に行われま す。これらのツールには SQL 文の入ったファイルが含まれているため、データベ ースの作成をオペレーティング システムのコマンド 1 つで行うことが可能です。 データ定義文については、「IBM Informix: SQL ガイド: 構文」および 「IBM Informix: データベース設計および実装 ガイド」に記載されています。 GRANT 文と EVOKE 文の埋込み データ定義に関するタスクとして繰返し実行されるのが、アクセス権の付与と取消 しです。アクセス権の付与と取消しの操作は頻繁に発生し、SQL に不慣れな人によ って行われる可能性もあります。このため、GRANT 文と REVOKE 文をプログラ ムにパッケージすると、ユーザビリティが向上します。 GRANT 文と REVOKE 文は、動的 SQL としての扱いに特に適しています。どち らの文も、次のようなパラメータを取ります。 v アクセス権の並び v 表名 v ユーザ名 これらの値の一部はユーザやコマンド行パラメータ、あるいはファイルなどのプロ グラムへの入力を基に指定することが必要になります。しかし、これらの値はどれ も、ホスト変数の形式で指定することはできません。これらの文の構文のどこにも ホスト変数を使用することができません。 唯一の代替手段は、文の各部を文字列にアセンブルし、アセンブルされた文を PREPARE 文で処理して実行する方法です。プログラム入力は、準備済みの文に文 字列として組み込むことがでます。 次の IBM Informix ESQL/C 関数は、関数パラメータから GRANT 文をアセンブル し、 PREPARE 文で処理して実行します。 char priv_to_grant[100]; char table_name[20]; char user_id[20]; table_grant(priv_to_grant, table_name, user_id) char *priv_to_grant; char *table_name; char *user_id; { EXEC SQL BEGIN DECLARE SECTION; char grant_stmt[200]; EXEC SQL END DECLARE SECTION; sprintf(grant_stmt, " GRANT %s ON %s TO %s", priv_to_grant, table_name, user_id); PREPARE the_grant FROM :grant_stmt; if(SQLCODE == 0) EXEC SQL EXECUTE the_grant; else printf("Sorry, got error # %d attempting %s", SQLCODE, grant_stmt); EXEC SQL FREE the_grant; } 220 IBM Informix: SQL ガイド: チュートリアル 次の例に示す関数の最初の文は、関数の名前とその 3 つのパラメータを指定しま す。この 3 つのパラメータでは、付与されるアクセス権、アクセス権が付与される 表の名前、およびそれらのアクセス権を付与されるユーザの ID を指定します。 table_grant(priv_to_grant, table_name, user_id) char *priv_to_grant; char *table_name; char *user_id; 関数は、次の例に示されている文を使用して、局所変数 grant_stmt を定義しま す。この変数は、GRANT 文をアセンブルして保持するのに使用されます。 EXEC SQL BEGIN DECLARE SECTION; char grant_stmt[200]; EXEC SQL END DECLARE SECTION; 次の例に示されているとおり、GRANT 文は、その定数部分と関数パラメータを連 結して作成されます。 sprintf(grant_stmt, " GRANT %s ON %s TO %s",priv_to_grant, table_name, user_id); この文は、次の 6 個の文字列を連結しています。 v GRANT v 付与されるアクセス権を指定するパラメータ v ON v 表名を指定するパラメータ v TO v ユーザを指定するパラメータ この結果、一部がプログラム入力で構成された、完全な GRANT 文が得られます。 PREPARE 文は、アセンブルされた文テキストを、解析のためにデータベース サー バへ渡します。 データベース サーバが、PREPARE 文の後の SQLCODE にエラー コードを入れて 戻した場合は、関数はエラー メッセージを表示します。データベース サーバは文 の形式を承認した場合には、ゼロの復帰コードを設定します。このアクションは文 が正しく実行されることを保証するものではありません。その文の構文が正しいこ とを意味しているに過ぎません。存在しない表を指定したり、実行時でなければ検 出できない、その他多くの種類のエラーが文に含まれていることがあります。例の 次の部分は、PREPARE 文による the_grant の処理が成功したかどうかを実行前に チェックするものです。 if(SQLCODE == 0) EXEC SQL EXECUTE the_grant; else printf("Sorry, got error # %d attempting %s", SQLCODE, grant_stmt); PREPARE 文の処理が成功した場合 (SQLCODE = = 0) には、次に PREPARE 文で処 理された文が実行されます。 第 8 章 SQL を使用したプログラミング 221 サマリ SQL 文をプログラム言語の通常の文と同じように扱って、プログラム中に埋め込む ことができます。プログラム変数を WHERE 節で使用したり、データベースから取 り出したデータをプログラム変数に代入したりすることができます。プリプロセッ サは、SQL コードをプロシジャ呼出しとデータ構造体に変換します。 データを戻さない文や 1 行のデータしか戻さない問合せは、プログラム言語の通常 の文と同じように作成することができます。複数の行を戻す可能性のある問合せ は、現行行のデータを表すカーソルと関連付けられます。プログラムはカーソルを 使用して、必要なデータを 1 行ずつ取り出すことができます。 静的 SQL 文は、プログラムのテキストとして書き込まれます。プログラムの実行 時に SQL 文を動的に生成して実行することも可能です。さらに、問合せがどのよ うなデータ型の列をいくつ戻すかを調べ、それらを格納するためのメモリ領域を動 的に割り当てることができます。 222 IBM Informix: SQL ガイド: チュートリアル 第 9 章 SQL プログラムによるデータの更新 DELETE の使用 . . . . . . . . . . . 直接的な削除 . . . . . . . . . . . 直接的な削除の途中で発生するエラー . . トランザクション ログの使用 . . . . . 整合性がある削除 . . . . . . . . . カーソルを使用した削除. . . . . . . . INSERT の使用. . . . . . . . . . . . INSERT カーソルの使用方法 . . . . . . INSERT カーソルの宣言. . . . . . . カーソルを使用した挿入. . . . . . . PUT 文と FLUSH 文の実行後の状態コード 定数の行 . . . . . . . . . . . . . 挿入の例 . . . . . . . . . . . . . UPDATE 文の使用 . . . . . . . . . . UPDATE カーソルの使用方法 . . . . . . キーワード UPDATE の目的 . . . . . 特定の列の更新. . . . . . . . . . 常に必要とされないキーワード UPDATE . 表の仕上げ . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 224 224 224 225 226 227 227 227 228 228 229 229 231 232 232 232 233 233 234 本章について これまでの章では、SQL 文、特に SELECT 文を、他の言語で作成されたプログラ ムに挿入したり、埋め込んだりする方法について説明しました。埋込み SQL を使 用すると、プログラムによるデータベースからのデータ抽出が可能になります。 この章では、プログラムで、表の行を削除、挿入、更新してデータベースを変更す る際に発生する問題について説明します。 197 ページの『第 8 章 SQL を使用し たプログラミング』と同様に、この章では、IBM Informix の埋込み言語のマニュア ルを読むために必要な情報を紹介します。 INSERT、UPDATE、および DELETE 文の一般的な使用方法については、 151 ペー ジの『第 6 章 データの変更』に記載されています。この章では、プログラム内部 での使用方法について説明します。これらの文をプログラムの内部に埋め込むこと 自体は簡単ですが、エラーを処理したり、複数のプログラムから同時に実行される データ変更操作を扱うのは、場合により非常に複雑になります。 DELETE の使用 表内の行を削除するために、プログラムは DELETE 文を実行します。 DELETE 文 は WHERE 節を使用した通常の方法で行を指定できるほか、指定したカーソルで取 り出された最後の行を参照できます。 行を削除するときは、その行に依存している行が他の表に含まれていないかを確認 する必要があります。このような整合性がある削除の問題については、第 6 章を参 照してください。プログラム内部から削除が行われる場合も問題は同じです。 © Copyright IBM Corp. 1996, 2003 223 直接的な削除 DELETE 文はプログラムに埋め込むことができます。次の例では、IBM Informix ESQL/C を使用しています。 EXEC SQL delete from items WHERE order_num = :onum; これと同じ書式の文を動的に処理し、実行することもできます。どちらの場合も、 文はデータベースに直接作用して、表の複数行に影響を与えます。 この例の WHERE 節では、onum というホスト変数の値を使用します。削除が終わ ると、結果が通常通り SQLSTATE と sqlca 構造体に設定されます。配列 SQLERRD の 3 番目の要素の値は、エラーが発生した場合も削除した行の数を示し ています。 SQLCODE の値は、この操作が成功したかどうかを示します。この値が 負ではない場合は、エラーは発生していません。この場合、SQLERRD の 3 番目の 要素の値は、WHERE 節の条件を満たして削除された行の総数を示しています。 直接的な削除の途中で発生するエラー エラーが発生すると、文は途中で終了します。エラーの原因は、SQLSTATE と SQLCODE の値、および SQLERRD の 2 番目の要素の値から判別できます。ま た、行のカウントにより、削除された行数が確認できます。多くのエラーでは、デ ータベース サーバが処理を開始する前にエラーが検出されるため、カウントの値は ゼロ (0) です。例えば、存在しない表を指定した場合や、WHERE 節で指定した列 の名前が変更されているような場合は、削除はまったく行われません。 削除が始まって複数行が処理されてから検出されるエラーもあります。このような エラーでもっとも一般的なのが、ロックの競合です。行を削除する場合、データベ ース サーバはその行に対し排他ロックを設定しないと削除できません。他のプログ ラムが操作の対象となる表を使用している場合は、データベース サーバはその行を ロックできません。ロックの問題はあらゆる種類の変更操作に影響するため、235 ページの『第 10 章 マルチユーザ環境のためのプログラミング』で詳細に説明して います。 削除を開始した後で、他の特殊なタイプのエラーが発生することがあります。例え ば、データベースの更新中に発生するハードウェアのエラーなどです。 トランザクション ログの使用 変更中に発生するあらゆる種類のエラーに対処するには、トランザクション ログ機 能を使用します。トランザクション ログ機能を使用すると、エラーが発生した場合 でも、データベースを変更した直前の状態に戻すことができます。次の例は、224 ページの『直接的な削除』で示した例を、トランザクションを使用するように拡張 したものです。 EXEC SQL begin work; EXEC SQL delete from items where order_num = :onum; del_result = sqlca.sqlcode; del_isamno = sqlca.sqlerrd[1]; del_rowcnt = sqlca.sqlerrd[2]; if (del_result < 0) EXEC SQL rollback work; else EXEC SQL commit work; 224 IBM Informix: SQL ガイド: チュートリアル /* start the transaction*/ /* save two error */ /* code numbers */ /* and count of rows */ /* problem found: */ /* put everything back */ /* everything worked OK:*/ /* finish transaction */ この例で重要なのは、トランザクションを終了する前 に、プログラムが sqlca 構 造体に重要な戻り値を保存していることです。 ROLLBACK WORK 文も COMMIT WORK 文も、他の SQL 文と同様に、復帰コードを sqlca 構造体に設定します。 ただし、エラーが生成したコードをレポートするには、ROLLBACK WORK 文を実 行する前にそれらを保存する必要があります。これは、ROLLBACK WORK 文が、 エラー コードを含むすべて の保留トランザクションを除去してしまうためです。 トランザクションを使用する利点は、何か問題が発生しても、データベースは不安 定な状態にならないことです。どこまで変更が終了したのかが不明になることはあ りません。すべての操作が完全に終了したか、あるいはまったく行われなかったの かのいずれになります。 ログ機能を使用するデータベースでは、ユーザが明示的なトランザクションを開始 しない場合には、データベース サーバは文の実行の前に内部トランザクションを開 始し、実行が完了または失敗した後トランザクションを終了します。文の実行に成 功すると、内部トランザクションは確定されます。文が失敗すると、ロール バック されます。 整合性がある削除 トランザクション ログ機能は、複数の表を削除する場合に特に役立ちます。例えば デモンストレーション データベースから注文を 1 件削除すると仮定します。 2 つ の表 orders と items から行を削除する場合を、IBM Informix ESQL/C の例で説 明します。 EXEC SQL BEGIN WORK; EXEC SQL DELETE FROM items WHERE order_num = :o_num; if (SQLCODE >= 0) { EXEC SQL DELETE FROM orders WHERE order_num == :o_num; { if (SQLCODE >= 0) EXEC SQL COMMIT WORK; { else { printf("Error %d on DELETE", SQLCODE); EXEC SQL ROLLBACK WORK; } このプログラムの論理は、トランザクションの使用あるいは不使用でもほとんど変 わりません。しかし、トランザクションを使用しない場合、エラー メッセージを見 たユーザが行う決定が困難になってしまいます。トランザクションを使用しない場 合、いつエラーが発生したかによって状況は次のように変わります。 v 削除はまったく行われなかった。この注文番号のすべての行は、データベースに 残っている。 v 表 items の行が一部のみ削除された。いくつかの品目 (いくつかは不明) を含む 注文レコードが残っている。 v 表 items のすべての行は削除されたが、表 orders の行は残っている。 v すべての行が削除された。 第 9 章 SQL プログラムによるデータの更新 225 2 番目と 3 番目の場合、データベースの一部が壊れてしまっています。データベー スには部分的な情報が入っているため、問合せに対しては間違った結果を戻すこと があります。この場合、慎重な処理を行って、情報を一貫性のある状態に戻さなけ ればなりません。トランザクションを使用していれば、このような不明確な状態に なることはありません。 カーソルを使用した削除 カーソルを使用して、取り出した最後の行を削除するように、DELETE 文を記述す ることもできます。この方法で行を削除すると、次の例に示すように、WHERE 節 でテストできない条件に基づいて削除をプログラムすることができます。次の例 は、トランザクションの始まりと終わりをセットアップする方法のため、ANSI 標 準準拠ではないデータベースにのみ適用されます。 警告: この例の ESQL/C 関数の設計では、プログラムがいつでも完全に動作すると は限りません。この関数が正しく動作するかどうかは、現在の排他レベルに 依存しています。排他レベルについては後述します。排他レベルの詳細につ いては、第 10 章を参照してください。たとえ意図したとおりに関数が動作 しても、その効果は表の行の物理的な順序に依存するため、一般的な意味で 適切な設計と言えません。 int delDupOrder() { int ord_num; int dup_cnt, ret_code; EXEC SQL declare scan_ord cursor for select order_num, order_date into :ord_num, :ord_date from orders for update; EXEC SQL open scan_ord; if (sqlca.sqlcode != 0) return (sqlca.sqlcode); EXEC SQL begin work; for(;;) { EXEC SQL fetch next scan_ord; if (sqlca.sqlcode != 0) break; dup_cnt = 0; /* default in case of error */ EXEC SQL select count(*) into dup_cnt from orders where order_num = :ord_num; if (dup_cnt > 1) { EXEC SQL delete from orders where current of scan_ord; if (sqlca.sqlcode != 0) break; } } ret_code = sqlca.sqlcode; if (ret_code == 100) /* merely end of data */ EXEC SQL commit work; else /* error on fetch or on delete */ EXEC SQL rollback work; return (ret_code); } この関数の目的は、重複した注文番号を含む行を削除することです。デモンストレ ーション データベースでは、orders.order_num の列番号に一意性インデックスが 指定されているため、注文番号が重複する可能性はありません。しかし、類似した 226 IBM Informix: SQL ガイド: チュートリアル 関数が行に設定する別のデータベース用に書き込まれている可能性はあります。こ の場合、使用済みの列名が指定されます。 この関数は、表 orders のすべての行を走査するカーソルとして、scan_ord を宣 言しています。このカーソルは FOR UPDATE 節で宣言されていますが、これは、 カーソルがデータの変更に使用できることを示しています。カーソルが正しくオー プンした場合は、この関数はトランザクションを開始し、表の各行を反復処理しま す。この関数は、表の各行について、埋込み SELECT 文を使用して、現行行と注文 番号が同じ行が表に何行あるかを調べます。 第 10 章で説明するように、この手順 は、排他レベルが正しくないと失敗します。 デモンストレーション データベースでは、この表に一意性インデックスが付いてい るため、dup_cnt に戻されるカウント、つまり重複行の数は常に 1 です。この値 が 1 よりも大きい場合は、この関数は表の現行行を削除して、カウント数を 1 減 らします。 このような目的で使用される関数は、この例より高度な設計を必要とします。この 関数は、データベース サーバが戻す最後の重複行以外のすべての重複行を削除しま す。この順番は、行の内容や意味とはまったく関係がありません。前出の例の関数 は、カーソル宣言に ORDER BY 節を追加することで改善することができます。た だし、ORDER BY 節と FOR UPDATE 節を同時に使用することはできません。 229 ページの『挿入の例』で、より適切な方法を説明します。 INSERT の使用 INSERT 文はプログラムに埋め込むことができます。その形式およびプログラム内 での使用方法は、第 6 章で説明したものと同じですが、追加機能として、ホスト変 数を式内で、VALUES 節と WHERE 節の両方で使用できます。さらに、プログラ ムにカーソルを使用して行を挿入することもできます。 INSERT カーソルの使用方法 DECLARE CURSOR 文には多くの種類があります。その大部分は、データに対して さまざまな走査を行うカーソルを作成するためのものですが、INSERT カーソル と いう特別な種類のカーソルを作成するものがあります。 INSERT カーソルを PUT 文と FLUSH 文で使用すると、複数の行を一括して効率よく表に挿入できます。 INSERT カーソルの宣言 INSERT カーソルを作成するには、SELECT 文の変わりに INSERT 文についてカー ソルを宣言します。このように宣言したカーソルは、行の取出しには使用できませ ん。使用できるのは行の挿入だけです。次の 4GL コード フラグメントに、 INSERT カーソルの宣言の例を示します。 DEFINE the_company LIKE customer.company, the_fname LIKE customer.fname, the_lname LIKE customer.lname DECLARE new_custs CURSOR FOR INSERT INTO customer (company, fname, lname) VALUES (the_company, the_fname, the_lname) INSERT カーソルをオープンすると、一群の行を格納するためのバッファがメモリ 内に作成されます。このバッファにはプログラムが生成した行が格納されます。バ 第 9 章 SQL プログラムによるデータの更新 227 ッファがフルになると、バッファ内のすべての行が一括してデータベースサーバへ 送られます。こうすれば、プログラムとデータベース サーバとの間の通信量が減る とともに、データベース サーバはより簡単に行を挿入できるようになります。その 結果、挿入処理が高速化されます。 バッファは、常に少なくとも 1 行の挿入データが入る大きさに作成されます。バッ ファの最小サイズより行が十分に短い場合は、バッファには複数の行が格納されま す。 カーソルを使用した挿入 上記の例は、INSERT カーソルが使用できるよう PREPARE 文で処理されていま す。次の例は、カーソルをどのように使用するかを示しています。問題を単純にす るため、この例では、next_cust という関数が新しい顧客に関する情報か、入力の 終わりを知らせる NULL データのどちらかを戻すと仮定しています。 EXEC SQL BEGIN WORK; EXEC SQL OPEN new_custs; while(SQLCODE == 0) { next_cust(); if(the_company == NULL) break; EXEC SQL PUT new_custs; } if(SQLCODE == 0) /* if no problem with PUT */ { EXEC SQL FLUSH new_custs; /* write any rows left */ if(SQLCODE == 0) /* if no problem with FLUSH */ EXEC SQL COMMIT WORK; /* commit changes */ } else EXEC SQL ROLLBACK WORK; /* else undo changes */ この例のコードでは next_cust が繰り返し呼び出されています。 next_cust が NULL でないデータを戻すと、PUT 文はそのデータを行バッファへ送ります。バッ ファがフルになると、バッファ内の行は自動的にデータベース サーバへ送られま す。 WHILE ループは、next_cust が戻すデータがなくなると正常終了します。ル ープから抜けた後、FLUSH 文がバッファ内に残っている行を表に書き込み、それが 終わると、このトランザクションは終了します。 227 ページの INSERT 文を再度確認してください。この INSERT 文自体は、カー ソル定義の一部ではなく、表 customer に 1 行を挿入します。実際、この例から INSERT カーソルを指定する部分を削除して、INSERT 文を PUT 文がある位置に 書くこともできます。その違いは、INSERT カーソルの方がプログラムの実行速度 が多少速いという点です。 PUT 文と FLUSH 文の実行後の状態コード PUT 文を実行する場合、プログラムは行が実際にバッファに格納されたかどうかを テストする必要があります。新しい行がバッファに入った場合、PUT 文が行う操作 は、その行をバッファにコピーすることのみです。この場合、エラーが発生する可 能性はありません。しかし、新しい行がバッファに入りきらない場合は、バッファ の中身全体がデータベース サーバに渡されて表に挿入されるため、このときにエラ ーが発生する可能性があります。 228 IBM Informix: SQL ガイド: チュートリアル SQL 通信領域 (SQLCA) に戻される値が、プログラムに対し、それぞれの場合を分 類するための情報を示します。PUT 文が実行されるたびに、SQLCODE および SQLSTATE が、エラーが発生しなかった場合はゼロに、エラーが発生した場合は負 のエラー コードに、それぞれ設定されます。 データベース サーバにより、SQLERRD の 3 番目の要素は、表に実際に挿入され た行の数に設定されます。以下のようになります。 v 新しい行がバッファにコピーされただけの場合はゼロ v バッファの中身がエラーを発生せずに挿入された場合は、バッファに格納されて いた行数 v 挿入中にエラーが発生した場合は、それまでに挿入された行数 コードを再度読んで、SQLCODE をどのように使用しているか確認してください。 前出の例を参照してください。まず、OPEN 文でエラーが発生した場合は、WHILE 条件が機能しないためにループが実行されず、FLUSH 操作も実行されずに、トラン ザクションがロール バックします。次に、PUT 文がエラーを戻す場合は、WHILE 条件によりループは終了し、FLUSH 操作は実行されずに、トランザクションがロー ル バックします。これが発生するのは、バッファを少なくとも 1 回はフルにする だけの数の行がループによって生成された場合のみです。その他の場合は、PUT 文 の実行でエラーが発生することはありません。 行がバッファに残っていても、場合によっては、1 行も挿入されていないにもかか わらずループが終了することがあります。この時点で SQL の状態はゼロになり、 FLUSH 操作が実行されます。 FLUSH 操作がエラー コードを生成する場合は、ト ランザクションがロール バックします。トランザクションがコミットするのは、す べての行が完全に成功したときのみです。 定数の行 INSERT カーソルを使用すると簡単に高い効率が得られる特殊な場合が 1 つありま す。それは、INSERT 文にリストされた値すべてが定数の場合、つまり、式もホス ト変数もなく、リテラル番号と文字列だけが並ぶ場合です。このような INSERT 文 は、何回実行しても同じ行を生成します。行が同じである場合、コピーし、バッフ ァに入れ、転送することはありません。 このような INSERT 文では、PUT 文はカウンタの値を増加するだけで他に何も行 いません。最後に FLUSH 文が実行されるときに、行の単一コピーと挿入の回数が データベース サーバへ渡されます。データベース サーバは渡された情報を基に、 必要な数の行を生成して 1 回の操作で挿入します。 同じ行を数多く挿入することは、通常ありません。ただし、データベースを作成し た直後には、大規模な表を NULL データで埋めるために、同一行を挿入できます。 挿入の例 226 ページの『カーソルを使用した削除』では、重複行を表から探し出して削除す ることを目的とする、DELETE 文の例を説明しました。不要な行を削除するのでは なく、必要な行を選択した方が、このタスクを適切に実行できます。次の IBM Informix ESQL/C のコードは、このタスクを遂行する方法の一例です。 第 9 章 SQL プログラムによるデータの更新 229 EXEC SQL BEGIN DECLARE SECTION; long last_ord = 1; struct { long int o_num; date o_date; long c_num; char o_shipinst[40]; char o_backlog; char o_po[10]; date o_shipdate; decimal o_shipwt; decimal o_shipchg; date o_paiddate; } ord_row; EXEC SQL END DECLARE SECTION; EXEC SQL BEGIN WORK; EXEC SQL INSERT INTO new_orders SELECT * FROM orders main WHERE 1 = (SELECT COUNT(*) FROM orders minor WHERE main.order_num = minor.order_num); EXEC SQL COMMIT WORK; EXEC SQL DECLARE dup_row CURSOR FOR SELECT * FROM orders main INTO :ord_row WHERE 1 < (SELECT COUNT(*) FROM orders minor WHERE main.order_num = minor.order_num) ORDER BY order_date; EXEC SQL DECLARE ins_row CURSOR FOR INSERT INTO new_orders VALUES (:ord_row); EXEC SQL BEGIN WORK; EXEC SQL OPEN ins_row; EXEC SQL OPEN dup_row; while(SQLCODE == 0) { EXEC SQL FETCH dup_row; if(SQLCODE == 0) { if(ord_row.o_num != last_ord) EXEC SQL PUT ins_row; last_ord = ord_row.o_num continue; } break; } if(SQLCODE != 0 && SQLCODE != 100) EXEC SQL ROLLBACK WORK; else EXEC SQL COMMIT WORK; EXEC SQL CLOSE ins_row; EXEC SQL CLOSE dup_row; この INSERT 文は、重複していない行を表から検出し、別の表に挿入します。挿入 先の表は、このプログラムの開始前に作成されている必要があります。この操作を 行うと、重複している行のみが残ります。デモンストレーション データベースの表 orders には、一意性インデックスが付いているため、行が重複する可能性はありま せん。この例では、デモンストレーション データベース以外のデータベースを取り 上げています。 上記の例では、その後 2 つのカーソルを宣言します。最初の dup_row というカー ソルは、表の重複行を取り出します。 dup_row は入力専用なので、ORDER BY 節を使用して重複行をソートすることができます。226 ページの例で示したよう 230 IBM Informix: SQL ガイド: チュートリアル に、物理的順序で行がソートされることはありません。この例では、重複行は日付 の順にソートされています。これは、最も古い日付の行が格納されるようにするた めです。目的に応じて、他の順序でソートすることも可能です。 2 番目のカーソル、ins_row は INSERT カーソルです。このカーソルは、C 構造 体、ord_row を使用できるという利点を生かして、その行のすべての列に値を与え ます。 コードの残りの部分は、dup_row から取り出した行を調べます。重複行の各グルー プから最初の 1 行だけを選んで表に挿入し、残りの行は無視します。 簡潔さのために、前出の例では、最も単純な種類のエラー処理を使用しています。 すべての行が処理される前にエラーが発生した場合には、サンプル コードは実行さ れたトランザクションにロール バックします。 影響を受ける行の数 カーソルを使用して行を選択するプログラムでは、SQLCODE の復帰コードがデー タの終わりを示す 100 かどうか、また SQLSTATE では 02000 かどうかを調べる ことができます。このコードは、問合せ条件を満たす行が存在しないか、またはこ れ以上存在しないかを示すために設定されます。 ANSI 標準に準拠していないデー タベースでは、データの終わりを示す復帰コードが設定されるのは、 SELECT 文の 後の SQLCODE や SQLSTATE のみです。この値は、DELETE 文、INSERT 文、 または UPDATE 文の後には使用されません。ANSI 標準準拠データベースでは、 UPDATE 文、DELETE 文、INSERT 文では、プログラム操作の影響を受ける行が含 まれない場合でも SQLCODE が 100 に設定されます。 データを取り出さなかった問合せは、成功したとはみなされません。これに対し て、UPDATE 文と DELETE 文では、1 行も更新または削除を行わなくても成功し たものと見なされます。これは、WHERE 節の条件を満たす行の集合が更新または 削除されましたが、その集合が空であったことを意味します。 INSERT 文の場合も同様です。挿入対象の行が SELECT 文の結果で、その SELECT 文が 1 行も選択しなかった場合でも、データの終わりを示すリターンコー ドは設定されません。この場合、INSERT 文は成功したと見なされます。指定され た数の行、この場合はゼロ行を挿入しているためです。 挿入、更新、削除された行が何行あるかは、SQLERRD の 3 番目の要素を調べると わかります。 SQLCODE の値が何であっても、この要素の値は、挿入、更新、削除 された行数を示しています。行数がゼロや負の値であっても、その値が示されま す。 UPDATE 文の使用 第 6 章で説明した、どの形式のプログラムにでも、UPDATE 文を埋め込むことが できます。追加機能として、SET 節および WHERE 節の両方で、ホスト変数を式 内で指定できます。さらにプログラムでは、カーソルが指定する行を更新すること ができます。 第 9 章 SQL プログラムによるデータの更新 231 UPDATE カーソルの使用方法 UPDATE カーソル により、現在行を削除または更新できます。現在行とは最後に 取り出された行のことです。 IBM Informix ESQL/C で記述された次の例に、 UPDATE カーソルの宣言を示します。 EXEC SQL DECLARE names CURSOR FOR SELECT fname, lname, company FROM customer FOR UPDATE; このカーソルを使用するプログラムは、次に示すように入力用のカーソルと同様に 行を取り出すことができます。 EXEC SQL FETCH names INTO :FNAME, :LNAME, :COMPANY; 取り出した行を変更する必要がある場合は、次に示すように更新することもでき ま す。 if (strcmp(COMPANY, "SONY") ==0) { EXEC SQL UPDATE customer SET fname = ’Midori’, lname = ’Tokugawa’ WHERE CURRENT OF names; } この WHERE 節では、通常の条件式の代わりに CURRENT OF names が使用されてい ます。これ以外は、この UPDATE 文は通常の UPDATE 文と同じです。この文に 指定されている表名は、カーソル名から間接的にわかりますが、指定しなければな りません。 キーワード UPDATE の目的 キーワード UPDATE を使用して UPDATE カーソルを宣言するのは、取り出され た行が更新または削除される可能性があることをデータベース サーバに知らせるた めです。データベース サーバは、UPDATE カーソルによって取り出された行に厳 しいロックを設定し、このキーワードが宣言されていないカーソルによって取り出 された行にはあまり厳しくないロックを設定します。これにより、通常のカーソル については効率が向上し、多重プロセッシング システムでは並行性が高まります。 ロックのレベルと並行使用については、第 10 章で説明します。 特定の列の更新 次の例は、UPDATE カーソルの前述の例の特定の列を更新しています。 EXEC SQL DECLARE names CURSOR FOR SELECT fname, lname, company, phone INTO :FNAME,:LNAME,:COMPANY,:PHONE FROM customer FOR UPDATE OF fname, lname END-EXEC. このカーソルを使用して更新できる列は、列 fname と列 lname のみです。次の ような文は、エラーと見なされるため実行できません。 232 IBM Informix: SQL ガイド: チュートリアル EXEC SQL UPDATE customer SET company = ’Siemens’ WHERE CURRENT OF names END-EXEC. このような UPDATE 文がプログラムに含まれていると、エラー コードが戻され て、更新は行われません。 WHERE CURRENT OF を指定した削除も実行できませ ん。削除はすべての列に影響すると考えられるためです。 常に必要とされないキーワード UPDATE ANSI 標準の SQL では、カーソル定義での FOR UPDATE 節は提供されていませ ん。ANSI 標準準拠のデータベースを使用するプログラムは、任意のカーソルを使 用して更新や削除を実行できます。 表の仕上げ UPDATE カーソルの使用例をもう 1 つ示します。この問題も、完成したデータベ ースでは絶対に発生しませんが、アプリケーションの初期設計段階で発生する問題 です。 この例では、target という大きな表が構築、移植されています。datcol という名前 の文字 (CHARCTER) 型列に、誤って NULL が複数挿入されました。これらの列は 削除しなければなりません。さらに、表の作成後に、ALTER TABLE 文を使用して serials という名前の新しい列を追加しました。この列には、一意の整数値を割り当 てる必要があります。次の例では、このタスクを実行するために使用する IBM Informix ESQL/C コードを示しています。 EXEC SQL BEGIN DECLARE SECTION; char dcol[80]; short dcolint; int sequence; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE target_row CURSOR FOR SELECT datcol INTO :dcol:dcolint FROM target FOR UPDATE OF serials; EXEC SQL BEGIN WORK; EXEC SQL OPEN target_row; if (sqlca.sqlcode == 0) EXEC SQL FETCH NEXT target_row; for(sequence = 1; sqlca.sqlcode == 0; ++sequence) { if (dcolint < 0) /* null datcol */ EXEC SQL DELETE WHERE CURRENT OF target_row; else EXEC SQL UPDATE target SET serials = :sequence WHERE CURRENT OF target_row; } if (sqlca.sqlcode >= 0) EXEC SQL COMMIT WORK; else EXEC SQL ROLLBACK WORK; 第 9 章 SQL プログラムによるデータの更新 233 サマリ プログラムでは、INSERT 文、DELETE 文、および UPDATE 文を実行できます。 これについては、第 6 章で説明しています。またプログラムでは、表をカーソルで 走査して、指定した行を更新または削除することもできます。また、行の挿入にも カーソルを使用することができます。これには、行がバッファに格納されてから、 一括してデータベース サーバに送られるという利点があります。 このような操作を行う場合、エラーを検出し、エラーが発生した場合にはデータベ ースを復元するようなプログラムを作成する必要があります。この復元処理で最重 要のツールは、トランザクション ログ機能です。プログラムでトランザクション ログ機能を使用しないと、エラーからの復旧が困難になります。 234 IBM Informix: SQL ガイド: チュートリアル 第 10 章 マルチユーザ環境のためのプログラミング 並行性およびパフォーマンス . . . . . . . . . . . . . . . . . . . . . . . . . ロックおよび整合性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . ロックおよびパフォーマンス . . . . . . . . . . . . . . . . . . . . . . . . . 並行性の問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ロックの動作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ロックの種類 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ロック範囲 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . データベース ロック . . . . . . . . . . . . . . . . . . . . . . . . . . 表ロック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . LOCK TABLE 文による表のロック . . . . . . . . . . . . . . . . . . . . データベース サーバが表を自動的にロックする場合 . . . . . . . . . . . . . . LOCK MODE 節による表ロックの設定 (XPS のみ) . . . . . . . . . . . . . . 行とキーのロック . . . . . . . . . . . . . . . . . . . . . . . . . . . ページ ロック . . . . . . . . . . . . . . . . . . . . . . . . . . . . すべての CREATE TABLE 文の行ロックまたはページ ロック モードの設定 (IDS のみ) . . コアース インデックス ロック . . . . . . . . . . . . . . . . . . . . . . スマート ラージ オブジェクト ロック (IDS のみ) . . . . . . . . . . . . . . . . バイト範囲ロック . . . . . . . . . . . . . . . . . . . . . . . . . . ロックの継続期間 . . . . . . . . . . . . . . . . . . . . . . . . . . . . データ修正中のロック . . . . . . . . . . . . . . . . . . . . . . . . . . SELECT 文でのロック . . . . . . . . . . . . . . . . . . . . . . . . . . . 排他レベルの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . SET TRANSACTION 文と SET ISOLATION 文の比較 . . . . . . . . . . . . . . SET ISOLATION . . . . . . . . . . . . . . . . . . . . . . . . . . SET TRANSACTION . . . . . . . . . . . . . . . . . . . . . . . . . 排他レベルの非確定読込み (ANSI) と単純読込み (Informix) . . . . . . . . . . . . . 排他レベルの確定読込み (ANSI) および確定読込み (Informix) . . . . . . . . . . . . 排他レベルのカーソル安定性 (Informix). . . . . . . . . . . . . . . . . . . . 直列化可能 (ANSI)、繰返し可能読込み (ANSI)、および繰返し可能読込み (Informix) 排他レベル UPDATE カーソル . . . . . . . . . . . . . . . . . . . . . . . . . . . 更新ロックの保存 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . INSERT 文、UPDATE 文、および DELETE 文により設定するロック . . . . . . . . . . . ロック タイプの動作の理解 . . . . . . . . . . . . . . . . . . . . . . . . . アクセス モードによるデータ変更の制御 . . . . . . . . . . . . . . . . . . . . . ロック モードの設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . ロックの待機 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ロックの解除を待機しない . . . . . . . . . . . . . . . . . . . . . . . . . 一定時間ロックの解除を待機する. . . . . . . . . . . . . . . . . . . . . . . デッドロックの処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . 外部デッドロックの処理. . . . . . . . . . . . . . . . . . . . . . . . . . 単純な並行性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . HOLD カーソル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SQL 文キャッシュの使用 . . . . . . . . . . . . . . . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 236 236 237 238 238 239 239 239 240 240 240 241 242 242 243 243 243 244 244 245 245 245 246 246 246 246 247 249 249 250 251 251 252 253 253 253 254 254 254 254 255 256 257 本章について この章では、マルチユーザ環境で操作する場合に把握しておく必要がある、プログ ラミングの問題をいくつか説明します。 © Copyright IBM Corp. 1996, 2003 235 データベースが保存されているコンピュータがシングルユーザ用のワークステーシ ョンで、他のコンピュータからデータにアクセスしなければ、プログラムはそのデ ータベースのデータを自由に変更できます。しかし、これ以外では、あるプログラ ムがデータを変更しているときに、他のプログラムが同じデータを読み込んだり変 更したりする可能性があります。この状態は並行性 と称されます。つまり、同じデ ータを複数のプログラムが同時に使用することを指します。この章では、同時実行 性、ロック、および排他レベルについて説明します。 この章では、セッションあたりのメモリ割当てを削減して、問合せ処理を高速化す ることができる、文キャッシュ機能も説明します。文キャッシュが格納した文は、 同じ SQL 文を使用する異なるユーザ セッションで共有できます。 並行性およびパフォーマンス 同時実行性は、複数プログラミング システムのパフォーマンス向上に不可欠なもの です。 1 回に 1 本のプログラムのデータのみを使用するようにデータベースへの アクセスを直列化 すると、処理速度は大幅に低下してしまいます。 ロックおよび整合性 データへのアクセスを適切に制御しないと、同時実行性はさまざまな弊害をもたら す恐れがあります。プログラムが、失効したデータを読み込んだリ、成功とみなさ れた変更操作の結果が失われるかもしれません。 データベース サーバは、ロック を系統的に設定することによって、このようなエ ラーを防止します。ロックは、データの各部に対するプログラムからの使用予約で す。データベース サーバは、ロックされているデータについては、他のプログラム がそのデータを更新できないようにします。他のプログラムがそのデータを要求し た場合は、ロックが解除されるまでそのプログラムを待機させるか、あるいはエラ ー メッセージを発行してその要求を拒否します。 ロックおよびパフォーマンス ロックは 1 つのデータに対するアクセスを直列化するため、同時実行性は低下しま す。ロックされているデータにアクセスしようとするプログラムは待機しなければ なりません。データベース サーバは単一の行、複数の行を持つディスク ページ、 表全体、またはデータベース全体をロックすることができます。 (ディスク ページ は、複数の行を持つことができ、行は複数のディスク ページを必要とすることがあ ります)。データベース サーバが設定するロックの数が多いほど、また、ロック対 象のオブジェクトが大きいほど、同時実行性は低下します。ロックの数が少なくオ ブジェクトが小さいほど、同時実行性とパフォーマンスは向上します。 以下の各節で、プログラムが次の目標を達成する方法について説明します。 v データ整合性を維持するために必要なロックを、すべて設定する。 v 最初の目標を達成できる範囲内で、ロックの数とロック対象のデータのサイズを 可能な限り減らす。 236 IBM Informix: SQL ガイド: チュートリアル 並行性の問題 同時実行性の弊害を理解するには、それぞれが独自の速度で動作する複数のプログ ラムが実行されている状況を考える必要があります。例えば、あるアプリケーショ ン プログラムが、次のように宣言されたカーソルを使用して行を取り出すと想定し ます。 EXEC SQL DECLARE sto_curse CURSOR FOR SELECT * FROM stock WHERE manu_code = ’ANZ’; データベース サーバが各行をプログラムへ転送するには時間がかかります。行が転 送されているとき、あるいは転送が終わってから次の転送が始まるまでの間に、他 のプログラムが他のデータベース操作を実行することがあります。あるユーザのプ ログラムが問合せにより生成された行を取り出すときに、別のユーザのプログラム が次の更新を実行する可能性もあります。 EXEC SQL UPDATE stock SET unit_price = 1.15 * unit_price WHERE manu_code = ’ANZ’; 2 つのプログラムは、同じ表にアクセスすることになり、一方はある行を取り出 し、もう一方はその行を更新します。以下のようなケースが考えられます。 1. 作成したプログラムが最初の行を取り出すときには、他のプログラムは更新をす でに終了している。 この場合、作成したプログラムが取り出すのは更新後の行です。 2. 作成したプログラムは、他のどのプログラムが変更するよりも早く表の行を取り 出す。 この場合、作成したプログラムが取り出すのは更新前の古い行です。 3. 作成したプログラムが更新前の行を何行か取り出した後で、他のプログラムが追 いつき、ユーザのプログラムがまだ取り出していない行を更新してしまう。 更 新が終了すると、他のプログラムは COMMIT WORK 文を実行する。 この場合、作成したプログラムが取り出すのは、一部は更新前の行、残りは更新 後の行です。 4. 表の更新が終了すると、他のプログラムが ROLLBACK WORK 文を発行する以 外は、3 番目の場合と同じ。 この場合も、作成したプログラムが取り出すのは、一部は更新前の行、残りは更 新後の行ですが、更新後の行はすでにデータベースに存在しません。 最初の 2 つの可能性は、深刻な事態を招きません。最初の可能性の場合、他のプロ グラムによる更新は、作成したプログラムが問合せを始める前に完了しています。 完了したのがマイクロ秒前であっても 1 週間前であっても、違いはありません。 2 番目の可能性の場合は、作成したプログラムの問合せは、他のプログラムが更新 を始める前に実質的に完了しています。他のプログラムは、作成したプログラムよ り 1 行ずつ遅れて更新するか、もしくは翌日の夜に更新を始める可能性もあります が、詳細を判別する必要はありません。 これに対し、残りの 2 つの可能性は、アプリケーションの設計によっては非常に深 刻な事態を招くことがあります。 3 番目の可能性の場合は、問合せは更新前のデー タと更新後のデータを合わせて戻します。アプリケーションによっては、これが問 第 10 章 マルチユーザ環境のためのプログラミング 237 題になることがあります。しかし、例えばすべての価格の平均を求めるようなアプ リケーションの場合は、まったく問題にならないと考えられます。 4 番目の可能性の場合は、トランザクションが取り消されたために表に既に存在し なくなった行をプログラムが戻すことがあるため深刻です。 作成したプログラムが、最後に取り出した行の更新あるいは削除を実行できるカー ソルを使用している場合は、別の問題が発生します。次の一連のイベントが行われ た場合には、その結果は誤ったものになります。 v 作成したプログラムが行を取り出す。 v 他のプログラムがその行を更新あるいは削除する。 v 作成したプログラムが WHERE CURRENT OF cursor_name を更新または削除す る。 このような、並行するイベントを制御するには、データベース サーバのロックと排 他レベル の機能を使用します。 ロックの動作 Informix データベース サーバは、ここで説明する複雑かつ柔軟な一群のロック機能 をサポートします。ロック機能のサマリについて、詳しくは、「IBM Informix: スタ ートアップ ガイド」を参照してください。 ロックの種類 次の表に、Informix データベース サーバがサポートする、状況に応じて使い分けら れるロックの種類を示します。 ロックの種類 使用方法 共有 共有ロックを設定すると、オブジェクトは読込み専 用になります。共有ロックが設定されている間は、 オブジェクトの変更はできません。同じオブジェク トに対し、複数のプログラムが共有ロックを設定で きます。共有モードでロックされたレコードは、複 数のオブジェクトから読み込むことができます。 排他 排他ロックを設定すると、オブジェクトは単一プロ グラム専用に使用されるようになります。このロッ クは、このプログラムがオブジェクトを変更しよう とすると使用されます。 他のタイプのロックが存在する場合は、排他ロック を設定することはできません。排他ロックを設定し た後は、同じオブジェクトに別のロックを設定する ことはできません。 増進可能/更新 238 IBM Informix: SQL ガイド: チュートリアル 増進可能な (または更新) ロックは、更新の意図を 明確にします。このロックは、他の増進可能なロッ クや排他ロックが設定されていないオブジェクト以 外に設定できません。しかし、共有ロックが設定さ れているレコードに対しては、増進可能なロックを 設定できます。ロックされたオブジェクトをプログ ラムが変更しようとするとき、増進可能なロックを 排他ロックに増進することができます。しかし、こ れは、増進可能なロックから排他ロックに変更され るときに、共有ロックを含む他のロックがレコード に対して設定されていない場合に限ります。増進可 能なロックを設定したときに、共有ロックがレコー ドにあった場合には、増進可能なロックが排他ロッ クに増進する前に、共有ロックを解除する必要があ ります。 ロック範囲 ロックは、データベース全体や表全体に対し、あるいは個々のディスク ページ、行 単位、インデックス キー値に対し設定できます。ロックされるオブジェクトのサイ ズを、ロック範囲 (またはロックの細分性) と呼びます。一般に、ロック範囲が広く なるほど同時実行性は低下しますが、プログラミングは簡単になります。 データベース ロック データベース全体をロックできます。データベースをオープンすると、データベー スの名前に共有ロックが設定されます。データベースは CONNECT、DATABASE または CREATE DATABASE 文でオープンされます。データベースが、あるプログ ラムによってオープンされている場合、そのデータベースに共有ロックが設定され ているため、他のプログラムはデータベースを削除したり、データベースに対し排 他的ロックを設定したりすることはできません。 次の文で、データベース全体に排他ロックを設定する方法を示します。 DATABASE database_one EXCLUSIVE データベースが他のプログラムによりオープンされていなければ、この文は成功し ます。排他ロックが設定されると、読込みが目的の場合でも、他のプログラムはそ のデータベースをオープンできなくなります。データベース名に共有ロックが設定 できないためです。 データベースのロックが解除されるのは、データベースがクローズされるときのみ です。このアクションは、DISCONNECT または CLOSE DATABASE 文を使用し て明示的に、もしくは別の DATABASE 文を使用して暗黙的に実行できます。 データベースをロックすると、そのデータベースの同時実行性がゼロになるため、 同時実行性の影響を受けず、プログラミングは非常に簡単になります。しかし、デ ータベースのロックは、そのデータベースにアクセスすることが必要なプログラム が他に存在しない場合にのみ行ってください。データベースのロックが行われるの は、データベースがあまり利用されていない時間帯に、データベースのデータを大 規摸に更新する場合などです。 表ロック 表全体をロックできます。場合によっては、データベース サーバにより自動的にロ ックされます。 LOCK TABLE 文を使用すると、表全体を明示的にロックできま す。 第 10 章 マルチユーザ環境のためのプログラミング 239 LOCK TABLE 文またはデータベース サーバは、以下の種類の表ロックを設定でき ます。 v 共有ロック どのユーザも表に書き込めなくなります。共有モードでは、データベース サーバ によって表に共有ロックが設定され、他のユーザが更新できないことが通知され ます。また、データベース サーバにより、更新、削除、または挿入されたあらゆ る行にロックが追加されます。 v 排他ロック 他のユーザは、表の読取りと書込みを実行できなくなります。排他モードでは、 データベース サーバによって、更新した行数にかかわらず表に排他ロックが 1 つだけ設定されます。表に対し排他ロックを設定すると、その表を複数のプログ ラムで同時に使用することがまったくできなくなります。 したがって、多くのプ ログラムがその表の使用を要求している場合は、パフォーマンスに重大な影響を 与えることがあります。しかし、表の大部分の行を更新する必要がある場合は、 表に排他ロックを設定します。 LOCK TABLE 文による表のロック: トランザクションによって、データベース サーバに、表に対して LOCK TABLE 文を使用した表レベルのロックを使用するよ う指定されます。次の例で、表に排他ロックを設定する方法を示します。 LOCK TABLE tab1 IN EXCLUSIVE MODE 次の例で表に共有ロックを設定する方法を示します。 LOCK TABLE tab2 IN SHARE MODE ヒント: 排他レベルをデータベース サーバに設定することにより、より大きな同時 実行性を提供しながら共有ロックの表と同じ程度の保護を達成できます。 データベース サーバが表を自動的にロックする場合: データベース サーバによ り、次の文の実行中は常に表全体がロックされます。 v ALTER FRAGMENT 文 Dynamic Server v ALTER INDEX 文 Dynamic Server の終り v ALTER TABLE 文 v CREATE INDEX 文 v DROP INDEX 文 v RENAME COLUMN 文 v RERENAME TABLE 文 文の実行が終了すると、またはトランザクションが終了すると、ロックは自動的に 解除されます。後述するように、特定の問合せが実行されているときに、表全体が 自動的にロックされることもあります。 LOCK MODE 節による表ロックの設定 (XPS のみ): Extended Parallel Server は、LOCK TABLE 文を使用するか、または CREATE TABLE 文に含まれる LOCK 240 IBM Informix: SQL ガイド: チュートリアル MODE 節の TABLE ロック モードを使用した、表のロックを可能にします。トラ ンザクションの排他レベルがトランザクションのロック獲得を必要とする場合、ロ ック モードが TABLE に設定されている表をアクセスするすべてのトランザクショ ンは、その表のために表ロックを獲得します。次の文で、表を作成する場合の TABLE ロック モードの使用方法を示します。 CREATE TABLE tab1 ( col1 ... ) LOCK MODE TABLE ALTER TABLE 文を使用して、表を 1 つのロック モードから別のロック モード (TABLE、PAGE、または ROW) に切り替えることができます。 CREATE TABLE または ALTER TABLE 文の LOCK MODE 節を指定しても、 LOCK TABLE 文を使用してロック表を獲得しても、効果は同じです。 TABLE ロック モードは、ページ レベル ロックまたは行レベル ロックを獲得する (または排他レベルに準じて獲得しようとする) 代わりに、トランザクションが表ロ ックを獲得するため、問合せが効果的に増加するデータ ウェアハウス環境で特に有 用です。表レベル ロックは、ロックの要求件数をかなり減少できます。表ロックの 不利な点としては、更新の同時実行性を急激に減少することですが、このことはデ ータ ウェアハウス環境では一般に問題ではありません。 行とキーのロック 表の 1 行をロックできます。プログラムは 1 行あるいは複数の行をロックするこ とができ、他のプログラムは、その表のロックされていない行を継続して処理する ことができます。 行とキーのロックはデフォルトの動作ではありません。表を作成するときに、行レ ベル ロックを指定する必要があります。次の例では、行レベル ロックの表を作成 します。 CREATE TABLE tab1 ( col1... ) LOCK MODE ROW; 表を作成するときに LOCK MODE 節を指定する場合は、ALTER TABLE 文を使用 して後でロック モードを変更できます。次の文により、予約表上のロック モード がページ レベル ロックに変更されます。 ALTER TABLE tab1 LOCK MODE PAGE データベース サーバが、存在しない行をロックしなければならない場合もありま す。こうした場合、データベース サーバはインデックス キーの値にロックを設定 します。キーに対するロックは、行ロックとまったく同じ働きをします。行単位で ロックされる表では、キー ロックは仮想的な行に対するロックとして実現されま す。ページ単位でロックされる表では、キー ロックはキーを含むインデックス ペ ージか、存在するならば含むであろうキーを含むインデックス ページに設定されま す。 第 10 章 マルチユーザ環境のためのプログラミング 241 キーを挿入、更新、または削除すると (行を挿入、更新、または削除すると自動的 に行われます)、データベース サーバはインデックスのキーにロックを設定しま す。 行とキーのロックは、比較的少数の行を更新する場合は、同時実行性が増すため、 通常は全体的に最高のパフォーマンスを発揮します。ただし、データベース サーバ がロックを取得するためのオーバーヘッドがかかります。 ページ ロック データベース サーバでは、データはディスク ページ と呼ばれる単位で格納されま す。各ディスク ページには 1 つ以上の行が含まれます。場合によっては、ディス ク ページの個々の行をロックするよりも、そのディスク ページをロックする方が パフォーマンスが向上します。例えば、多数の行を変更する必要がある操作では、 行レベル ロック (行ごとに 1 つのロック) は費用効果がないため、ページ レベル ロックを選択します。 表を作成するときに LOCK MODE 節を指定しない場合は、データベース サーバの デフォルトの動作はページ レベル ロックになります。ページ ロックでは、データ ベース サーバは行を含むページ全体をロックします。同じページに格納されるいく つかの行を更新する場合は、データベース サーバは 1 ページに 1 ロックのみを使 用します。 すべての CREATE TABLE 文の行ロックまたはページ ロック モードの設定 (IDS のみ): Dynamic Server により、ロック モードを、単一ユーザ (各セッション) ま たはマルチユーザ (各サーバー) 向けに新規に作成されたすべての表の、ページ レ ベル ロックまたは行レベル ロックに設定できます。 CREATE TABLE 文を使用し て新規表を作成する際に、ロック モードの指定が不要になります。 セッション内で作成された新規表をすべて特定のロック モードで作成する場合、 IFX_DEF_TABLE_LOCKMODE 環境変数を設定する必要があります。例えば、セッ ション内で作成された新規表をすべて行ロック モードで作成する場合、 IFX_DEF_TABLE_LOCKMODE を ROW に指定します。この動作を上書きするに は、CREATE TABLE または ALTER TABLE 文を使用し、LOCK MODE 節を再定 義してください。 シングルユーザ ロック モード: セッションで作成したすべての新規表が同じロッ ク モードを必要とする場合、シングルユーザ ロック モードを設定します。 IFX_DEF_TABLE_LOCKMODE 環境変数を使用して、シングルユーザ ロック モー ドを指定してください。例えば、セッション内で作成された新規の表をすべて行レ ベル ロック で作成する場合、 IFX_DEF_TABLE_LOCKMODE を ROW に指定し ます。この動作を上書きするには、CREATE TABLE または ALTER TABLE 文を 使用し、LOCK MODE 節を再定義してください。環境変数の設定について、詳しく は、「IBM Informix: SQL ガイド: 参照」を参照してください。 マルチユーザ ロック モード: データベース管理者は、複数ロック モードを使用 して、ロック モードを同じサーバ上のすべてのユーザに指定することによる高い並 行性を実現できます。これにより、サーバ上で任意のユーザが作成するすべての表 には、同じロック モードが指定されます。マルチユーザ ロック モードを有効化す るには、データベース サーバの開始前に IFX_DEF_TABLE_LOCKMODE 環境変数 を設定するか、または DEF_TABLES_LOCKMODE 構成パラメータを設定します。 242 IBM Informix: SQL ガイド: チュートリアル 優先順位の規則: CREATE TABLE または ALTER TABLE のロック モードに は、優先度の高い順にリストされた、以下の優先順位の規則があります。 1. LOCK MODE 節を使用する CREATE TABLE または ALTER TABLE SQL 文 2. シングルユーザ環境変数の設定 3. サーバ環境へのマルチユーザ環境変数の設定 4. ONCONFIG ファイル内の構成パラメータ 5. デフォルト動作 (ページ レベル ロック) コアース インデックス ロック インデックスの通常のロック モードをコアース ロック モードに変更する場合、イ ンデックス上に、通常のロックである項目レベル ロックまたはページ レベル ロッ クの代わりに、インデックス レベル ロックを獲得します。このモードは、インデ ックス上のロック呼び出しの回数を削減します。 インデックスが変更されない場合、つまりインデックス上で読込み専用の操作が行 われる場合は、コアース ロック モードを使用します。 データベース サーバが必要に応じてインデックスに項目レベル ロックまたはペー ジ レベル ロックを設定するようにする場合は、通常のロック モードを使用しま す。インデックスが頻繁に更新される場合は、このモードを使用します。 データベース サーバがコマンドを実行してロック モードをコアースに変更する場 合、コマンドが継続している間は、表に排他ロックが設定されます。データベース サーバをコアース ロック モードに変更する前に、その時点で微小細分度のロック を使用しているあらゆるトランザクションを完了しておく必要があります。 スマート ラージ オブジェクト ロック (IDS のみ) 文字ラージ オブジェクト (CLOB) 型またはバイナリ ラージ オブジェクト (BLOB) 型列上のロックは、行上のロックと区別されます。スマート ラージ オブジェクト は、アクセスされたときのみロックされます。文字ラージ オブジェクト (CLOB) 型または バイナリ ラージ オブジェクト (BLOB) 型列を含む表をロックする場 合、スマート ラージ オブジェクトはすべてロックされません。書込みのためにア クセスされると、スマート ラージ オブジェクトは更新モードでロックされ、実際 に書込みが行われるときに排他ロックになります。読込みのためにアクセスされる と、スマート ラージ オブジェクトは共有モードでロックされます。データベース サーバはトランザクションの排他モードを認識するため、繰返し可能読込みの排他 レベルが設定されている場合は、トランザクションが終わるまでスマート ラージ オブジェクトの読込みロックを解除しません。 データベース サーバが行を抽出し、行が指し示すスマート ラージ オブジェクトを 更新すると、更新中はスマート ラージ オブジェクトにだけ排他ロックが設定され ます。 バイト範囲ロック: スマート ラージ オブジェクトに対して、ある範囲のバイトを ロックできます。バイト範囲ロックを使用すると、トランザクションはロックする バイトを選択できるので、同じスマート ラージ オブジェクトの異なるバイト範囲 に書込みおよび読込みで同時にアクセスできます。 第 10 章 マルチユーザ環境のためのプログラミング 243 バイト範囲ロックの使用方法については、「IBM Informix: パフォーマンス ガイ ド」を参照してください。 バイト範囲ロックは、デッドロック検出をサポートします。デッドロック検出につ いて、詳しくは、 254 ページの『デッドロックの処理』を参照してください。 ロックの継続期間 データベースに対するロックの継続期間はプログラムが管理します。データベース ロックは、そのデータベースがクローズされると解除されます。 表に対するロックの継続期間は、データベースがトランザクションの使用状況に応 じて変化します。トランザクションを使用していない場合 (すなわちトランザクシ ョン ログがなく COMMIT WORK 文が使用されていない場合) は、表ロックは UNLOCK TABLE 文によって解除されるまで続きます。 表、行、インデックスに対するロックの継続期間は、使用している SQL 文の種類 と、トランザクションの使用状況に応じて変化します。 トランザクションを使用する場合は、トランザクションの終わりに、すべての表、 行、ページ、およびインデックス ロックが解除されます。トランザクションが終了 するとき、すべてのロックが解除されます。 データ修正中のロック UPDATE カーソルを使用して行を取り出す場合、データベース サーバは取り出さ れた行に対して増進可能なロックを設定します。この設定により、他のプログラム はその行を変更できなくなります。増進可能なロックは、排他ロックとは異なり、 ロック中も他のプログラムはその行を引続き読み込むことができます。この結果、 その行を取り出したプログラムが UPDATE 文か DELETE 文を実行するまでに少し 時間がかかるときでも、他のプログラムは待機する必要がなくなったり、次の行を 取り出したりすることができるため、同時実行性が高まり、パフォーマンスが向上 します。行の更新が必要になると、データベース サーバはその行に対し排他ロック を設定します。その行に増進可能なロックがすでに設定されている場合は、データ ベース サーバは増進可能なロックを排他ロックに変更します。 行に対する排他ロックの継続期間は、トランザクションの使用状況に応じて変化し ます。トランザクションが使用されていない場合は、変更された行がディスクに書 き込まれると排他ロックはすぐに解除されます。トランザクションが使用されてい る場合は、トランザクションが終了するまで排他ロックが続きます。したがって、 ロール バックされる可能性のある行を他のプログラムが使用することはありませ ん。 トランザクションが使用されている場合、行が削除されるときは、インデックス キ ーに対するロックが常に使用されます。これは、次のようなエラーの発生を防止す るためです。 v プログラム A が行を削除する。 v プログラム B が、その行と同じキーを持つ行を挿入する。 v プログラム A がトランザクションをロール バックして、削除した行を復元す る。 244 IBM Informix: SQL ガイド: チュートリアル この場合、プログラム B によって挿入された行を処理しようとするため、エラー が発生します。 インデックスをロックすれば、プログラム A がそのトランザクションを確定するま では、プログラム B が行を挿入することはできません。 データベース サーバが行を読み込む間に設定されたロックは、現在の排他レベルに 従って制御されます。これについては、次の節で説明します。 SELECT 文でのロック データベース サーバが設定するロックのタイプと継続期間は、アプリケーションで 設定された排他レベル、および SELECT 文が UPDATE カーソルの範囲内にあるか どうかにより異なります。このセクションでは、異なる排他レベルおよび UPDATE カーソルについて説明します。 排他レベルの設定 排他レベル とは、あるプロセスが他のプロセスの並列動作から分離する程度を意味 します。データベース サーバでは、プログラムがデータを読み込むときどのように ロックを使用するか、異なる設定のルールを反映する排他レベルを選択できます。 排他レベルを設定するには、 SET ISOLATION または SET TRANSACTION のい ずれかを使用してください。さらに、SET TRANSACTION により、アクセス モー ドの設定が可能です。アクセス モードの詳細については、252 ページの『アクセス モードによるデータ変更の制御』を参照してください。 SET TRANSACTION 文と SET ISOLATION 文の比較 SET TRANSACTION 文は、ANSI SQL-92 に準拠します。この文は、Informix SET ISOLATION 文と類似しています。ただし、SET ISOLATION 文は ANSI に準拠し ておらず、アクセス モードを提供しません。 以下の表に、SET TRANSACTION および SET ISOLATION 文を使用して設定し た、排他レベル間の関係を示します。 SET TRANSACTION ” 相関性 ” SET ISOLATION 非確定読込み 単純読込み 確定読込み 確定読込み サポートなし カーソル安定性 (ANSI) 繰返し可能読込み 直列化可能 (Informix) 繰返し可能読込み (Informix) 繰返し可能読込み SET TRANSACTION 文と SET ISOLATION 文との主な違いは、トランザクション 内の排他レベルの動作です。 SET TRANSACTION 文は、トランザクションに対し 1 回のみ発行できます。トランザクション中にオープンされたカーソルは、必ず排 他レベル (アクセス モードを定義している場合にはアクセス モード) が設定されま す。SET ISOLATION 文ではトランザクション開始後、トランザクション中に排他 レベルを何回も変更することができます。以下の例は、SET ISOLATION の使用と SET TRANSACTION の使用との違いを示しています。 第 10 章 マルチユーザ環境のためのプログラミング 245 SET ISOLATION: EXEC SQL BEGIN WORK; EXEC SQL SET ISOLATION TO DIRTY READ; EXEC SQL SELECT ... ; EXEC SQL SET ISOLATION TO REPEATABLE READ; EXEC SQL INSERT ... ; EXEC SQL COMMIT WORK; -- Executes without error SET TRANSACTION: EXEC SQL BEGIN WORK; EXEC SQL SET TRANSACTION ISOLATION LEVEL TO SERIALIZABLE; EXEC SQL SELECT ... ; EXEC SQL SET TRANSACTION ISOLATION LEVEL TO READ COMMITTED; Error 876: Cannot issue SET TRANSACTION more than once in an active transaction. 排他レベルの非確定読込み (ANSI) と単純読込み (Informix) 最も簡潔な排他レベルである非確定読込み (ANSI) と単純読込みは、実質的に排他 性がありません。行を取り出すとき、プログラムはロックをまったく設定せず、他 のプログラムによるロックも認識しません。データベースの行をコピーするのみ で、他のプログラムがどのような操作をしているかについては考慮しません。 プログラムは常に、完全な行を受け取ります。排他レベルの設定が非確定読込み (ANSI) または単純読込み (Informix) であっても、一部の列のみが更新されている行 をプログラムが読み込むことはありません。ただし、あるプログラムが行を更新す るトランザクションを終了する前に、排他レベルとして非確定読込み (ANSI) また は単純読込み (Informix) を設定してある別のプログラムが、更新後の行を読み込む 可能性はあります。この場合、更新しているプログラムが後でそのトランザクショ ンをロール バックすると、読込みプログラムは実際には存在しなかったデータを処 理することになります (237 ページの同時実行性に関する問題のリストの 4 に該当 します)。 非確定読込み (ANSI) または 単純読込み (Informix) は、最も効率的な排他レベルで す。プログラムが読込みのために待機することはなく、他のプログラムを待機させ ることもありません。この排他レベルは、次のような場合によく使用されます。 v どの表も静的な場合。 すなわち、並列的に実行されるプログラムはデータを読み 込むだけで、データを変更することは絶対にない場合 v 表に対し排他ロックが設定されている場合 v 表を使用しているプログラムが 1 つのみであることが確実な場合 排他レベルの確定読込み (ANSI) および確定読込み (Informix) プログラムが排他レベルに確定読込み (ANSI) または確定読込み (Informix) を要求 した場合、データベース サーバでは、確定がまだ済んでいない行は絶対に戻されな いようになります。これにより、確定が済んでいないデータを読み込んだ後で、そ のデータがロール バックされる問題は回避されます。 確定読込み (ANSI) または確定読込み (Informix) は、簡潔に実装されます。行を取 り出す前に、データベース サーバは、更新中のプロセスがその行にロックを設定し たかどうかをテストします。 ロックが設定されていなければ、データベース サー 246 IBM Informix: SQL ガイド: チュートリアル バはその行を戻します。更新は済んだがまだ確定されていない行にはロックが設定 されているため、このテストを行うことにより、非確定のデータをプログラムが読 み取ることはありません。 確定読込み (ANSI) または確定読込み (Informix) は、取り出された行に実際にロッ クを設定するわけではないので、この排他レベルは、非確定読込み (ANSI) または 単純読込み (Informix) とほぼ同様に効率的です。この排他レベルは、各行のデータ が、他の行 (同じ表、または他の表の) を参照しない、独立した単位として処理され る場合に適しています。 排他レベルのカーソル安定性 (Informix) 次のレベルであるカーソル安定性は、 Informix SQL 文である SET ISOLATION を 使用する場合に限り、利用できます。 Dynamic Server 排他レベルにカーソル安定性を設定した場合、Dynamic Server は取り出された最新 の行のみにロックを設定します。通常のカーソルについては共有ロック、UPDATE カーソルについては増進可能なロックを設定します。一度にロックされるのは、1 行のみです。つまり、1 行取り出されるたびに、前の行に設定されていたロックは 解除されます。ただし、前の行が更新された行である場合は、この行のロックはト ランザクションが終了するまで解除されません。 Dynamic Server の終り Extended Parallel Server カーソル安定性が有効になっている場合、Extended Parallel Server は 2 行以上にロ ックを設定します。通常のカーソルについては共有ロック、UPDATE カーソルにつ いては増進可能なロックを設定します。構成パラメータ ISOLATION_LOCKS を使 用して、所定の時刻に所定の走査をロックする最大行数を指定します。データベー ス サーバには、現在ロックされている行セットにユーザの現在行が含まれます。次 の行がカーソルから読み込まれるため、前の行が解除される場合も解除されない場 合もあります。どの行がロックされ、これらの行がいつ解除されるかは制御できま せん。データベース サーバは、最大 n 行が所定のカーソルについて所定の時にロ ックされること、および現在の行が現在ロックされている行セットにあることのみ を保証します。 (デフォルト値は 1 行です。) ISOLATION_LOCKS パラメータの詳 細については、「IBM Informix: パフォーマンス ガイド」および「IBM Informix: 管 理者ガイド」を参照してください。 Extended Parallel Server の終り カーソル安定性では、1 回にロックされる行の数は、Dynamic Server の場合は 1 行、Extended Parallel Server の場合は指定された数のみであるため、表やデータベ ースに対するロックの場合よりも同時実行性が向上します。 カーソル安定性は、プログラムが行を調べている最中に、その行が変化しないこと を保証します。このことが重要になるのは、その行から読み込んだデータを基に、 第 10 章 マルチユーザ環境のためのプログラミング 247 プログラムが他の表を更新する場合です。排他レベルにカーソル安定性が設定され ていれば、更新は必ず現在の情報を基に行われます。これにより、失効したデータ の使用が回避されます。 次に排他レベルのカーソル安定性の効果的な使用方法を示します。プログラム A は、デモンストレーション データベースの表 stock に、ヒーロースポーツ社 (HRO) の新しい取扱品目を 1 つ挿入しようとしています。それと同時に、プログラ ム B は、ヒーロースポーツ社に関する情報と、このメーカーに関係するすべての取 扱品目を削除しようとしています。この場合、次のような一連のイベントが発生す る可能性があります。 1. 排他レベルにカーソル安定性を使用するプログラム A が、メーカー コードを検 出するために表 manufact から HRO の行を取り出します。これにより、この 行には共有ロックが設定されます。 2. プログラム B は、行に対し DELETE 文を発行します。この行にはロックが設 定されているため、データベース サーバはプログラム B を待機させます。 3. プログラム A が、表 manufact から取り出したメーカー コードを使用して、 表 stock に新しい行を挿入します。 4. プログラム A が、表 manufact に対するそのカーソルをクローズ、あるいは表 manufact の別の行を読み、そのロックを解除します。 5. 待機状態でなくなったプログラム B が、表 manufact からヒーロースポーツ社 の行を削除し、さらにメーカー コードが HRO の行を表 stock から削除しま す。プログラム A が表 stock にいま挿入した行も削除します。 プログラム A が使用する排他レベルがカーソル安定性よりも低い場合には、次のよ うな一連のイベントが発生する可能性があります。 1. プログラム A が、メーカー コードを検出するために表 manufact から HRO の行を読み込みます。ロックは設定されません。 2. プログラム B は、行に対し DELETE 文を発行します。実行は成功します。 3. プログラム B が、メーカー コードが HRO のすべての行を表 stock から削除 します。 4. プログラム B が終了します。 5. 読み込んだ HRO の行が無効となったことを認識しないプログラム A が、メー カー コード HRO を使用し表 stock に新しい行を挿入します。 6. プログラム A が終了します。 プログラム A が終了した時点では、メーカー コードが表 manufact にない行が表 stock に 1 行存在するという結果になります。さらに、プログラム B にはバグが あるかのように見えます。 つまり、プログラム B が削除すべき行を削除しなかっ たことになります。プログラム A が排他レベルとしてカーソル安定性を使用すれ ば、このような結果にはなりません。 排他レベルとしてカーソル安定性が使用されていてもエラーが発生するように、こ の例の順序を並替えることもできます。プログラム A とは逆の順番でプログラム B が表を操作するように並替えればいいのです。 例えば、プログラム B が表 manufact を削除する前に、表 stock の行を削除した場合、どのレベルの排他を行 248 IBM Informix: SQL ガイド: チュートリアル ってもエラーの発生を防止できません。このようなエラーが発生する可能性がある 場合は、関係するすべてのプログラムが同じ順番で表にアクセスするようにするこ とが必要です。 直列化可能 (ANSI)、繰返し可能読込み (ANSI)、および繰返し可能読 込み (Informix) 排他レベル 直列化可能 (ANSI) または繰返し可能読込み (ANSI) が必要な場合、繰返し可能読 込み (Informix) と呼ばれる単一の排他レベルが提供されます。これは、論理的に 直 列化可能 (ANSI) と同等です。直列化可能 (ANSI) は繰返し可能読込み (ANSI) よ りも制限されるため、繰返し可能読込み (ANSI) が望ましい場合、 (このようなコ ンテキストでは繰返し可能読込み (Informix) が必要以上に制限されるにもかかわら ず) 繰返し可能読込み (Informix) を使用できます。 繰返し可能読込みの排他レベルでは、データベース サーバは、プログラムが検証 し、取り出すすべての行にロックを設定します。通常のカーソルについては共有ロ ック、UPDATE カーソルについては増進可能なロックが設定されます。各行が検証 される際、ロックは個別に設定されます。カーソルがクローズされるかトランザク ションが終了するまで、ロックは解除されません。 排他レベルに繰返し可能読込みを設定すると、スクロール カーソルを使用するプロ グラムは、一度読み込んだ行を再び読み込むまでの間に、行が更新されたり削除さ れたりしていないことを確かめるために、選択された行を何度でも繰返し読み込む ことができます。 (第 8 章で、スクロール カーソルについて説明しています。) 繰 返し可能読込みより低い排他レベルでは、行がまだ存在することと、2 回目の読込 みでも変化しないことは保証されません。 繰返し可能読込みとして設定されるロックは、ロックされる行数の点でも継続期間 の点でも、他の排他レベルよりも高いレベルになります。したがって、排他レベル として繰返し可能読込みを設定すると同時実行性がもっとも低下する可能性があり ます。プログラムがこの排他レベルを使用する場合は、設定されるロックの数、継 続期間、他のプログラムに対する影響について慎重に検討することが必要です。 ロックの数が多いことは、同時実行性に影響するだけでなく、困難な状況をもたら すことがあります。データベース サーバは各プログラムのロック数をロック表に記 録します。ロック数が最大数を超えるとロック表はフルになり、データベース サー バはそれ以上ロックを設定できなくなります。その場合、エラー コードが戻されま す。 Informix データベース サーバ システムの管理者は、このロック表を監視し、 表の使用頻度に注意してください。 ANSI 標準準拠のデータベースでは、排他レベルがデフォルトで直列化可能に設定 されます。直列化可能排他レベルでは、SQL の ANSI 標準に準拠して動作している か、確認が必要です。 UPDATE カーソル UPDATE カーソルは、行が更新される可能性があるときにアプリケーションが使用 できる特殊なカーソルです。 UPDATE カーソルを使用するには、SELECT FOR UPDATE 文をアプリケーションにて実行します。 UPDATE カーソルは増進可能ロ ック を使用します。つまり、データベース サーバはアプリケーションが行を取り 出す場合に、更新ロック (他のユーザはまだ行を表示できることを意味します) を設 第 10 章 マルチユーザ環境のためのプログラミング 249 定します。しかし、アプリケーションが UPDATE カーソルおよび UPDATE...WHERE CURRENT OF 文を使用して行を更新する場合は、ロックは排他 ロックに変更されます。 UPDATE カーソルを使用する利点は、行を表示していれば更新するまでの間、他の ユーザは UPDATE カーソルでその行を変更または表示できないことです。 ヒント: ANSI 準拠のデータベースでは、SELECT カーソルが UPDATE カーソル と同じ動作を行うため、UPDATE カーソルは不要です。 図 356 の疑似コードは、データベース サーバがいつ、どこでカーソルにロックを設 定し解除するかを示します。 図 356. 更新のために設定するロック 更新ロックの保存 ユーザが繰返し可能読込みより低い排他レベルを設定している場合は、データベー ス サーバは、カーソルから次の行が取り出されるとすぐに、行に設定された更新ロ ックを解除します。この機能とともに RETAIN UPDATE LOCKS 節を使用するこ とにより、次の排他レベルのいずれかを設定している場合は、トランザクションの 終わりまで更新ロックを保持できます。 v 単純読込み v 確定読込み v カーソル安定性 この機能により、繰返し可能読込みの排他レベルのオーバーヘッド、または行をダ ミーで更新する動作などのオーバーヘッドを避けることができます。 RETAIN UPDATE LOCKS 機能がオンになり、更新ロックが暗黙的に行に設定されると、 SELECT...FOR UPDATE 文の取出しの間はトランザクションの終わりまで更新ロッ クは解除されません。 RETAIN UPDATE LOCKS 機能では更新ロックのみがトラ ンザクションの終わりまで保持されますが、繰返し可能読込みの排他レベルでは更 新ロックと共有ロックの両方がトランザクションの終わりまで保持されます。 次の例では、排他レベルを確定読込みに設定した場合の RETAIN UPDATE LOCKS 節の使用方法を示します。 SET ISOLATION TO COMMITTED READ RETAIN UPDATE LOCKS RETAIN UPDATE LOCKS 機能をオフにするには、 RETAIN UPDATE LOCKS 節 を使用せずに排他レベルを設定してください。機能をオフにすると、更新ロックは 250 IBM Informix: SQL ガイド: チュートリアル 直接解除されません。しかし、これ以降では、直前の取出しの更新ロックは後続の 取出しによって解除されますが、それ以前の取出し操作のロックは解除されませ ん。クローズ カーソルは、現在行の更新ロックを解除します。 排他レベルを指定する場合の RETAIN UPDATE LOCKS 機能の使用方法につい て、詳しくは、「IBM Informix: SQL ガイド: 構文」を参照してください。 INSERT 文、UPDATE 文、および DELETE 文により設定するロック INSERT 文、UPDATE 文、または DELETE 文を実行する場合、データベース サー バは排他ロックを使用します。排他ロックは、他のユーザは単純読込みの排他レベ ルを使用していない限り、行を表示できないことを意味します。また、他のユーザ は、データベース サーバがロックを取り消すまでは、項目を更新または削除できま せん。 データベース サーバが排他ロックを取り消すタイミングは、データベースに設定さ れたログ機能の種類に依存します。データベースがログ機能を持つ場合は、データ ベース サーバは、トランザクションが完了 (確定またはロール バック) するときに 排他ロックを取消します。データベースにログ機能がない場合、データベース サー バは、 INSERT 文、UPDATE 文、または DELETE 文の完了後、即時にすべての排 他ロックを削除します。 ロック タイプの動作の理解 Informix データベース サーバは、内部のロック表にロックを格納します。データベ ース サーバは行を読み込むと、その行または関連付けられたページ、表、またはデ ータベースがロック表にリストされているかどうかをチェックします。ロック表に リストされている場合は、データベース サーバはロック タイプもチェックしま す。ロック表には、次のロック タイプを含めることができます。 ロックの名前 説明 ロックに通常設定される文 S 共有ロック SELECT X 排他ロック INSERT 文、UPDATE 文、DELETE 文 U 更新ロック UPDATE カーソル中の SELECT 文 B バイト ロック 可変長文字 (VARCHAR) 型列を更新する任意の文 また、ロック表は意図ロック を格納できます。意図ロックは、共有意図 (IS)、排他 意図 (IX)、または共有排他意図 (SIX) に分類されます。意図ロックは、データベー ス サーバ (ロック マネージャ) が、細分度の低いオブジェクトにロックを設定する 必要がないときに、細分度の高いオブジェクトに設定するロックです。例えば、ユ ーザが行またはページを共有ロック モードでロックすると、データベース サーバ は IS (共有意図) ロックを表に設定して、他のユーザが表に X ロックを保持してい ないかどうかをすぐにチェックします。この場合、意図ロックは表にのみ設定さ れ、行またはページには設定されません。意図ロックは、行、ページ、または表の レベルのみで設定できます。 ユーザは、意図ロックを直接制御できません。ロック マネージャがすべての意図ロ ックを内部で管理します。 第 10 章 マルチユーザ環境のためのプログラミング 251 次の表は、他のユーザ (またはデータベース サーバ) が特定のタイプのロックを保 持している場合に、ユーザ (またはデータベース サーバ) が設定できるロックを示 します。例えば、あるユーザが項目に排他ロックを保持している場合は、別のユー ザがどのような種類のロック (排他、更新、または共有) を要求してもエラーを受け 取ります。また、ユーザが項目に排他ロックを保持している場合は、データベース サーバはその項目にどのような意図ロックも設定することはできません。 X ロック を保持 U ロック を保持 S ロック を保持 IS ロック を保持 SIX ロック を保持 IX ロック を保持 X ロックを要 求 不可 不可 不可 不可 不可 不可 U ロックを要 求 不可 不可 可 可 不可 不可 S ロックを要求 不可 可 可 可 不可 不可 IS ロックを要 求 可 可 可 可 可 SIX ロックを要 不可 求 不可 不可 可 不可 不可 IX ロックを要 求 不可 不可 可 不可 可 不可 不可 ロックがパフォーマンスに及ぼす影響について、詳細は「IBM Informix: パフォーマ ンス ガイド」を参照してください。 アクセス モードによるデータ変更の制御 Informix データベース サーバでは、アクセス モードをサポートしています。アク セス モードは SET TRANSACTION 文で設定され、トランザクション中の行の読 込みと書込みの同時実行性に影響を与えます。アクセス モードを使用して共有ファ イル間のデータ更新を制御できます。 トランザクションはデフォルトでは読込みと書込みが可能です。トランザクション を読込み専用に指定すると、そのトランザクションでは次のタスクは実行できませ ん。 v 行の挿入、削除、または更新 v スキーマ、表、一時表、インデックス、またはストアド ルーチンなどのデータベ ース オブジェクトの作成、変更、削除 v アクセス権の付与と取消し v 統計情報の更新 v 列名および行名の変更 読込み専用アクセス モードは更新を禁止します。 ルーチンが制限付きの文の実行を試行しない限り、ストアド ルーチンは読込み専用 トランザクションで実行できます。 アクセス モードを指定するための SET TRANSACTION 文の使用方法について は、「IBM Informix: SQL ガイド: 構文」を参照してください。 252 IBM Informix: SQL ガイド: チュートリアル ロック モードの設定 ロック モードにより、プログラムが操作しようとするデータがロックされている場 合のプログラムの動作が制御されます。ロックされている行をプログラムが取り出 そうとしたり、変更しようとした場合は、次の 3 つの結果のいずれかになります。 v データベース サーバは、SQLCODE または SQLSTATE に含まれるエラー コー ドを即時にプログラムに戻します。 v データベース サーバは、ロックを設定されたプログラムがロックを解除するま で、このプログラムをサスペンドします。 v データベース サーバは、しばらくの間プログラムをサスペンドし、その後ロック が解除されない場合、このプログラムはデータベース サーバからエラーの復帰コ ードを受け取ります。 SET LOCK MODE 文を使用して、3 つの結果のうちいずれかを選択します。 ロックの待機 ロックされている場合、データベース サーバはデフォルトの動作により、アプリケ ーションにエラーを戻します。ロックが解除されるまで待機する場合 (これは多く のアプリケーションで最適の選択です) は、次の SQL 文を実行します。 SET LOCK MODE TO WAIT このロック モードが設定されたプログラムでは、同時に実行される他のプログラム の存在を、通常は無視できます。他のプログラムがロックした行にアクセスしなけ ればならない事態になった場合は、このプログラムはロックが解除されるまで待機 し、解除されてからアクセスします。ほとんどの場合、遅延は認識できません。 また、次の例のように特定の秒数の間、待機することができます。 SET LOCK MODE TO WAIT 20 ロックの解除を待機しない ロックの解除を待つことの欠点は、待ち時間が長くなる可能性があることです (適 切に設計されたアプリケーションのロック保持は短時間)。長時間の遅延の可能性が 受け入れられない場合は、プログラムは次の文を実行できます。 SET LOCK MODE TO NOT WAIT このモードが設定されると、ロックされている行にプログラムがアクセスした場合 はすぐに、行がロックされていることを示す -107 DTP 行はロックされています。 などのエラー番号がプログラムに戻され、実行中の SQL 文は終了します。プログ ラムは現行トランザクションをロール バックして、操作を再試行する必要がありま す。 プログラム始動時の初期設定では、待機 しません。SQL を対話的に使用してい て、ロックに関連するエラーが表示された場合は、ロックモードを WAIT モードに 設定してください。プログラムを作成している場合は、プログラムが実行する組込 み SQL 文の 1 つを検討してください。 第 10 章 マルチユーザ環境のためのプログラミング 253 一定時間ロックの解除を待機する 次の文により、待機時間の上限を設定するようにデータベース サーバに要求するこ とができます。 SET LOCK MODE TO WAIT 17 この文は、待機時間の上限を 17 秒に設定します。この時間が経過するまでにロッ クが解除されない場合は、エラーが戻されます。 デッドロックの処理 デッドロック とは、2 つのプログラムが互いに他の実行を妨害しあう状態のことで す。プログラム同士は、相手のプログラムがアクセスするオブジェクトにロックを 設定しています。デッドロックが検出される可能性があるのは、関係するすべての プログラムがそのロック モードを WAIT モードに設定している場合のみです。 Informix データベース サーバでは、デッドロックが単一のネットワーク サーバの データのみに関係する場合は、すぐにデッドロックを検出できます。デッドロック の発生を防止するために、エラー コード (-143 SAM エラー: デッドロックが検出さ れました。) を 2 番目のプログラムに戻してロックを要求します。このエラーは、 そのプログラムがロック モードを NOT WAIT モードに設定した場合に受け取るは ずのエラーです。したがって、プログラムがロック モードを WAIT モードに設定 したにもかかわらず、ロックに関連するエラー番号を受け取った場合は、デッドロ ックの発生が事前に検出されたことがわかります。 外部デッドロックの処理 異なるデータベース サーバ上のプログラムの間でも、デッドロックが検出されるこ とがあります。この場合、データベース サーバはデッドロックをすぐには検出でき ません。 (ネットワーク上のすべてのデータベース サーバ間で膨大な量の通信を行 わない場合は、デッドロックを完全には検出できません。) そのかわり、各データ ベース サーバは、異なるデータベース サーバのロックされたデータを取得するま でにプログラムが待機できる時間の上限を設定します。その制限時間が経過した場 合は、データベース サーバはデッドロックが原因であったと想定し、ロックに関連 するエラー番号を戻します。 すなわち、外部データベースが関係する場合は、どのプログラムも、そのロックの 最大待機時間が設定された状態で実行されます。 DBA は、データベース サーバに 対する最大待機時間を設定または修正できます。 単純な並行性 ロックと同時実行性に関する設定を確定できない場合、アプリケーションが単純な ものなら、次の簡単な基準を使用できます。 起動の際、すなわち最初の CONNECT および DATABASE 文の直後で、次の文をプログラムに実行させます。 SET LOCK MODE TO WAIT SET ISOLATION TO REPEATABLE READ これらの文が戻す値は無視してください。他のプログラムは存在しないものとし て、実行を続けてください。これでパフォーマンスに関する問題が発生しなけれ ば、設定を検討し直す必要はありません。 254 IBM Informix: SQL ガイド: チュートリアル HOLD カーソル Dynamic Server トランザクション ログ機能が使用される場合、 Dynamic Server は、トランザクシ ョン内で実行されるすべての処理がその終わりにロール バックされることを保証し ます。トランザクションを確実に扱うために、データベース サーバには、通常次の ルールが適用されます。 v トランザクションが終了するとき、すべてのカーソルがクローズされる。 v トランザクションが終了するとき、すべてのロックが解除される。 Dynamic Server の終り Extended Parallel Server Extended Parallel Server はトランザクションの終了時に、ロックを解除しないこと があります。表ロックを獲得する方法を示すために、データベース サーバが表の一 部を格納するすべてのコサーバのロックを獲得すると仮定します。トランザクショ ンがまず SHARED モード表ロックを獲得し、EXCLUSIVE モード表ロックにアッ プグレードしようとする場合、ロックはトランザクションの終了時に解除されない 場合もあります。これは、トランザクションがを実行し、その後ロック モード TABLE を使用して表内の INSERT 文を実行する場合に発生します。この場合、コ サーバによってはアップグレードに成功するものとしないものがあります。成功し たアップグレードにはロール バックは試行されません。これは、いくつかのコサー バについては、トランザクションが表の EXCLUSIVE ロックで終了する場合がある ことを意味します。 Extended Parallel Server の終り トランザクションを確実に処理するこれらのルールは、トランザクションをサポー トするデータベース システムでは通常のルールです。そしてほとんどのアプリケー ションでは問題の原因になりません。しかし、カーソルとともに標準トランザクシ ョンを使用できない場合があります。例えば、次のコードはトランザクションがな くても正常に動作します。しかし、トランザクションが追加されると、2 つのカー ソルを並行して使用することにより、カーソルのクローズで衝突が生じます。 EXEC SQL DECLARE master CURSOR FOR EXEC SQL DECLARE detail CURSOR FOR FOR UPDATE EXEC SQL OPEN master; while(SQLCODE == 0) { EXEC SQL FETCH master INTO if(SQLCODE == 0) { EXEC SQL BEGIN WORK; EXEC SQL OPEN detail USING EXEC SQL FETCH detail EXEC SQL UPDATE WHERE CURRENT OF detail EXEC SQL COMMIT WORK; } } EXEC SQL CLOSE master; 第 10 章 マルチユーザ環境のためのプログラミング 255 この設計では、カーソルの 1 つは表の走査に使用されます。表から取り出されたレ コードを基にして、別の表が更新されます。問題は、前述の例の疑似コードに示し たとおり、各更新が個別のトランザクションとして扱われるとき、UPDATE 文に続 く COMMIT WORK 文が主カーソルを含むすべてのカーソルをクローズすることで す。 この問題に対するもっとも簡単な解決策は、主表全体に対する走査が 1 つの大きな トランザクションになるように、COMMIT WORK 文と BEGIN WORK 文がそれぞ れ最後と最初の文になるようにすることです。主表に対する走査を 1 つの大きなト ランザクションとして扱う場合もありますが、更新すべき行が非常に多い場合は非 実際的になります。ロックの数が膨大になります。しかも、これらのロックはプロ グラムの実行が終了するまで保持されます。 この問題の解決策として、Informix データベース サーバでは、主カーソルの宣言に キーワード WITH HOLD を追加できます。このキーワードを付けて宣言されたカ ーソルは HOLD カーソル と呼ばれ、トランザクションが終了してもクローズされ ません。その他のすべてのカーソルはクローズされ、ロックもすべて解除されます が、 HOLD カーソルは明示的にクローズされるまでオープンされた状態を保ちま す。 HOLD カーソルを使用する場合は、その前に、ここで説明したロック機能を十分理 解するとともに、同時実行される他のプログラムについても十分理解してくださ い。ロックと同時実行性に関する理解が必要になるのは、COMMIT WORK 文を実 行すると、ロックがすべて解除されてしまうためです。HOLD カーソルを使用して 取り出された行に設定されていたロックも、解除されてしまいます。 カーソルが、表全体を順方向に 1 回走査する目的で使用される場合は、HOLD カー ソルを宣言してもあまり意味はありません。しかし、キーワード WITH HOLD を、UPDATE カーソル、スクロール カーソルを含む、あらゆるカーソルにも指定 できます。これを実行する前に、表全体のロックを含むすべてのロックが、トラン ザクションの終了時に解放されることを理解してください。 SQL 文キャッシュの使用 SQL 文のキャッシュ機能を使用すると、繰返し実行される同一の SQL 文をバッフ ァに格納して、異なるユーザのセッションで文を再使用できるため、セッションの たびにメモリを割当てる必要がありません。文をキャッシュすると、処理された文 を多く含むアプリケーションのパフォーマンスを著しくに改善できます。ただし、1 回だけ処理して何回も実行する文をキャッシュするために、文のキャッシュを使用 する場合は、パフォーマンス改善はそれほど顕著ではありません。 データベース サーバについて文のキャッシュが可能である場合は、SQL 文を使用 して、個別のデータベース セッションについて文のキャッシュを行なうかを切り替 えます。次に、SQL 文を使用して、現在のデータベース セッションのキャッシュ をオンにする方法を示します。 SET STATEMENT_CACHE ON 次の文で、SQL における現在のデータベース セッションのキャッシュをオフにす る方法を示します。 SET STATEMENT_CACHE OFF 256 IBM Informix: SQL ガイド: チュートリアル キャッシュが無効になっている場合に、文のキャッシュをオンまたはオフにしよう とすると、データベース サーバはエラーを戻します。 SET STATEMENT CACHE 文の構文について、詳しくは、「IBM Informix: SQL ガ イド: 構文」を参照してください。 STMT_CACHE および STMT_CACHE_SIZE 構成パラメータについては、「IBM Informix: 管理者の参照」および「IBM Informix: パフォーマンス ガイド」を参照してください。STMT_CACHE 環境変数について は、「IBM Informix: SQL ガイド: 参照」を参照してください。 サマリ 複数のプログラムが並行してデータベースにアクセスしている場合 (そのうち 1 つ でもデータを変更することができる場合)、すべてのプログラムは他のプログラム が、仮にデータを読み込むだけであっても、データを変更できる可能性のあること を理解しなければなりません。データベース サーバは、プログラムがあたかもデー タを占有しているかのように実行することを許す、ロックと排他レベルの機構を提 供します。 SET STATEMENT CACHE 文により、繰り返し使用される同一の SQL 文をバッフ ァに格納できます。文のキャッシュをオンにすると、データベース サーバは同一の 文を格納するため、異なるユーザ セッションで再使用が可能であり、セッションの たびにメモリを割当てる必要がありません。 第 10 章 マルチユーザ環境のためのプログラミング 257 258 IBM Informix: SQL ガイド: チュートリアル 第 11 章 SPL ルーチンの作成と使用 SPL ルーチンの概要 . . . . . . . . . . . . . . . . . . . . SPL ルーチンの機能 . . . . . . . . . . . . . . . . . . . Extended Parallel Server での SPL ルーチンの動作 . . . . . . . . . SPL ルーチンの作成 . . . . . . . . . . . . . . . . . . . . CREATE PROCEDURE 文または CREATE FUNCTION 文の使用 . . . . ルーチンの開始と終了 . . . . . . . . . . . . . . . . . ルーチン名の指定 . . . . . . . . . . . . . . . . . . . 固有名の追加 (IDS のみ) . . . . . . . . . . . . . . . . パラメータ リストの追加 . . . . . . . . . . . . . . . . パラメータとしてシンプル ラージ オブジェクトを使用 . . . . . 未定義の引数 . . . . . . . . . . . . . . . . . . . RETURN 節の追加 . . . . . . . . . . . . . . . . . . 表示ラベルの追加 (IDS のみ) . . . . . . . . . . . . . . . SPL 関数がバリアントであるかどうかの指定 . . . . . . . . . . 修飾子の追加 (IDS のみ) . . . . . . . . . . . . . . . . COMMUTATOR 修飾子 . . . . . . . . . . . . . . . . NEGATOR 修飾子 . . . . . . . . . . . . . . . . . . DOCUMENT 節の指定 . . . . . . . . . . . . . . . . . リスト ファイルの指定 . . . . . . . . . . . . . . . . . コメントの追加. . . . . . . . . . . . . . . . . . . . 完全なルーチンの例 . . . . . . . . . . . . . . . . . . . プログラム内の SPL ルーチンの作成 . . . . . . . . . . . . . SPL ルーチンの削除 . . . . . . . . . . . . . . . . . . . 変数の定義と使用 . . . . . . . . . . . . . . . . . . . . . 局所変数の宣言. . . . . . . . . . . . . . . . . . . . . 局所変数の範囲. . . . . . . . . . . . . . . . . . . . 組込み型変数の宣言 . . . . . . . . . . . . . . . . . . スマート ラージ オブジェクト用の変数の宣言 (IDS のみ) . . . . . シンプル ラージ オブジェクト用の変数の宣言 . . . . . . . . . コレクション (COLLECTION) 型変数の宣言 (IDS のみ) . . . . . . 行 (ROW) 型変数の宣言 (IDS のみ) . . . . . . . . . . . . . 不透明 (OPAQUE) 型およびディスティンクト (DISTINCT) 型変数の宣言 LIKE 節による列データ用変数の宣言 . . . . . . . . . . . . PROCEDURE 型変数の宣言 . . . . . . . . . . . . . . . 変数とサブスクリプトの使用 . . . . . . . . . . . . . . . 変数およびキーワードのあいまいさ . . . . . . . . . . . . . 変数と列の名前. . . . . . . . . . . . . . . . . . . 変数および SQL 関数 . . . . . . . . . . . . . . . . SPL ルーチン名および SQL 関数 . . . . . . . . . . . . 広域変数の宣言. . . . . . . . . . . . . . . . . . . . . 変数への値の代入 . . . . . . . . . . . . . . . . . . . . LET 文 . . . . . . . . . . . . . . . . . . . . . . 変数に値を代入する他の方法 . . . . . . . . . . . . . . . SPL ルーチンの式 . . . . . . . . . . . . . . . . . . . . . 文ブロックの記述 . . . . . . . . . . . . . . . . . . . . . 暗黙的および明示的文ブロック . . . . . . . . . . . . . . . カーソルの使用. . . . . . . . . . . . . . . . . . . . . FOREACH ループを使用したカーソルの定義 . . . . . . . . . . . IF - ELIF - ELSE 構造の使用 . . . . . . . . . . . . . . . . WHILE ループと FOR ループの追加 . . . . . . . . . . . . . © Copyright IBM Corp. 1996, 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 261 262 262 263 263 264 264 265 266 266 267 267 268 268 268 269 270 270 271 271 272 272 273 274 274 275 275 275 276 277 278 278 279 279 280 280 280 281 281 282 282 284 284 284 285 285 286 288 289 259 ループの終了 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SPL 関数からの値の戻り . . . . . . . . . . . . . . . . . . . . . . . . . . 単一値の戻り . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 複数値の戻り . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型データの処理 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . ピリオド表記の優先順位. . . . . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型式の更新 . . . . . . . . . . . . . . . . . . . . . . . . . . コレクションの処理 (IDS のみ) . . . . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型の使用 . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型の準備 . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型変数の宣言 . . . . . . . . . . . . . . . . . . 要素変数の宣言. . . . . . . . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型変数へのコレクション (COLLECTION) 型データの選択 . . . コレクション (COLLECTION) 型変数への要素の挿入 . . . . . . . . . . . . . . . . セット (SET) 型データまたはマルチセット (MULTISET) 型データへの挿入 . . . . . . . リスト (LIST) 型データへの挿入 . . . . . . . . . . . . . . . . . . . . . . リスト (LIST) 型のコレクションの基数検査 . . . . . . . . . . . . . . . . . . VALUES 節の構文 . . . . . . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型データからの要素の選択 . . . . . . . . . . . . . . コレクション (COLLECTION) 型データ問合せ . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型データ問合せの SPL ルーチンへの追加 . . . . . . . . コレクション (COLLECTION) 型要素の削除 . . . . . . . . . . . . . . . . . . . データベース内のコレクション (COLLECTION) 型データの更新 . . . . . . . . . . . コレクション全体の削除. . . . . . . . . . . . . . . . . . . . . . . . . コレクション (COLLECTION) 型要素の更新 . . . . . . . . . . . . . . . . . . . 変数によるコレクション (COLLECTION) 型データの更新 . . . . . . . . . . . . . コレクション全体の更新. . . . . . . . . . . . . . . . . . . . . . . . . . 行 (ROW) 型のコレクション (COLLECTION) 型データの更新 . . . . . . . . . . . . 入れ子コレクション (COLLECTION) 型データの更新 . . . . . . . . . . . . . . . コレクション (COLLECTION) 型データへの挿入 . . . . . . . . . . . . . . . . . 入れ子コレクションへの挿入 . . . . . . . . . . . . . . . . . . . . . . . 外部コレクション(COLLECTION) 型データへのコレクション (COLLECTION) 型データの挿入 内部コレクション (COLLECTION) 型データへの値の挿入 . . . . . . . . . . . . ルーチンの実行. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EXECUTE 文の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . CALL 文の使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 式の中のルーチンの実行. . . . . . . . . . . . . . . . . . . . . . . . . . RETURN 文による外部関数の実行 . . . . . . . . . . . . . . . . . . . . . . SPL ルーチンからのカーソル関数の実行 . . . . . . . . . . . . . . . . . . . . 動的ルーチン名の指定 . . . . . . . . . . . . . . . . . . . . . . . . . . ルーチンのアクセス権 . . . . . . . . . . . . . . . . . . . . . . . . . . . ルーチンを登録する権限. . . . . . . . . . . . . . . . . . . . . . . . . . ルーチンを実行する権限. . . . . . . . . . . . . . . . . . . . . . . . . . Execute アクセス権の付与と取消し . . . . . . . . . . . . . . . . . . . . . COMMUTATOR 関数と NEGATOR 関数をともなう Execute アクセス権 (IDS のみ) . . . . ルーチンに関連付けられたオブジェクトのアクセス権 . . . . . . . . . . . . . . . . ルーチンを実行するための DBA アクセス権 . . . . . . . . . . . . . . . . . . . SPL ルーチンのエラー検出 . . . . . . . . . . . . . . . . . . . . . . . . . . コンパイル時の警告の表示 . . . . . . . . . . . . . . . . . . . . . . . . . ルーチンのテキストの生成 . . . . . . . . . . . . . . . . . . . . . . . . . SPL ルーチンのデバッグ . . . . . . . . . . . . . . . . . . . . . . . . . . 例外処理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . エラー トラッピングと復旧 . . . . . . . . . . . . . . . . . . . . . . . . ON EXCEPTION 文の制御の有効範囲 . . . . . . . . . . . . . . . . . . . . . ユーザが生成する例外 . . . . . . . . . . . . . . . . . . . . . . . . . . SQL エラーのシミュレート. . . . . . . . . . . . . . . . . . . . . . . . 260 IBM Informix: SQL ガイド: チュートリアル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 291 292 292 294 294 294 295 295 296 297 297 297 298 298 299 300 300 301 301 302 303 304 305 306 307 308 309 310 311 312 312 314 315 315 317 317 318 318 319 320 320 321 321 322 322 323 324 325 325 326 328 328 329 329 330 入れ子コードを終了する RAISE EXCEPTION の使用 . SPL ルーチンで処理される行数のチェック . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 . 331 . 331 本章について この章では、SPL ルーチンの作成方法と使用方法を説明します。SPL ルーチンは、 IBM Informix ストアド プロシジャ言語 (SPL) で記述されたユーザ定義ルーチンで す。 IBM Informix SPL は SQL を拡張したものであり、ループやコントロールな どのフロー制御を実現します。データベースに対する Resource アクセス権を所有す るすべてのユーザが SPL ルーチンを作成できます。 SQL で書かれたルーチンは、可能な限り構文解析され、最適化され、次に、実行可 能形式でシステム カタログ表に格納されます。 SPL ルーチンは、SQL 主体のタス クに効果的です。SPL ルーチンは、C を始めとする外部言語で記述されたルーチン を実行でき、逆に外部ルーチンも SPL ルーチンを実行できます。 SQL で実行できるタスクは、すべて SPL ルーチンでも実行可能です。また、SQL よりも多くの機能を備えています。 SPL はデータベースに対して固有であり、SPL ルーチンは実行時よりも作成時に構文解析および最適化されます。このため、SPL ルーチンでは、特定のタスクのパフォーマンスを改善することができます。また、 SPL ルーチンは、クライアント アプリケーションとデータベース サーバ間のトラ フィックを削減し、プログラムの複雑さを解消します。 SPL 文の各構文については、「IBM Informix: SQL ガイド: 構文」に記載されてい ます。各文の構文には例が示されています。 SPL ルーチンの概要 SPL ルーチン には、SPLプロシジャ および SPL 関数 が含まれます。SPLプロシ ジャ は、値を戻さない SPL および SQL で記述されたルーチンです。 SPL 関数 は、単一値、複数のデータ型を含む値、または複数値を戻す SPL および SQL で記 述されたルーチンです。通常、値を戻す SPL で記述されたルーチンは、SPL 関数 になります。 SPL ルーチンを作成するには、SQL および SPL 文を使用します。 SPL 文は、 CREATE P ROCEDURE、CREATE PROCEDUREFROM、CREATE FUNCTION、お よび CREATE FUNCTION FROM 文内でのみ使用できます。これらの文はすべて、 IBM Informix ESQL/C のような SQL API で使用できます。なお、CREATE PROCEDURE および CREATE FUNCTION 文は、DB–Access で使用できます。 SPL ルーチンの機能 SPL ルーチンを使用して、データベースのパフォーマンス向上、アプリケーション 記述の単純化、およびデータ アクセスの制限または監視などの、幅広い目標を達成 できます。 SPL ルーチンは、実行可能形式で格納されるため、頻繁に繰り返されるタスクの実 行に使用することにより、パフォーマンスを向上できます。 SQL のみのコードに 代わり、SPL ルーチンを使用することで、構文解析、妥当性検査、および問合せ最 適化の反復をバイパスできます。 第 11 章 SPL ルーチンの作成と使用 261 SPL ルーチンを使用して、データを操作する SQL 文に値を渡すことができます。 例えば、ルーチンを使用すると次のことが実行可能です。 v 表に挿入する値を渡す。 v SELECT、DELETE、または UPDATE 文の条件節を構成する値を渡す。 データ操作ステートメントでルーチンを使用する 2 つアクションを紹介しました が、これら以外にも様々な用途があります。実際のところ、データ操作 SQL 文の 式はすべて、ルーチン呼出しで構成できます。 SQL 文を SPL ルーチン内で発行し、それらの SQL 文をデータベースから隠すこ ともできます。すべてのユーザが SQL を習得するよりは、SQL を習得した 1 人の ユーザが SQL の動作をカプセル化する SPL ルーチンを作成してデータベースに格 納し、他のユーザが実行できるようにする方が効率的です。 DBA アクセス権を持たないユーザが実行できる、DBA アクセス権付きの SPL ル ーチンを作成できます。この機能を使用することで、データベース内のデータへの アクセスを制限し、制御することができます。あるいは、SPL ルーチンによって、 特定の表またはデータにアクセスするユーザを監視できます。 SPL ルーチンを使用 してデータへのアクセスを制御する方法については、「IBM Informix: データベース 設計および実装 ガイド」を参照してください。 Extended Parallel Server での SPL ルーチンの動作 Extended Parallel Server は SPL プロシジャをサポートしますが、SPL 関数はサポ ートしません。 Extended Parallel Server では、以下の SPL プロシジャが、Dynamic Server の場合 と異なる動作をします。 v SYSPROCPLAN システム カタログ表 すべての Informix データベース サーバは、SPL プロシジャが作成されるたび に、SYSPROCPLAN システム カタログ表を修正します。 Dynamic Server で は、SPL プロシジャが実行中に新規問合せ実行計画を生成する場合、その SPL プロシジャの実行中にも SYSPROCPLAN システム カタログ表を修正します。し かし Extended Parallel Server では、SPL プロシジャの実行中に新規問合せ実行計 画が生成される場合でも、表 SYSPROCPLAN を修正することはありません。例 えば、SYSPROCPLAN システム カタログ表から計画が削除され、コサーバから プロシジャが実行された場合、計画は SYSPROCPLAN には復元されません。た だし、コサーバから UPDATE STATISTICS FOR PROCEDURE 文が実行された 場合は、SYSPROCPLAN の計画が更新されます。 v SPL プロシジャ呼出し SPL プロシジャ呼出しは、現行データベースおよびデータベース サーバ内の SPL プロシジャに対してのみ行うことができます。 SPL ルーチンの作成 SPL ルーチンは、開始文、文ブロック、および終了文から構成されます。文ブロッ クの中で、SQL または SPL 文を使用できます。 262 IBM Informix: SQL ガイド: チュートリアル SPL ルーチンの最大サイズは 64KB です。最大サイズには、データベースおよびル ーチン自体のあらゆる SPL 広域変数が含まれます。 CREATE PROCEDURE 文または CREATE FUNCTION 文の使 用 作成しているルーチンが値を戻すかどうかを最初に決定する必要があります。ルー チンが値を戻さない場合は、CREATE PROCEDURE 文を使用して、SPL プロシジ ャを作成します。ルーチンが値を戻す場合は、CREATE FUNCTION 文を使用して SPL 関数を作成します。 SPL ルーチンを作成する場合は、1 つの CREATE PROCEDURE 文または CREATE FUNCTION 文を使用して、ルーチンの本体を記述し、それを登録しま す。 ルーチンの開始と終了 値を戻さない SPL ルーチンを作成する場合は、CREATE PROCEDURE 文で始め、 キーワード END PROCEDURE で終了します。図 357 に、SPL プロシジャの開始 と終了の記述方法を示します。 CREATE PROCEDURE new_price( per_cent REAL ) . . . END PROCEDURE; 図 357. 命名規則の詳細については、「IBM Informix: SQL ガイド: 構文」の識別子に関する 説明を参照してください。 1 つ以上の値を戻す SPL 関数を作成するには、CREATE FUNCTION 文で始め、キ ーワード END FUNCTION で終了します。図 358 に、SPL 関数の開始と終了の記 述方法を示します。 CREATE FUNCTION discount_price( per_cent REAL) RETURNING MONEY; . . . END FUNCTION; 図 358. SPL ルーチンのテキストは、スペースとタブを含み全体で 64KB を超えることはで きません。 SPL ルーチンでは、キーワード END PROCEDURE または END FUNCTION が必須です。 重要: 以前の IBM Informix 製品との互換性を保つためには、 CREATE PROCEDURE を RETURNING 節とともに使用し、値を戻すユーザ定義ルー チンを作成します。これにより、使用するコードがより読みやすく、管理し やすくなります。ただし、CREATE PROCEDURE を値を戻さない SPL ルー チン (SPL プロシジャ) で使用し、 CREATE FUNCTION を 1 つ以上の値を 戻す SPL ルーチン (SPL 関数) で使用する場合に限ります。 第 11 章 SPL ルーチンの作成と使用 263 ルーチン名の指定 SPL ルーチンの名前を、CREATE PROCEDURE または CREATE FUNCTION 文の 直後、パラメータ リストの前に指定します。図 359 に例を示します。 CREATE PROCEDURE add_price (arg INT ) 図 359. Dynamic Server Dynamic Server を使用すると、複数の SPL ルーチンを同じ名前でも異なるパラメ ータで指定できます。この機能は、ルーチン オーバロード と呼ばれます。例え ば、次の SPL ルーチンを、それぞれデータベースの中に作成できます。 CREATE PROCEDURE multiply (a INT, b FLOAT) CREATE PROCEDURE multiply (a INT, b SMALLINT) CREATE PROCEDURE multiply (a REAL, b REAL) multiply() という名前のルーチンを呼び出す場合、データベース サーバがルーチン の名前と引数を評価し、実行するルーチンを決定します。 Dynamic Server の終り ルーチン分析 は、データベース サーバが、ルーチンの名前と引数のリストを基 に、使用できるルーチン シグネチャを検索するプロセスのことです。すべてのルー チンは、以下の情報に基づいた固有のシグネチャ を持ちます。 v ルーチンの型 (プロシジャまたは関数) v ルーチン名 v パラメータの数 v パラメータのデータ型 v パラメータの順序 ルーチンのシグネチャは、そのルーチンの完全なパラメータ リストを入力した場 合、CREATE、DROP、または EXECUTE 文で使用されます。例えば、図 360 の各 文では、ルーチンのシグネチャが使用されています。 CREATE FUNCTION multiply(a INT, b INT); DROP PROCEDURE end_of_list(n SET, row_id INT); EXECUTE FUNCTION compare_point(m point, n point); 図 360. 固有名の追加 (IDS のみ) Dynamic Server ではルーチン オーバロードをサポートするため、名前のみでは SPL ルーチンを個別に識別できない場合があります。このような場合は、固有名 を 使用することで、個別に識別できます。固有名 という固有 ID は、ルーチン名に加 え、CREATE PROCEDURE または CREATE FUNCTION 文で指定します。固有名 264 IBM Informix: SQL ガイド: チュートリアル は、キーワード SPECIFIC とともに定義し、データベース内で一意になります。同 じデータベース内の 2 つのルーチンは、それぞれが異なる所有者に属していたとし ても、同じ固有名を持つことはできません。 固有名は、最長 128 バイトです。図 361 では、calculate() 関数を作成する CREATE FUNCTION 文で、固有名 calc を定義しています。 CREATE FUNCTION calculate(a INT, b INT, c INT) RETURNING INT SPECIFIC calc1; . . . END FUNCTION; 図 361. 所有者 bsmith が SPL 関数に calc1 という固有名を指定したため、他のユーザは SPL ルーチンにも、外部ルーチンにも固有名 calc1 を使用することができません。 固有名をつけたルーチンは、以降 bsmith.calculate、またはキーワード SPECIFIC を必須とするすべての文の中ではキーワード SPECIFIC とともに calc1 として使用 できます。 パラメータ リストの追加 SPL ルーチンの作成時には、ルーチンがその起動時に 1 つ以上の引数を受け入れる よう、パラメータ リストを定義できます。パラメータ リストはオプションです。 SPL ルーチンへのパラメータには名前が必要であり、デフォルト値で定義できま す。パラメータで指定する、異なる Informix データベース サーバのデータ型のカ テゴリを次の表に示します。 Dynamic Server Extended Parallel Server 組込みデータ型 組込みデータ型 不透明 (OPAQUE) 型 ディスティンクト (DISTINCT) 型 行 (ROW) 型 コレクション (COLLECTION) 型 スマート ラージ オブジェクト (文字ラージ オブジェクト (CLOB) 型およびバイナリ ラージ オブジェクト (BLOB) 型) すべての Informix データベース サーバについて、次のデータ型をパラメータで定 義することはできません。 v シリアル (SERIAL) 型 v 8 バイト シリアル (SERIAL8) 型 v テキスト (TEXT) 型 v バイト (BYTE) 型 図 362 に、異なるパラメータ リストの例を示します。 第 11 章 SPL ルーチンの作成と使用 265 CREATE PROCEDURE raise_price(per_cent INT) CREATE FUNCTION raise_price(per_cent INT DEFAULT 5) CREATE PROCEDURE update_emp(n employee_t) CREATE FUNCTION update_nums( list1 LIST (ROW a varchar(10), b varchar(10), c int) NOT NULL ) 図 362. パラメータを定義すると、2 つのタスクを一度に達成できます。 v ルーチンが実行されるとユーザに値の入力を要求します。 v 局所変数としてルーチン本体の中で使用できるように、変数をパラメータと同じ 名前で暗黙的に定義します。 パラメータをデフォルト値で定義すると、ユーザは対応する引数の有無にかかわら ず SPL ルーチンを実行できます。ユーザが引数を使用せずに SPL ルーチンを実行 すると、データベース サーバではデフォルト値が引数としてパラメータに割り当て られます。 SPL ルーチンを起動すると、引数に NULL 値を渡すことができます。SPL ルーチ ンはデフォルトで NULL 値を処理します。ただし、引数がコレクション (COLLECTION) 型要素の場合は、引数に NULL 値を渡すことができません。 パラメータとしてシンプル ラージ オブジェクトを使用: シンプル ラージ オブジ ェクト (テキスト (TEXT) 型またはバイト (BYTE) 型を含むラージ オブジェクト) でパラメータを定義することはできませんが、図 363 に示すように、キーワード REFERENCES を使用してシンプル ラージ オブジェクトを指すパラメータを定義で きます。 CREATE PROCEDURE proc1(lo_text REFERENCES TEXT) CREATE FUNCTION proc2(lo_byte REFERENCES BYTE DEFAULT NULL) 図 363. キーワード REFERENCES は、オブジェクト自体ではなくシンプル ラージ オブジ ェクトのポインタを含む記述子を SPL ルーチンが渡すことを意味します。 未定義の引数: SPL ルーチンを起動すると、定義済み引数のすべてまたは一部を指 定できることも、まったく定義できないこともあります。引数を定義しておらず、 対応するパラメータがデフォルト値を持たない場合は、SPL ルーチン内で変数とし て使用される引数には、未定義 の状態になります。 未定義 は、値を持たない SPL 変数に使用される特殊な状態を指します。 SPL ル ーチンは、その本文中に未定義 の状態の変数を使用しない限り、正常に実行できま す。 未定義 の状態は、NULL 値とは異なります。(NULL 値は、値が不明な場合、値が 存在しない場合、または値が適切でない場合に使用されます。) 266 IBM Informix: SQL ガイド: チュートリアル RETURN 節の追加 CREATE FUNCTION 文を使用して SPL ルーチンを作成する場合は、1 つ以上の値 を戻す RETURN 節を指定する必要があります。 ヒント: CREATE PROCEDURE 文を使用して SPL ルーチンを作成する場合、任意 で RETURN 節を指定できます。これによりコードがより読みやすく、管 理しやすくなりますが、値を戻すルーチンを作成するには、CREATE FUNCTION 文を使用することをお勧めします。 RETURN 節を指定するには、キーワード RETURNING または RETURNS を、ル ーチンが戻すデータ型のリストとともに使用します。データ型には、シリアル (SERIAL) 型、 8 バイト シリアル (SERIAL8) 型、テキスト (TEXT) 型、または バイト (BYTE) 型を除く任意の SQL データ型を使用できます。 図 364 の RETURN 節は、SPL ルーチンがINT 値および REAL 値を戻すことを指 定しています。 NCTION find_group(id INT) RETURNING INT, REAL; . . . END FUNCTION; 図 364. RETURN 節を指定した後、ルーチンの本文中にも RETURN 文を指定し、呼出しル ーチンに明示的に値を戻す必要があります。 RETURN 文の記述に関する詳細は、 291 ページの『SPL 関数からの値の戻り』に記載されています。 関数でシンプル ラージ オブジェクト (テキスト (TEXT) 型 またはバイト (BYTE) 型値) を戻すように指定する場合は、図 365 に示すように、REFERENCES 節を使 用します。これが必要なのは、SPL ルーチンがオブジェクトにポインタを戻し、オ ブジェクト自体を戻さないためです。 CREATE FUNCTION find_obj(id INT) RETURNING REFERENCES BYTE; 図 365. 表示ラベルの追加 (IDS のみ) CREATE FUNCTION を使用して、戻り値の表示ラベルの名前を指定するルーチン を作成できます。表示ラベルに名前を指定しないと、そのラベルは式として表示し ます。 値を戻すルーチンには CREATE FUNCTION の使用が推奨されますが、 CREATE PROCEDURE を使用して値を戻し、戻り値の表示ラベルを指定することもできま す。 第 11 章 SPL ルーチンの作成と使用 267 1 つの戻り値に対して表示ラベルを指定する場合、すべての戻り値に対して表示ラ ベルを指定する必要があります。加えて、各戻り値にはそれぞれ固有の表示ラベル が必要です。 表示ラベルを追加するには、キーワード RETURNING を使用して RETURN 節を指 定します。図 366 の RETURN 節は、ルーチンが serial_num 表示ラベルを持つ整 数 (INT) 型値、name 表示ラベルを持つ文字 (CHAR) 型値、points 表示ラベルを持 つ整数 (INT) 型値を戻すことを指定しています。 図 366 では、CREATE FUNCTION と CREATE PROCEDURE のいずれも使用できます。 CREATE FUNCTION p(inval INT DEFAULT 0) RETURNING INT AS serial_num, CHAR (10) AS name, INT AS points; RETURN (inval + 1002), "Newton", 100; END PROCEDURE; 図 366. 図 367 に戻り値とその表示ラベルを示します。 serial_num name points 1002 Newton 100 図 367. ヒント: 戻り値の表示ラベルは、SELECT 文で直接指定できるため、 SPL ルーチン が SELECT 文で使用されている場合は、ラベルが式として表示されます。 SELECT 文で戻り値の表示ラベルを指定する方法の詳細については、 15 ペ ージの『第 2 章 SELECT 文の作成』 を参照してください。 SPL 関数がバリアントであるかどうかの指定 SPL 関数を作成すると、関数はデフォルトでバリアントになります。同じ引数で起 動したとき異なる結果を戻す関数、あるいはデータベースまたは変数の状態を変更 する関数はバリアントです。例えば、現在の日付または時刻を戻す関数は、バリア ント関数です。 SPL 関数はデフォルトでバリアントになりますが、その関数の作成時に WITH NOT VARIANT を指定した場合、その関数には SQL 文を含めることができなくな ります。非バリアント関数上に関数インデックスを作成することができます。 修飾子の追加 (IDS のみ) SPL 関数を作成する場合、WITH 節を使用して CREATEFUNCTION 文に修飾子を 追加できます。 WITH 節では、COMMUTATOR または NEGATOR 関数を指定で きます。他の修飾子は外部ルーチン用です。 重要: COMMUTATOR または NEGATOR 修飾子は、SPL 関数でのみ使用できま す。SPL プロシジャでは、修飾子を使用できません。 COMMUTATOR 修飾子: COMMUTATOR 修飾子を使用して、作成している SPL 関数の交換子関数 である SPL 関数を指定できます。交換子関数は、作成している 268 IBM Informix: SQL ガイド: チュートリアル SPL 関数と同じ引数を適用しますが、同じ値を逆の順序で戻します。交換子関数を 使うと、SQL オプティマイザが実行する場合の対費用効果が大きくなることがあり ます。 例えば、a が b よりも小さい場合に TRUE を戻す関数 lessthan(a,b) と、b が a よりも大きいか等しい場合に TRUE を戻す関数 greaterthan(b,a) は、交換子関数 です。 図 368 では、WITH 節を使用して交換子関数を定義しています。 CREATE FUNCTION lessthan( a dtype1, b dtype2 ) RETURNING BOOLEAN WITH ( COMMUTATOR = greaterthan ); . . . END FUNCTION; 図 368. オプティマイザは、lessthan(a,b) を実行するよりも費用が安い場合に、 greaterthan(b,a) を使用します。交換子関数を指定するには、交換子関数と、記述 する SPL 関数の両方を所有する必要があります。また、SPL 関数のユーザに両方 の関数の Execute アクセス権を与える必要があります。 アクセス権の付与に関する詳細は、「IBM Informix: SQL ガイド: 構文」のGRANT に関する説明を参照してください。 NEGATOR 修飾子: NEGATOR 修飾子は、ブール関数に使用できます。 2 つのブ ール関数が、同じ引数を同じ順序で取り、補数のブール (Boolean) 型値を戻す場 合、それらは 否定素子関数 になります。 例えば、a が b と等しい場合に TRUE を戻す関数 equal(a,b) と、a が b と等し い場合に FALSE を戻す関数 notequal(a,b) は、否定素子関数です。オプティマイ ザは、指定した否定素子関数の費用が元の関数より安い場合に否定素子関数の実行 を選択します。 図 369 に、CREATE FUNCTION 文の WITH 節を使用して否定素子関数を指定す る方法を示します。 CREATE FUNCTION equal( a dtype1, b dtype2 ) RETURNING BOOLEAN WITH ( NEGATOR = notequal ); . . . END FUNCTION; 図 369. ヒント: すべての SPL ルーチンは、引数リストで渡された NULL 値をデフォルト で処理できます。つまり、SPL ルーチンでは HANDLESNULLS 修飾子が YES に設定されており、それを変更できないのです。 COMMUTATOR および NEGATOR 修飾子の詳細については、「IBM Informix: SQL ガイド: 構文」のルーチン 修飾子に関する説明を参照してください。 第 11 章 SPL ルーチンの作成と使用 269 DOCUMENT 節の指定 DOCUMENT および WITH LISTING IN 節は、END PROCEDURE または END FUNCTION 文の後に続きます。 DOCUMENT 節を使用すると、SPL ルーチンにコメントを追加できるため、別のル ーチンは必要に応じてシステム カタログ表から選択できます。 図 370 の DOCUMENT 節には、SPL ルーチンの実行方法を示す文が含まれます。 CREATE FUNCTION raise_prices(per_cent INT) . . . END FUNCTION DOCUMENT "USAGE: EXECUTE FUNCTION raise_prices (xxx)", "xxx = percentage from 1 - 100"; 図 370. 一重または二重引用符でリテラル節を囲むことを忘れないでください。リテラル節 が 1 行を超える場合は、各行を引用符で囲んでください。 リスト ファイルの指定 オプション WITH LISTING IN を使用すると、ファイルに発生するコンパイル時の あらゆる警告を表示できます。 UNIX のみ 図 371 は、UNIX で /tmp/warn_file にあるコンパイル時の警告をログに記録する方 法を示します。 CREATE FUNCTION raise_prices(per_cent INT) . . . END FUNCTION WITH LISTING IN ’/tmp/warn_file’ 図 371. UNIX のみ の終り Windows のみ 図 372 は、Windows で \tmp\listfile にあるコンパイル時の警告をログに記録する方 法を示します。 CREATE FUNCTION raise_prices(per_cent INT) . . . END FUNCTION WITH LISTING IN ’C:\tmp\listfile’ 図 372. Windows のみ の終り 270 IBM Informix: SQL ガイド: チュートリアル 常に、一重または二重引用符でファイル名またはパス名を囲むことを忘れないでく ださい。 コメントの追加 空白行も含み SPL ルーチンのあらゆる行にコメントを追加できます。 コメントを追加するには、二重ハイフン (--) をコメントの前に挿入するか、または コメントを中括弧 ({ }) で囲みます。二重ハイフンは、ANSI/ISO の SQL 標準に準 拠しています。中括弧は、ANSI/ISO 標準に対する Informix 拡張です。 複数行のコメントを追加するには、次のいずれかを実行します。 v コメントの各行の前に二重ハイフンを挿入する。 v コメント全体を中括弧で囲む。 図 373 の例はすべて、有効なコメントです。 SELECT * FROM customer -- Selects all columns and rows SELECT * FROM customer -- Selects all columns and rows -- from the customer table SELECT * FROM customer { Selects all columns and rows from the customer table } 図 373. 警告: 中括弧 ({ }) ではコメントを区切ることができるほか、コレクション内の要 素のリストも区切ることができます。パーサがコメントまたはコレクション 内の要素リストの終わりを正確に認識できるよう、SPL ルーチン内の、コレ クション (COLLECTION) 型を処理するコメントに二重ハイフン (--) を使用 します。 完全なルーチンの例 以下の CREATE FUNCTION 文は、顧客の住所を読み取るルーチンを作成します。 CREATE FUNCTION read_address (lastname CHAR(15)) -- one argument RETURNING CHAR(15), CHAR(15), CHAR(20), CHAR(15),CHAR(2) CHAR(5); -- 6 items DEFINE p_lname,p_fname, p_city CHAR(15); --define each routine variable DEFINE p_add CHAR(20); DEFINE p_state CHAR(2); DEFINE p_zip CHAR(5); SELECT fname, address1, city, state, zipcode INTO p_fname, p_add, p_city, p_state, p_zip FROM customer WHERE lname = lastname; RETURN p_fname, lastname, p_add, p_city, p_state, p_zip; --6 items END FUNCTION; DOCUMENT ’This routine takes the last name of a customer as’, 第 11 章 SPL ルーチンの作成と使用 271 --brief description ’its only argument. It returns the full name and address’, ’of the customer.’ WITH LISTING IN ’pathname’ -- modify this pathname according -- to the conventions that your operating system requires -- compile-time warnings go here ; -- end of the routine read_address プログラム内の SPL ルーチンの作成 SQL API を使用して SPL ルーチンを作成する場合は、 CREATE PROCEDURE ま たは CREATE FUNCTION 文のテキストをファイルに書き込みます。 CREATE PROCEDURE FROM または CREATE FUNCTION FROM 文を使用してファイルを 参照し、ルーチンをコンパイルします。例えば、顧客名を読み取るルーチンを作成 するには、前述の例のような文を使用してファイルに格納します。ファイルの名前 が read_add_source である場合は、次の文が read_address ルーチンをコンパイ ルします。 CREATE PROCEDURE FROM ’read_add_source’; 次の例に、上述の SQL 文が ESQL/C プログラムではどのように記述されるか示し ます。 /* This program creates whatever routine is in * * the file ’read_add_source’. */ #include <stdio.h> EXEC SQL include sqlca; EXEC SQL include sqlda; EXEC SQL include datetime; /* Program to create a routine from the pwd */ main() { EXEC SQL database play; EXEC SQL create procedure from ’read_add_source’; } SPL ルーチンの削除 SPL ルーチンを作成した後で、ルーチンの本体を変更することはできません。それ には、ルーチンを削除して再作成する必要があります。ただし、ルーチンを削除す る前に、必ずデータベース以外の場所にそのテキストのコピーをとる必要がありま す。 通常は DROP PROCEDURE を SPL プロシジャ名とともに使用し、 DROP FUNCTION を SPL 関数名とともに使用してください。 図 374 に例を示します。 DROP PROCEDURE raise_prices; DROP FUNCTION read_address; 図 374. ヒント: DROP PROCEDURE を関数名とともに使用し、SPL 関数を削除することも できます。ただし、DROP PROCEDURE はプロシジャ名のみと使用し、 DROP FUNCTION は関数名のみと使用することをお勧めします。 272 IBM Informix: SQL ガイド: チュートリアル 一方、データベースに同じ名前の他のルーチン (オーバーロード ルーチン) がある 場合は、ルーチン名だけで SPL ルーチンを削除することはできません。オーバーロ ードされたルーチンを削除するには、シグネチャまたは固有名のいずれかを指定す る必要があります。 図 375 に、オーバーロードされたルーチンを削除する 2 つの 方法を示します。 DROP FUNCTION calculate( a INT, b INT, c INT); -- this is a signature DROP SPECIFIC FUNCTION calc1; -- this is a specific name 図 375. ルーチンの種類 (関数またはプロシジャ) がわからない場合は、 DROP ROUTINE 文を使用して削除することができます。 DROP ROUTINE は、関数とプロシジャ両 方と使用することができます。また、DROP ROUTINE は、図 376 に示すように、 キーワード SPECIFIC を持ちます。 DROP ROUTINE calculate; DROP SPECIFIC ROUTINE calc1; 図 376. リモート データベース サーバに格納される SPL ルーチンを削除する前に、次の制 限に注意してください。引数なしのルーチン名だけで、ルーチンを識別するのに十 分である場合に限り、フォーム database@dbservername:owner.routinename の完全 修飾ルーチン名を持つ SPL ルーチンを削除できます。あるデータベースのユーザ定 義 (user-defined) 型は、別のデータベース上では存在できないため、ユーザ定義 (user-defined) 型の引数とともに修飾名は使用できません。 変数の定義と使用 SPL ルーチンで使用するあらゆる変数は、ルーチンのパラメータ リストの中で暗黙 的に定義される変数を除き、ルーチン本体の中で定義する必要があります。 変数の値はメモリ内に保持されます。変数はデータベース オブジェクトではありま せん。そのため、トランザクションをロール バックしても SPL 変数の値は復元さ れません。 SPL ルーチンで変数を定義するには、DEFINE 文を使用します。 DEFINE は実行 可能文ではありません。 DEFINE は、CREATE PROCEDURE 文の後、その他の文 の前に置きます。 図 377 の例は、すべて有効な変数定義です。 DEFINE a INT; DEFINE person person_t; DEFINE GLOBAL gl_out INT DEFAULT 13; 図 377. 第 11 章 SPL ルーチンの作成と使用 273 DEFINE の詳細については、「IBM Informix: SQL ガイド: 構文」の説明を参照して ください。 SPL 変数は名前とデータ型を持ちます。変数名は、有効な識別子である必要があり ます。これについては、「IBM Informix: SQL ガイド: 構文」の識別子に関する説明 を参照してください。 局所変数の宣言 変数には、ローカル またはグローバル な範囲を定義できます。ここでは局所変数 を説明します。 SPL ルーチンで使用する局所変数 には、以下の特徴があります。 v SPL ルーチンのみに有効。 v ルーチンが実行されるたびに、初期値またはユーザがルーチンに渡す値にリセッ トされる。 v デフォルト値を持つことはできない。 次のいずれのデータ型でも局所変数を定義できます。 v 組込みデータ型 (シリアル (SERIAL) 型、8 バイト シリアル (SERIAL8) 型、テ キスト (TEXT) 型、または バイト (BYTE) 型を除く) v SPL ルーチンを実行する前にデータベースの中で定義されたあらゆる拡張 (extended) 型 (行 (ROW) 型、不透明 (OPAQUE) 型、ディスティンクト (DISTINCT) 型、またはコレクション (COLLECTION) 型) 局所変数の有効範囲は、局所変数が宣言された文ブロックです。同じ変数名は、文 ブロックの外で異なる定義の場合には使用できます。 広域変数を定義する詳細については、281 ページの『広域変数の宣言』を参照して ください。 局所変数の範囲 局所変数は、文ブロックの範囲内で変数を再定義しない限り、定義されている文ブ ロックの範囲内、およびあらゆる入れ子文ブロックの範囲内で有効です。 図 378 の SPL プロシジャの始めに、整数 (INTEGER) 型変数 x、y、 および z が 定義され初期化されています。 274 IBM Informix: SQL ガイド: チュートリアル CREATE PROCEDURE scope() DEFINE x,y,z INT; LET x = 5; LET y = 10; LET z = x + y; --z is 15 BEGIN DEFINE x, q INT; DEFINE z CHAR(5); LET x = 100; LET q = x + y; -- q = 110 LET z = ’silly’; -- z receives a character value END LET y = x; -- y is now 5 LET x = z; -- z is now 15, not ’silly’ END PROCEDURE; 図 378. BEGIN 文および END 文は、整数 (INTEGER) 型変数 x、q、および文字 (CHAR) 型変数 z が定義されている入れ子文ブロックを示します。入れ子ブロックの範囲内 で、再定義変数 x は元の変数 x をマスクします。入れ子ブロックの終わりを示す END 文の後で、元の値の x が再度アクセス可能になります。 組込み型変数の宣言 組込み変数 は、組込みデータ型から抽出したデータを保持します。 SPL 変数は、 シリアル (SERIAL) 型および 8 バイト シリアル (SERIAL8) 型を除くすべての組 込みデータ型を定義できます。図 379 に例を示します。 DEFINE DEFINE DEFINE DEFINE x INT; y INT8; name CHAR(15); today DATETIME YEAR TO DAY; 図 379. スマート ラージ オブジェクト用の変数の宣言 (IDS のみ) バイナリ ラージ オブジェクト (BLOB) 型または 文字ラージ オブジェクト (CLOB) 型オブジェクト (またはスマート ラージ オブジェクトを含むデータ型) 用 の変数は、オブジェクトそのものではなく、そのオブジェクトへのポインタを含み ます。 図 380 に、バイナリ ラージ オブジェクト (BLOB) 型および文字ラージ オ ブジェクト (CLOB) 型オブジェクト用の変数を定義する方法を示します。 DEFINE a_blob BLOB; DEFINE b_clob CLOB; 図 380. シンプル ラージ オブジェクト用の変数の宣言 シンプル ラージ オブジェクト (テキスト (TEXT) 型またはバイト (BYTE) 型オブ ジェクト) 用の変数は、オブジェクト自体ではなく、オブジェクトを指すポインタ 第 11 章 SPL ルーチンの作成と使用 275 を含みます。テキスト (TEXT) 型またはバイト (BYTE) 型で変数を定義する場合 は、キーワード REFERENCES をデータ型の前に使用する必要があります。図 381 に例を示します。 DEFINE t REFERENCES TEXT; DEFINE b REFERENCES BYTE; 図 381. コレクション (COLLECTION) 型変数の宣言 (IDS のみ) データベースから取り出したコレクションを保持するためには、変数がセット (SET) 型、マルチセット (MULTISET) 型、または リスト (LIST) 型である必要が あります。 重要: コレクション (COLLECTION) 型変数は、局所変数として定義する必要があ ります。コレクション (COLLECTION) 型の変数を広域変数として定義する ことはできません。 セット (SET) 型、マルチセット (MULTISET) 型、またはリスト (LIST) 型の変数 は、コレクション (COLLECTION) 型変数であり、DEFINE 文で指定された型のコレ クションを保持します。図 382 に、型付きコレクション (COLLECTION) 型変数を 定義する方法を示します。 DEFINE a SET ( INT NOT NULL ); DEFINE b MULTISET ( ROW ( ) b1 INT, b2 CHAR(50), NOT NULL ); DEFINE c LIST ( SET (DECIMAL NOT NULL) NOT NULL); 図 382. コレクション (COLLECTION) 型変数の要素は、必ず NOT NULL として定義する 必要があります。この例では、変数 a は非 NULL 整数のセット (SET) 型を保持 し、変数 b は非 NULL 行 (ROW) 型のマルチセット (MULTISET) 型を保持し、 変数 c は非 NULL 10 進数値の非 NULL の集合のリスト (LIST) 型を保持すると 定義します。 変数定義では、データベースに格納されるデータ型に一致させるために、あらゆる 組合せまたは深さで複合 (Complex) 型を入れ子にできます。 あるデータ型のコレクション (COLLECTION) 型変数を別のデータ型のコレクショ ン (COLLECTION) 型変数に代入することはできません。例えば、コレクション (COLLECTION) 型変数をセット (SET) 型に定義する場合、それに対してマルチセ ット (MULTISET) 型またはリスト (LIST) 型の別のコレクション (COLLECTION) 型変数を割り当てることはできません。 276 IBM Informix: SQL ガイド: チュートリアル 行 (ROW) 型変数の宣言 (IDS のみ) 行 (ROW) 型変数は、名前付きまたは名前なしの行 (ROW) 型のデータを保持しま す。名前付き行 (named row) 型変数 または名前なし行 (unnamed row) 型変数 を定 義できます。図 383 に示す名前付き行 (named row) 型を定義すると仮定します。 CREATE ROW TYPE zip_t ( z_code CHAR(5), z_suffix CHAR(4) ); CREATE ROW TYPE address_t ( street VARCHAR(20), city VARCHAR(20), state CHAR(2), zip zip_t ); CREATE ROW TYPE employee_t ( name VARCHAR(30), address address_t salary INTEGER ); CREATE TABLE employee OF TYPE employee_t; 図 383. 名前付き行 (named row) 型の名前とともに変数を定義した場合、変数は行 (ROW) 型のデータのみを保持できます。 図 384 では、変数 person は employee_t 型の データのみを保持できます。 DEFINE person employee_t; 図 384. 名前なし行 (unnamed row) 型に格納されるデータを保持する変数を定義するには、 図 385 に示すように、行 (ROW) 型フィールドの前にキーワード ROW を使用しま す。 DEFINE manager ROW (name department salary VARCHAR(30), VARCHAR(30), INTEGER ); 図 385. 名前なし行 (unnamed row) 型は、構造的同等性について型のチェックをするのみな ので、名前なし行 (unnamed row) 型で定義した変数は、同じフィールド数で同じ型 定義のあらゆる名前なし行 (unnamed row) 型のデータを保持できます。そのため、 変数 manager は図 386 のあらゆる行 (ROW) 型のデータを保持できます。 第 11 章 SPL ルーチンの作成と使用 277 ROW ( name department salary VARCHAR(30), VARCHAR(30), INTEGER ); ROW ( french spanish number VARCHAR(30), VARCHAR(30), INTEGER ); ROW ( title musician price VARCHAR(30), VARCHAR(30), INTEGER ); 図 386. 重要: 行 (ROW) 型変数を使用する前に、その変数を LET 文または SELECTINTO 文で初期化する必要があります。 不透明 (OPAQUE) 型およびディスティンクト (DISTINCT) 型変数の 宣言 (IDS のみ) 不透明 (OPAQUE) 型変数 は、不透明 (OPAQUE) 型から抽出されたデータを保持 します。ディスティンクト (DISTINCT) 型変数 は、ディスティンクト (DISTINCT) 型から抽出したデータを保持します。不透明 (OPAQUE) 型またはディスティンクト (DISTINCT) 型で定義した変数は、その型のデータだけを保持できます。 point という名前の不透明 (OPAQUE) 型および centerpoint という名前のディス ティンクト (DISTINCT) 型を定義した場合は、図 387 に示すように、2 つの型のデ ータをそれぞれ保持する SPL 変数を定義できます。 DEFINE a point; DEFINE b centerpoint; 図 387. 変数 a は point 型のデータのみを保持でき、変数 b は centerpoint 型のデータ のみを保持できます。 LIKE 節による列データ用変数の宣言 LIKE 節を使用すると、データベース サーバにより表またはビューの列と同じデー タ型を持つように変数が定義されます。 列に、行 (ROW) 型または入れ子複合 (Complex) 型のコレクション (COLLECTION) 型データが含まれる場合は、その列の変数は複合 (Complex) 型または入れ子複合 (Complex) 型に定義されます。 図 388 において、変数 loc1 は、表 image の列 locations のデータ型を定義しま す。 DEFINE loc1 LIKE image.locations; 図 388. 278 IBM Informix: SQL ガイド: チュートリアル PROCEDURE 型変数の宣言 SPL ルーチンでは、PROCEDURE 型の変数を定義し、それに既存の SPL ルーチン 名または外部ルーチン名を割り当てることができます。 PROCEDURE 型の変数を 定義するということは、その変数はユーザ定義ルーチンへの呼出しであり、同じ名 前の組込みルーチンではないことを示します。 例えば、図 389 の文では、length を組込み LENGTH 関数としてではなく、SPLプ ロシジャまたは SPL 関数として定義します。 DEFINE length PROCEDURE; LET x = length( a,b,c ); 図 389. この定義によって組込み関数 LENGTH は文ブロックの有効範囲内で使用不可にな ります。こうした定義は、SPL ルーチンまたは外部ルーチンを LENGTH という名 前で既に作成していた場合に使用します。 Dynamic Server Dynamic Server によりルーチン オーバーロードがサポートされているため、複数の SPL ルーチンまたは外部ルーチンを同じ名前で定義できます。 SPL ルーチンから 任意のルーチンを呼び出す場合は、Dynamic Server により、指定された引数とルー チン決定規則に基づいて使用するルーチンが決定されます。ルーチン オーバロード およびルーチン決定の詳細については、「IBM Informix: ユーザ定義ルーチンおよび データ タイプ 開発者ガイド」を参照してください。 Dynamic Server の終り ヒント: SPL ルーチンを、集計関数 (SUM、MAX、MIN、AVG、COUNT) と同じ 名前、または extend という名前で作成する場合は、ルーチン名を所有者 名で修飾する必要があります。 変数とサブスクリプトの使用 サブスクリプトは、文字 (CHAR) 型、可変長文字 (VARCHAR) 型、各国語文字 (NCHAR) 型、ラージ可変長文字 (LVARCHAR) 型、バイト (BYTE) 型、またはテ キスト (TEXT) 型の変数で使用できます。サブスクリプトは、変数の範囲内で使用 する文字の開始位置と終了位置を示します。 サブスクリプトは、常に定数である必要があります。変数は、サブスクリプトとし て使用することはできません。図 390 に、サブスクリプトを CHAR(15) 型変数と使 用する方法を示します。 DEFINE name CHAR(15); LET name[4,7] = ’Ream’; SELECT fname[1,3] INTO name[1,3] FROM customer WHERE lname = ’Ream’; 図 390. 第 11 章 SPL ルーチンの作成と使用 279 この例では、顧客の姓を、名前の位置 4 と 7 の間に置きます。顧客のファースト ネームの最初の 3 文字は、名前の位置 1 から 3 に抽出されます。 2 つのサブス クリプトで区切られた変数の一部はサブ文字列 といいます。 変数およびキーワードのあいまいさ SQL キーワードと同じ名前の変数を宣言する場合、あいまいさが発生する可能性が あります。 ID に関する以下のルールにより、SPL 変数、SPL ルーチン名、および 組込み関数名をめぐるあいまいさを回避できます。 v 定義済みの変数が、最も優先される。 v DEFINE 文でキーワード PROCEDURE とともに定義されたルーチンは、SQL 関 数よりも優先される。 v SQL 関数は、存在はするが DEFINE 文でキーワード PROCEDURE とともに識 別されていない SPL ルーチンよりも優先される。 一般的に、ANSI 標準の予約語を変数の名前として使用することは避けるようにし ます。例えば、変数を count または max という集計関数の名前で定義することは できません。変数名として使用すべきでない予約キーワードのリストは、 「IBM Informix: SQL ガイド: 構文」の修飾子に関する説明を参照してください。 変数と列の名前: 列の名前と同じ識別子を SPL 変数について使用すると、データ ベース サーバは識別子の各実現値は変数であると判断します。識別子を列の名前と して使用するには、ピリオド表記を使用して列の名前を表の名前で限定します。 図 391 の SELECT 文では、customer.lname が列名、lname が変数名です。 CREATE PROCEDURE table_test() DEFINE lname CHAR(15); LET lname = ’Miller’; SELECT customer.lname INTO lname FROM customer WHERE customer_num = 502; . . . END PROCEDURE; 図 391. 変数および SQL 関数: SPL 変数に SQL 関数と同じ識別子を使用すると、データ ベース サーバは実現値の識別子が変数であると判断して、SQL 関数の使用を許可 しません。変数が定義されているコードのブロックでは、SQL 関数を使用できませ ん。 図 392 の例では、user という変数を定義する SPL プロシジャ内のブロック を示します。この定義により、BEGIN END ブロックでは USER 関数が使用できな くなります。 280 IBM Informix: SQL ガイド: チュートリアル CREATE PROCEDURE user_test() DEFINE name CHAR(10); DEFINE name2 CHAR(10); LET name = user; -- the SQL function BEGIN DEFINE user CHAR(15); -- disables user function LET user = ’Miller’; LET name = user; -- assigns ’Miller’ to variable name END . . . LET name2 = user; -- SQL function again 図 392. SPL ルーチン名および SQL 関数: SPL ルーチン名と SQL 関数名のあいまいさ に関する詳細は、「IBM Informix: SQL ガイド: 構文」を参照してください。 広域変数の宣言 広域変数 の値はメモリに格納され、同じデータベース上の同じユーザ セッション により実行される他の SPL ルーチンにとって利用可能になります。広域変数には次 の特性があります。 v デフォルト値を必要とします。 v あらゆる SPL ルーチンで使用できますが、その変数を使用する各ルーチンの中 には必ず定義する必要があります。 v セッションが終わるまで、値を SPL ルーチンから別の SPL ルーチンへ運びま す。 重要: コレクション (COLLECTION) 型の変数を広域変数として定義することはで きません。 図 393 に、1 つの広域変数を共用する 2 つの SPL 関数を示します。 CREATE FUNCTION func1() RETURNING INT; DEFINE GLOBAL gvar INT DEFAULT 2; LET gvar = gvar + 1; RETURN gvar; END FUNCTION; CREATE FUNCTION func2() RETURNING INT; DEFINE GLOBAL gvar INT DEFAULT 5; LET gvar = gvar + 1; RETURN gvar; END FUNCTION; 図 393. 広域変数にデフォルト値を定義する必要がありますが、変数は最初に使用するとき のみデフォルトに設定されます。 図 394 に示す順序で 2 つの関数を実行すると、 gvar の値は 4 になります。 第 11 章 SPL ルーチンの作成と使用 281 EXECUTE FUNCTION func1(); EXECUTE FUNCTION func2(); 図 394. ただし、図 395 に示すように関数を逆の順序で実行すると、gvar の値は 7 になり ます。 EXECUTE FUNCTION func2(); EXECUTE FUNCTION func1(); 図 395. 詳しくは、315 ページの『ルーチンの実行』を参照してください。 変数への値の代入 SPL ルーチン内では、LET 文を使用して、定義済みの変数に値を割り当てます。 ルーチンに渡される引数または LET 文のいずれかにより、変数に値を代入しない 場合は、変数は未定義の値を持ちます。 未定義の値は、NULL 値とは異なります。SPL ルーチン内で未定義の値とともに変 数を使用しようとすると、エラーになります。 次のいずれかの方法により、ルーチンの変数に値を代入できます。 v LET 文を使用する。 v SELECTINTO 文を使用する。 v RETURNING 節をもつプロシジャで CALL 文を使用する。 v EXECUTE PROCEDUREINTO または EXECUTE FUNCTION INTO 文を使用す る。 LET 文 LET 文とともに、等号 (=)、および有効な式または関数名を持つ、1 つ以上の変数 名を使用できます。 図 396 の例はすべて、有効な LET 文です。 LET LET LET LET a = 5; b = 6; LET c = 10; a,b = 10,c+d; a,b = (SELECT cola,colb FROM tab1 WHERE cola=10); LET d = func1(x,y); 図 396. Dynamic Server Dynamic Server を使用すると、不透明 (OPAQUE) 型変数、行 (ROW) 型変数、ま たは行 (ROW) 型のフィールドに値を代入できます。また、外部関数または別の 282 IBM Informix: SQL ガイド: チュートリアル SPL 関数の値を、SPL 変数に戻すこともできます。 Dynamic Server の終り 名前付き行 (named row) 型の zip_t および address_t を 277 ページの図 383 に 示すように定義すると仮定します。行 (ROW) 型変数を定義するときは使用する前 に必ず変数を初期化する必要があります。 図 397 に、行 (ROW) 型変数を定義およ び初期化する方法を示します。変数を初期化するには、行 (ROW) 型の任意の値を 使用できます。 DEFINE a address_t; LET a = ROW (’A Street’, ’Nowhere’, ’AA’, ROW(NULL, NULL))::address_t 図 397. 行 (ROW) 型変数を定義および初期化した後、図 398 に示す LET 文を記述するこ とができます。 LET a.zip.z_code = 32601; LET a.zip.z_suffix = 4555; -- Assign values to the fields of address_t 図 398. ヒント: variable.field または variable.field.field のようにピリオド表記を使用 し、行 (ROW) 型のフィールドにアクセスします。294 ページの『行 (ROW) 型データの処理 (IDS のみ)』 に例を示します。 2 次元のポイントを定義する 2 つの値を含む不透明 (OPAQUE) 型のポイントを定 義し、値のテキスト表現が ’(x,y)’ であると仮定します。また、関数 circum() があ り、特定のポイント ’(x,y)’ および半径 r の円の円周を計算するものとします。 円の中心である点を定義する不透明 (OPAQUE) 型の center、およびその円の面積 を中心点と半径を基に計算する関数 circum() を定義する場合、それぞれに対して 変数定義を記述できます。 図 399 に示す c は不透明 (OPAQUE) 型の変数であ り、 d は外部関数 circum() が戻す値を保持します。 DEFINE c point; DEFINE r REAL; DEFINE d REAL; LET c = ’(29.9,1.0)’ ; -- Assign a value to an opaque type variable LET d = circum( c, r ); -- Assign a value returned from circum() 図 399. LET 文の構文の詳細については、「IBM Informix: SQL ガイド: 構文」に記載され ています。 第 11 章 SPL ルーチンの作成と使用 283 変数に値を代入する他の方法 図 400 に示すように、SELECT 文を使用してデータベースから値を取り出して、変 数に直接代入することができます。 SELECT fname, lname INTO a, b FROM customer WHERE customer_num = 101 図 400. CALL または EXECUTE PROCEDURE 文を使用して、SPL 関数または外部関数が 戻した値を、1 つ以上の SPL 変数に割り当てることができます。図 401 のいずれ かの文を使用して、フルネームおよびアドレスを SPL 関数 read_address から特 定の SPL 変数に戻すことができます。 EXECUTE FUNCTION read_address(’Smith’) INTO p_fname, p_lname, p_add, p_city, p_state, p_zip; CALL read_address(’Smith’) RETURNING p_fname, p_lname, p_add, p_city, p_state, p_zip; 図 401. SPL ルーチンの式 SPL ルーチンでは、集計式を除くすべての SQL 式を使用できます。 SQL 式の構 文および説明は、「IBM Informix: SQL ガイド: 構文」に記載されています。 次の例には、SQL 式が含まれます。 var1 var1 + var2 + 5 read_address(’Miller’) read_address(lastname = ’Miller’) get_duedate(acct_num) + 10 UNITS DAY fname[1,5] || ’’|| lname ’(415)’ || get_phonenum(cust_name) 文ブロックの記述 すべての SPL ルーチンは、1 つ以上の文ブロックを持ちます。これは、CREATE 文から END 文までの SQL 文と SPL 文のグループです。文ブロック内では、SPL 文および許可された SQL 文はすべて使用することができます。 SPL 文ブロックで 使用できない SQL 文については、「IBM Informix: SQL ガイド: 構文」の文ブロッ クに関する説明を参照してください。 284 IBM Informix: SQL ガイド: チュートリアル 暗黙的および明示的文ブロック SPL ルーチンでは、暗黙的文ブロック は CREATE 文の終わりから END 文の始め までを指します。一方、明示的文ブロック は、BEGIN 文で始まり、 END 文で終 わります。図 402 に例を示します。 BEGIN DEFINE distance INT; LET distance = 2; END 図 402. 明示的文ブロックを使用すると、文ブロックの中でのみ有効な変数または処理を定 義できます。例えば、明示的文ブロックの有効範囲内に対して、変数の定義、再定 義、あるいは例外処理を個々に実行できます。 図 403 の SPL 関数は、暗黙的文ブロックで定義済みの変数を再定義する明示的文 ブロックを持ちます。 CREATE FUNCTION block_demo() RETURNING INT; DEFINE distance INT; LET distance = 37; BEGIN DEFINE distance INT; LET distance = 2; END RETURN distance; END FUNCTION; 図 403. この例では、暗黙的文ブロックで変数 distance を定義し、値 37 を渡します。明 示的文ブロックは別の変数 distance を定義し、値 2 を渡します。ただし、 RETURN 文は、最初の distance 変数が保持する値、つまり 37 を戻します。 カーソルの使用 FOREACH ループは特別な識別子 cursor を定義します。この識別子はコレクション (COLLECTION) 型データの中の行のグループまたは要素のグループの中の 1 項目 を指します。 FOREACH ループは、カーソルを宣言しオープンして、データベースから行を取り 出し、グループ内の各項目について動作し、次にカーソルをクローズします。 SELECT、EXECUTE PROCEDURE、または EXECUTE FUNCTION 文が複数の行を 戻す可能性がある場合は、カーソルを宣言する必要があります。カーソルを宣言し た後、SELECT、 EXECUTE PROCEDURE、または EXECUTE FUNCTION 文をそ のカーソル内に置きます。 戻されるデータにアクセスするにはカーソルを使用する必要があるため、行のグル ープを戻す SPL ルーチンをカーソル ルーチン と呼びます。値を戻さないか、1 つ またはその他のカーソルを必要としない値を戻す SPL ルーチンを、非カーソル ル 第 11 章 SPL ルーチンの作成と使用 285 ーチン と呼びます。FOREACH ループは、カーソルを宣言してオープンし、データ ベースから行またはコレクション (COLLECTION) 型データを取り出し、グループ 内の各項目を操作し、カーソルをクローズします。 SELECT、EXECUTE PROCEDURE、または EXECUTE FUNCTION 文が、複数の行、またはコレクショ ンを戻す可能性がある場合は、カーソルを宣言する必要があります。カーソルを宣 言した後、SELECT、 EXECUTE PROCEDURE、または EXECUTE FUNCTION 文 をそのカーソル内に置きます。 FOREACH ループでは、EXECUTEFUNCTION または SELECTINTO 文を使用し て、反復関数である外部関数を実行できます。 FOREACH ループを使用したカーソルの定義 FOREACH ループはキーワード FOREACH で始まり、END FOREACH で終わりま す。FOREACH と END FOREACH の間であれば、カーソルを宣言するか、 EXECUTE PROCEDURE または EXECUTE FUNCTION を使用できます。図 404 の 2 つの例は、FOREACH ループの構造を示します。 FOREACH cursor FOR SELECT column FROM table INTO variable; . . . END FOREACH; FOREACH EXECUTE FUNCTION name() INTO variable; END FOREACH; 図 404. 図 405 では、 FOREACH ループを使用し、表 employee を操作するルーチンを作 成します。 CREATE_PROCEDURE increase_by_pct( pct INTEGER ) DEFINE s INTEGER; FOREACH sal_cursor FOR SELECT salary INTO s FROM employee WHERE salary > 35000; LET s = s + s * ( pct/100 ); UPDATE employee SET salary = s WHERE CURRENT OF sal_cursor; END FOREACH; END PROCEDURE; 図 405. 図 405 のルーチンは、 FOREACH ループ内で以下のタスクを実行します。 v カーソルの宣言。 v employee から salary の値を 1 つずつ選択する。 v 給与を割合により増加する。 v employee を新しい給与で更新する。 v 次の給与値を取り出す。 286 IBM Informix: SQL ガイド: チュートリアル SELECT 文は、表の中で 35000 より大きいすべての給与を戻すため、カーソルの範 囲内に置きます。 UPDATE 文内の WHERE CURRENT OF 節は、カーソルが現在配置されている行 のみを更新し、現行行で UPDATE カーソル を設定します。 UPDATE カーソルは 行に関して更新ロックを設定するため、他のユーザは更新が発生するまで行を更新 することはできません。 FOREACH ループ内の UPDATE または DELETE 文が WHERE CURRENT OF 節 を使用する場合、SPL ルーチンは自動的に UPDATE カーソルを設定します。 WHERE CURRENT OF を使用する場合は、 FOREACH 文内で明示的にカーソルを 参照する必要があります。 UPDATE カーソルを使用している場合は、BEGIN WORK 文を FOREACH 文の前に、COMMIT WORK 文を END FOREACH の後ろ に追加できます。図 406 に例を示します。 BEGIN WORK; FOREACH sal_cursor FOR SELECT salary INTO s FROM employee WHERE salary > 35000; LET s = s + s * ( pct/100 ); UPDATE employee SET salary = s WHERE CURRENT OF sal_cursor END FOREACH COMMIT WORK; 図 406. 図 406 では、 FOREACH ループが反復されるたびに、新しいロックが必要です (行 レベル ロックを使用する場合)。 FOREACH ループの最後の反復の後、 COMMIT WORK 文がすべてのロックを解放します。また、更新されたすべての行を単一トラ ンザクションとしてコミットします。 ループの各反復後に更新済みの行をコミットするには、次の SPL ルーチンに示すよ うに、カーソル WITH HOLD をオープンし、BEGIN WORK および COMMIT WORK 文を FOREACH ループ内 にインクルードする必要があります。 CREATE PROCEDURE serial_update(); DEFINE p_col2 INT; DEFINE i INT; LET i = 1; FOREACH cur_su WITH HOLD FOR SELECT col2 INTO p_col2 FROM customer WHERE 1=1; BEGIN WORK; UPDATE customer SET col2 = p_col2 WHERE CURRENT OF cur_su COMMIT WORK; LET i = i+1 END FOREACH END PROCEDURE; 図 407. SPL ルーチン serial_update( ) は、各行を個別のトランザクションとしてコミッ トします。 第 11 章 SPL ルーチンの作成と使用 287 IF - ELIF - ELSE 構造の使用 図 408 の SPL ルーチンでは、IF - ELIF - ELSE 構造を使用し、そのルーチンが受 け入れる 2 つの引数を比較します。 CREATE FUNCTION str_compare( str1 CHAR(20), str2 CHAR(20)) RETURNING INTEGER; DEFINE result INTEGER; IF str1 > str2 THEN result = 1; ELIF str2 > str1 THEN result = -1; ELSE result = 0; END IF RETURN result; END FUNCTION; 図 408. 図 409 に示す列について manager という名前の表を定義すると仮定します。 CREATE TABLE manager ( mgr_name VARCHAR(30), department VARCHAR(12), dept_no SMALLINT, direct_reports SET( VARCHAR(30) NOT NULL ), projects LIST( ROW ( pro_name VARCHAR(15), pro_members SET( VARCHAR(20) NOT NULL ) ) NOT NULL), salary INTEGER, ); 図 409. 図 410 の SPL ルーチンでは、IF - ELIF - ELSE 構造を使用して、列 direct_reports の セット (SET) 型の数をチェックし、その結果に基づいてさまざ まな外部ルーチンを呼び出します。 288 IBM Informix: SQL ガイド: チュートリアル CREATE FUNCTION check_set( d SMALLINT ) RETURNING VARCHAR(30), VARCHAR(12), INTEGER; DEFINE name VARCHAR(30); DEFINE dept VARCHAR(12); DEFINE num INTEGER; SELECT mgr_name, department, CARDINALITY(direct_reports) FROM manager INTO name, dept, num WHERE dept_no = d; IF num > 20 THEN EXECUTE FUNCTION add_mgr(dept); ELIF num = 0 THEN EXECUTE FUNCTION del_mgr(dept); ELSE RETURN name, dept, num; END IF; END FUNCTION; 図 410. cardinality( ) 関数は、コレクションに含まれる要素数をカウントします。詳しく は、96 ページの『計数関数 (IDS のみ)』を参照してください。 SPL ルーチン内の IF - ELIF - ELSE 構造は、以下の 4 つのパーツで構成されま す。 v IF THEN 条件 IF 文に続く条件がTRUE の場合、このルーチンは IF ブロック内の文を実行しま す。条件が FALSE である場合は、ルーチンは ELIF 条件を評価します。 IF 文内の式は、有効な条件であれはすべて使用できます。これについては、 「IBM Informix: SQL ガイド: 構文」の条件に関する説明を参照してください。IF 文の構文および詳細については、「IBM Informix: SQL ガイド: 構文」を参照して ください。 v 1 つ以上の ELIF 条件 (オプション) ルーチンは、IF 条件が FALSE の場合のみ、 ELIF 条件を評価します。 ELIF 条 件が TRUE の場合、そのルーチンは ELIF ブロック内の文を実行します。ELIF 条件が FALSE の場合、ルーチンは次の ELIF ブロックを評価するか、 ELSE 文 を実行します。 v ELSE 条件 (オプション) ルーチンは、IF 条件およびすべての ELIF 条件が FALSE の場合に ELSE ブロ ックの文を実行します。 v END IF 文 END IF 文は、文ブロックを終了します。 WHILE ループと FOR ループの追加 WHILE 文と FOR 文は、両方とも SPL ルーチンで実行ループを作成します。 WHILE ループは、WHILE 条件 で始まり、その条件が TRUE である間文ブロック を実行し、END WHILE で終了します。 第 11 章 SPL ルーチンの作成と使用 289 図 411 に、有効な WHILE 条件を示します。ルーチンは WHILE 文で指定した条件 が TRUE である限り WHILE ループを実行します。 CREATE PROCEDURE test_rows( num INT ) DEFINE i INTEGER; LET i = 1; WHILE i < num INSERT INTO table1 (numbers) VALUES (i); LET i = i + 1; END WHILE; END PROCEDURE; 図 411. 図 411 の SPL ルーチンは引数として整数を受け入れ、WHILE ループを実行するた びに整数値を table1 の列 numbers に挿入します。挿入された値は 1 で始まり、 num - 1 まで増加します。 図 412 に示すような無限ループを作らないよう注意してください。 CREATE PROCEDURE endless_loop() DEFINE i INTEGER; LET i = 1; WHILE ( 1 = 1 ) -- don’t do this! LET i = i + 1; INSERT INTO table1 VALUES (i); END WHILE; END PROCEDURE; 図 412. FOR ループは FOR 文から END FOR 文までを指し、FOR 文で指定する回数だけ 反復します。図 413 に、FOR ループで反復を定義する方法をいくつか示します。 FOR i = 1 TO 10 . . . END FOR; FOR i = 1 TO 10 STEP 2 . . . END FOR; FOR i IN (2,4,8,14,22,32) . . . END FOR; FOR i IN (1 TO 20 STEP 5, 20 to 1 STEP -5, 1,2,3,4,5) . . . END FOR: 図 413. 290 IBM Informix: SQL ガイド: チュートリアル 最初の例では、SPL プロシジャは、i が 1 から 10 のいずれかである限り FOR ル ープを実行します。 2 番目の例では、i は 1、3、5、7、のようにステップします が、10 を超えることはありません。3 番目の例では、i が定義された値セットの範 囲内かチェックします。 4 番目の例では、SPL プロシジャは、i が 1、6、11、 16、20、15、10、5、1、2、3、4、または 5 の場合、つまり 11 回 (1 と 5 の重複 分を除く)、ループを実行します。 ヒント: WHILE ループと FOR ループの最も大きい違いは、FOR ループが必ず終 了するのに対し、 WHILE ループには終了する保証がないという点です。 FOR 文は、文がルーチンのループを終了することがない限り、ループの完 全な実行回数を指定します。 WHILE では、エンドレス ループになる可能 性があります。 ループの終了 FOR、FOREACH、または WHILE ループでは、CONTINUE または EXIT 文を使用 してループの実行を制御できます。 CONTINUE 文を使用すると、ルーチンはループに残された文をスキップして、FOR 文の次の反復に移動できます。 EXIT 文を使用すると、ループは終了し、ルーチン は END FOR文に続く最初の文を継続して実行します。 EXIT の後には、ルーチン が実行しているループのキーワードを置いてください。例えば、EXIT FOR または EXIT FOREACH のようにします。 図 414 に、FOR ループ内の CONTINUE および EXIT の例を示します。 FOR i = 1 TO 10 IF i = 5 THEN CONTINUE FOR; . . . ELIF i = 8 THEN EXIT FOR; END IF; END FOR; 図 414. ヒント: CONTINUE および EXIT を使用して、SPL ルーチンのパフォーマンスを 改善し、必要のないループを実行しないようすることができます。 SPL 関数からの値の戻り SPL 関数は、1 つ以上の値を戻すことができます。 SPL 関数が値を戻すには、次 の 2 つの部分を含める必要があります。 1. CREATE PROCEDURE 文または CREATE FUNCTION 文の中に RETURNING 節を記述し、戻す値の数とそのデータ型を指定します。 2. 明示的に値を戻す RETURN 文を関数の本体に入れます。 ヒント: ルーチンは値を戻す CREATE PROCEDURE 文で定義できますが、この場 合、そのルーチンは事実上の関数になります。 ルーチンが値を戻す場合 は、CREATE FUNCTION 文を使用することをお勧めします。 第 11 章 SPL ルーチンの作成と使用 291 RETURNING 文で RETURN 節を定義した場合 SPL 関数は、指定された数とデー タ型に一致する値を戻すことも、まったく値を戻さないことも可能です。 RETURN 節を指定したのに SPL ルーチンが実際に値を戻さない場合でも、なおルーチンは関 数であると考えることができます。このような場合には、ルーチンは RETURN 節 で定義した各値に NULL 値を戻します。 SPL 関数は、変数、式、または別の関数呼出しの結果を戻すことができます。 SPL 関数が変数を戻す場合は、最初に次のいずれかの方法で変数に値を代入する必要が あります。 v LET 文 v デフォルト値 v SELECT 文 v 値を変数に渡すその他の関数 SPL 関数が戻す各値は、最大 32KB です。 重要: SPL 関数の戻り値は、特定のデータ型を持ちます。戻り値のデータ型とし て、一般的な行または一般的なコレクション (COLLECTION) 型を指定する ことはできません。 単一値の戻り 図 415 では、SPL 関数で単一値を戻します。 CREATE FUNCTION increase_by_pct(amt DECIMAL, pct DECIMAL) RETURNING DECIMAL; DEFINE result DECIMAL; LET result = amt + amt * (pct/100); RETURN result; END FUNCTION; 図 415. 関数 increase_by_pct は、10 進数 (DECIMAL) 型の値で増分とその割合の 2 つ の引数を受け取ります。 RETURN 節では、関数が 1 つの 10 進数 (DECIMAL) 型 の値を戻すことを指定します。 RETURN 文は、result に格納された 10 進数 (DECIMAL) 型値を戻します。 複数値の戻り SPL 関数は、表の単一行から複数の値を戻すことができます。 図 416 に示す SPL 関数は、表の単一行から 2 つの列値を戻します。 292 IBM Informix: SQL ガイド: チュートリアル CREATE FUNCTION birth_date( num INTEGER ) RETURNING VARCHAR(30), DATE; DEFINE n VARCHAR(30); DEFINE b DATE; SELECT name, bdate INTO n, b FROM emp_tab WHERE emp_no = num; RETURN n, b; END FUNCTION; 図 416. 図 416 の関数は、表 emp_tab の単一行からの 2 つの値 (name および birthdate) を呼出しルーチンに戻します。この場合、呼出しルーチンには、戻される可変長文 字 (VARCHAR) 型および日付 (DATE) 型の値を処理する準備の必要があります。 図 417 に示す SPL 関数は複数の行から複数の値を戻します。 CREATE FUNCTION birth_date_2( num INTEGER ) RETURNING VARCHAR(30), DATE; DEFINE n VARCHAR(30); DEFINE b DATE; FOREACH cursor1 FOR SELECT name, bdate INTO n, b FROM emp_tab WHERE emp_no > num; RETURN n, b WITH RESUME; END FOREACH END FUNCTION; 図 417. 図 417 の SELECT 文は、ユーザが入力した番号より大きい従業員番号の行の集合 から 2 つの値を取り出します。条件を満たす行の集合には、0 行、1 行、または多 くの行が含まれることがあります。 SELECT 文は多くの行を戻すことができるた め、カーソルの範囲内に置くことができます。 ヒント: SPL ルーチン内の文が行を戻さない場合、それに対応する SPL 変数には NULL 値が割り当てられます。 RETURN 文ではキーワード WITH RESUME を使用します。RETURN WITH RESUME が実行される場合、コントロールは呼出しルーチンに戻ります。ただし、 次回 FETCH 文または呼出ルーチンの次のカーソルの反復により SPL 関数が呼び 出されると、SPL 関数のすべての変数は同じ値を保ち、RETURN WITH RESUME 文の直後の文で実行が継続されます。 SPL ルーチンが複数の値を戻す場合は、呼出しルーチンは次のようにカーソルまた はループを通して複数の値を扱うことができる必要があります。 v 呼出しルーチンが SPL ルーチンである場合、FOREACH ループが必要。 v 呼出しルーチンが ESQL/C プログラムである場合、DECLARE 文で宣言されたカ ーソルが必要。 v 呼出しルーチンが外部ルーチンである場合、ルーチンを記述した言語に適したカ ーソルまたはループが必要。 第 11 章 SPL ルーチンの作成と使用 293 行 (ROW) 型データの処理 (IDS のみ) SPL ルーチンでは、名前付き行 (named row) 型および名前なし行 (unnamed row) 型をパラメータ定義、引数、変数定義、および戻り値として使用できます。 SPL で 行変数を宣言する方法については、277 ページの『行 (ROW) 型変数の宣言 (IDS のみ)』を参照してください。 図 418 では、ここで使用する例として、行 (ROW) 型変数 salary_t および表 emp_info を定義します。 CREATE ROW TYPE salary_t(base MONEY(9,2), bonus MONEY(9,2)) CREATE TABLE emp_info (emp_name VARCHAR(30), salary salary_t); 図 418. 表 emp_info は、従業員名および給与情報の列を持ちます。 ピリオド表記の優先順位 Dynamic Server では、SPL ルーチンの SQL 文でピリオド表記を使用する値 (proj.name のように) が、以下の優先順位の付いた 3 つの意味のうちいずれかに 解釈されます。 1. variable.field 2. column.field 3. table.column つまり、式 proj.name は、まず variable.field として評価されます。そしてルーチ ンが変数 proj を検出できない場合、この式は column.field として評価されます。 さらにルーチンが列 proj を検出できない場合、この式は table.column として評価 されます。(この名前が SPL ルーチンで宣言されている変数やフィールド、そして データベース内のオブジェクト識別子として解決できない場合は、エラーが戻りま す。) 行 (ROW) 型式の更新 SPL ルーチン内から、行変数を使用して行 (ROW) 型式を更新できます。 図 419 に示す SPL プロシジャ emp_raise は、従業員の給与が特定の割合増加した場合に 表 emp_info を更新します。 294 IBM Informix: SQL ガイド: チュートリアル CREATE PROCEDURE emp_raise( name VARCHAR(30), pct DECIMAL(3,2) ) DEFINE row_var salary_t; SELECT salary INTO row_var FROM emp_info WHERE emp_name = name; LET row_var.base = row_var.base * pct; UPDATE emp_info SET salary = row_var WHERE emp_name = name; END PROCEDURE; 図 419. SELECT 文は、表 emp_info の列 salary の行を選択し、行 (ROW) 型変数 row_var に代入します。 プロシジャ emp_raise は、SPL ピリオド表記を使用して変数 row_var のフィー ルド base に直接アクセスします。この場合、ピリオド表記は variable.field を意味 します。emp_raise プロシジャは、row_var.base の値を (row_var.base * pct) として再計算します。プロシジャは、次に表 emp_info の列 salary を、新しい row_var の値で更新します。 重要: 行 (ROW) 型変数は、そのフィールドが設定または参照される前に、行とし て初期化する必要があります。行 (ROW) 型は、 SELECTINTO 文または LET 文で初期化することができます。 コレクションの処理 (IDS のみ) コレクション は、セット (SET) 型、マルチセット (MULTISET) 型、またはリスト (LIST) 型のような同じデータ型の要素をグループ化したものです。 表は、列の内容として、または列の中の行 (ROW) 型フィールドとして格納される コレクション (COLLECTION) 型データを含むことができます。コレクション (COLLECTION) 型データには、単純コレクション (COLLECTION) 型または入れ子 コレクション (COLLECTION) 型が可能です。単純コレクション (COLLECTION) 型 は、組込み型、不透明 (OPAQUE) 型、またはディスティンクト (DISTINCT) 型の セット (SET) 型、マルチセット (MULTISET) 型、またはリスト (LIST) 型です。 入れ子コレクション (COLLECTION) 型 は、他のコレクションを含むコレクション です。 コレクション (COLLECTION) 型の使用 この章の次のセクションでは、いくつかの異なる例により、SPL プログラムでコレ クション (COLLECTION) 型データを操作する方法を説明します。 SPL プログラム内でのコレクションの処理の基本については、図 420 のように表 numbers を使用して説明します。 第 11 章 SPL ルーチンの作成と使用 295 CREATE TABLE numbers ( idINTEGER PRIMARY KEY, primes SET( INTEGER NOT NULL ), evens LIST( INTEGER NOT NULL ), twin_primes LIST( SET( INTEGER NOT NULL ) NOT NULL ) 図 420. 列 primes および列 evens は単純コレクション (COLLECTION) 型を保持しま す。列 twin_primes は入れ子コレクション (COLLECTION) 型 (SET の LIST) を 保持します。対の素数 (twin prime) とは、差が 2 で連続した素数の組であり、5 と 7、または 11 と 13 などです。列 twin_primes はこのようなペアを入力できるよ うに設計されています。 この章のいくつかの例は、図 421 に示す表 polygons を使用してコレクション (COLLECTION) 型データの操作方法を説明します。表 polygons に含まれるコレ クション (COLLECTION) 型データは 2次元のグラフィック データを表します。例 えば、2 次元ポイントの x 座標と y 座標を ’1.0, 3.0’ として表示するような 2 つの実数 (DOUBLE PRECISION) 型の値を持つ point という名前の不透明 (OPAQUE) 型を定義すると仮定します。 point データ型を使用して、多角形を定義 するポイントのセットを含む表を作成できます。 CREATE OPAQUE TYPE point ( INTERNALLENGTH = 8); CREATE TABLE polygons ( id INTEGER PRIMARY KEY, definition SET( point NOT NULL ) ); 図 421. 表 polygons の列 definition は、単純コレクション (COLLECTION) 型であるセ ット (SET) 型の値 point を含みます。 コレクション (COLLECTION) 型の準備 単純コレクション (COLLECTION) 型または入れ子コレクション (COLLECTION) 型の各要素にアクセスし、操作する前に、以下のタスクを実行してください。 v コレクション (COLLECTION) 型データを保持するようコレクション (COLLECTION) 型変数を宣言します。 v コレクション (COLLECTION) 型データの各要素を保持するよう要素変数を宣言 します。 v データベースからコレクション (COLLECTION) 型変数へコレクション (COLLECTION) 型データを選択します。 これらの初期手順を実行した後には、コレクション (COLLECTION) 型データに要 素を挿入したり、既にコレクション (COLLECTION) 型データにある要素を選択ま たは処理することができます。 296 IBM Informix: SQL ガイド: チュートリアル これらの各手順は、次のセクションで表 numbers を例として使用して説明しま す。 ヒント: すべての SPL ルーチン内のコレクションを処理できます。 コレクション (COLLECTION) 型変数の宣言 データベースからコレクションを SPL ルーチンに抽出する前に、コレクション (COLLECTION) 型変数を宣言する必要があります。 図 422 では、コレクション (COLLECTION) 型変数を宣言して、表 numbers から列 primes を抽出します。 DEFINE p_coll SET( INTEGER NOT NULL ); 図 422. DEFINE 文は、列 primes に格納されるコレクション (COLLECTION) 型データと データ型が一致するコレクション (COLLECTION) 型変数 p_coll を宣言します。 要素変数の宣言 コレクション (COLLECTION) 型変数を宣言した後で、コレクション (COLLECTION) 型データの各要素を保持するために要素変数を宣言します。要素変 数のデータ型は、コレクション (COLLECTION) 型データ要素のデータ型と一致す る必要があります。 例えば、セット (SET) 型の要素を列 primes で保持するには、図 423 に示すよう な要素変数宣言を使用します。 DEFINE p INTEGER; 図 423. 入れ子コレクション (COLLECTION) 型変数を保持し、列 twin_primes の要素を保 持する変数を宣言するには、図 424 に示すような変数宣言を使用します。 DEFINE s SET( INTEGER NOT NULL ); 図 424. 変数 s は、整数の セット (SET) 型を保持します。各 セット (SET) 型は、 twin_primes に格納されたリスト (LIST) 型の要素です。 コレクション (COLLECTION) 型変数へのコレクション (COLLECTION) 型データの選択 コレクション (COLLECTION) 型変数を宣言した後で、コレクション (COLLECTION) 型データをその変数に取り出すことができます。コレクション (COLLECTION) 型変数へコレクション (COLLECTION) 型データを取り出すには、 SELECTINTO 文を入力して、名前を付けたコレクション (COLLECTION) 型変数へ コレクション (COLLECTION) 型データ列をデータベースから選択します。 第 11 章 SPL ルーチンの作成と使用 297 例えば、表 numbers の列 primes の 1 行に格納されたコレクション (COLLECTION) 型データを選択するには、図 425 に示すように SELECT 文を SPL ルーチンに追加します。 SELECT primes INTO p_coll FROM numbers WHERE id = 220; 図 425. 表 numbers の 1 行のみに格納するコレクション (COLLECTION) 型データを選択 する場合は、SELECT 文の WHERE 節で指定します。この文により、コレクション (COLLECTION) 型データは、297 ページの図 422 で宣言したコレクション (COLLECTION) 型変数 p_coll に置かれます。 これで、変数 p_coll は、値 SET {5,7,31,19,13} を含む列 primes からのコレク ション (COLLECTION) 型データを保持します。 コレクション (COLLECTION) 型変数への要素の挿入 コレクション (COLLECTION) 型変数にコレクション (COLLECTION) 型データを 抽出したら、コレクション (COLLECTION) 型変数に値を挿入できます。 INSERT 文の構文は、値を追加しようとするコレクション (COLLECTION) 型データの種類 によって少し異なります。 セット (SET) 型データまたはマルチセット (MULTISET) 型データへ の挿入 コレクション (COLLECTION) 型変数に格納されたセット (SET) 型またはマルチセ ット (MULTISET) 型データに挿入するには、INSERT 文を使用し、キーワード TABLE の後にコレクション (COLLECTION) 型変数を置きます。図 426 に例を示 します。 INSERT INTO TABLE(p_coll) VALUES(3); 図 426. キーワード TABLE により、コレクション (COLLECTION) 型変数はコレクション (COLLECTION) 型導出表になります。コレクション (COLLECTION) 型導出表につ いては、138 ページの『SELECT 文でのコレクションの処理 (IDS のみ)』に記載さ れています。図 426 で導出するコレクション (COLLECTION) 型データは、コレク ション (COLLECTION) 型データの各要素が表の行に相当する 1 列の仮想表です。 挿入する前の p_coll は図 427 に示すような行 (要素) を含む仮想表とします。 5 7 31 19 13 図 427. 298 IBM Informix: SQL ガイド: チュートリアル 挿入後の p_coll は、図 428 に示すような仮想表になります。 5 7 31 19 13 3 図 428. コレクション (COLLECTION) 型データはセット (SET) 型なので、新しい値がコレ クション (COLLECTION) 型データに追加されますが、新しい要素の位置は未定義 です。この原則はマルチセット (MULTISET) 型にも適用されます。 ヒント: 単純コレクション (COLLECTION) 型には、値を 1 つずつしか挿入できま せん。 リスト (LIST) 型データへの挿入 コレクション (COLLECTION) 型がリスト (LIST) 型の場合、リスト (LIST) 型 の 特定の位置または最後に新しい要素を追加できます。セット (SET) 型またはマルチ セット (MULTISET) 型については、最初にコレクション (COLLECTION) 型変数を 定義して、データベースからコレクション (COLLECTION) 型変数へコレクション (COLLECTION) 型データを選択する必要があります。 図 429 では、コレクション (COLLECTION) 型変数を定義して、表 numbers から コレクション (COLLECTION) 型変数へリスト (LIST) 型を選択するのに必要な文を 示します。 DEFINE e_coll LIST(INTEGER NOT NULL); SELECT evens INTO e_coll FROM numbers WHERE id = 99; 図 429. この時点の変数 e_coll の値は LIST {2,4,6,8,10} のようになります。変数 e_coll はリスト (LIST) 型を保持するため、各要素のリスト内の位置には番号が付けられま す。リスト (LIST) 型の特定の位置に要素を追加する場合は、AT 位置 節を INSERT 文に追加します。図 430 に例を示します。 INSERT AT 3 INTO TABLE(e_coll) VALUES(12); 図 430. これにより、e_coll のリスト (LIST) 型に、要素 {2,4,12,6,8,10} がこの順で追加 されます。 AT 節の位置 に入力する値は、数値または変数にすることができます。ただし、整 数 (INTEGER) 型または小桁整数 (SMALLINT) 型である必要があります。文字、浮 動小数点数、10 進数値、または式は使用できません。 第 11 章 SPL ルーチンの作成と使用 299 リスト (LIST) 型のコレクションの基数検査 場合により、リスト (LIST) 型データの終わりに要素を追加する必要があります。こ のとき、cardinality( ) 関数を使用して、リスト (LIST) 型データの要素数を検出 し、次に cardinality が戻す値より大きい位置を入力することができます。 Dynamic Server Dynamic Server では、cardinality 関数とともに列に格納されるコレクション (COLLECTION) 型データを使用できますが、コレクション (COLLECTION) 型変数 に格納されるコレクション (COLLECTION) 型データは使用できません。 SPL ルー チンでは、列のコレクション (COLLECTION) 型データの基数を SELECT 文でチェ ックし、値を変数に戻すことができます。 Dynamic Server の終り 表 numbers には、列 id が 99 である行の列 evens にはコレクション (COLLECTION) 型データ LIST {2,4,6,8,10}がまだ含まれていると仮定します。こ のとき、リスト (LIST) 型データの最後に要素 12 を追加すると仮定します。これ は、図 431 に示すように、SPL プロシジャ end_of_list を使用することで実行可能 です。 CREATE PROCEDURE end_of_list() DEFINE n SMALLINT; DEFINE list_var LIST(INTEGER NOT NULL); SELECT CARDINALITY(evens) FROM numbers INTO n WHERE id = 100; LET n = n + 1; SELECT evens INTO list_var FROM numbers WHERE id = 100; INSERT AT n INTO TABLE(list_var) VALUES(12); END PROCEDURE; 図 431. end_of_list の変数 n は、CARDINALITY() が戻す値、つまりリスト (LIST) 型の 項目数を保持します。 LET 文は n をインクリメントし、INSERT 文でリスト (LIST) 型の最後の位置に値を挿入できるようにします。SELECT 文は、表の 1 行 からコレクション (COLLECTION) 型変数 list_var へコレクション (COLLECTION) 型データを選択します。 INSERT 文でリストの最後に要素 12 を 挿入します。 VALUES 節の構文 VALUES 節の構文は、SPL コレクション (COLLECTION) 型変数に挿入する場合と コレクション (COLLECTION) 型列に挿入する場合とで異なります。コレクション (COLLECTION) 型変数にリテラルを挿入するための構文規則は次のとおりです。 v キーワード VALUES の後の値の完全なリストを括弧で囲みます。 300 IBM Informix: SQL ガイド: チュートリアル v 単純コレクション (COLLECTION) 型に挿入する場合は、型コンストラクタまた は大括弧を使用する必要はありません。 v 入れ子コレクション (COLLECTION) 型に挿入する場合は、リテラル コレクショ ン (COLLECTION) 型データを指定する必要があります。 コレクション (COLLECTION) 型データからの要素の選択 要素を扱うために、コレクション (COLLECTION) 型変数に格納されるコレクショ ン (COLLECTION) 型データから SPL ルーチンで一度に 1 つの要素を選択すると 仮定します。 コレクション (COLLECTION) 型データの要素を移動するには、行の集合を移動す るカーソルを宣言する場合のように、まず FOREACH 文を使用してカーソルを宣言 する必要があります。 図 432 では、 FOREACH 文と END FOREACH 文の間に、 文がありません。 FOREACH cursor1 FOR . . . END FOREACH 図 432. FOREACH 文については、285 ページの『カーソルの使用』および「IBM Informix: SQL ガイド: 構文」に記載されています。 次の『コレクション (COLLECTION) 型データ問合せ』では、FOREACH 文と END FOREACH 文の間で省略されている文について説明します。 次のセクションで使用する例は、296 ページの図 421 の表 polygons を基にしてい ます。 コレクション (COLLECTION) 型データ問合せ FOREACH 文と END FOREACH 文の間でカーソルを宣言した後、コレクション (COLLECTION) 型データ問合せ と呼ばれる特殊かつ制限付きの SELECT 文を入力 します。 コレクション (COLLECTION) 型データ問合せは、キーワード FROM TABLE とそ れに続くコレクション (COLLECTION) 型変数名を使用する SELECT 文です。 図 433 に、コレクション (COLLECTION) 型導出表 と呼ばれるこの構造を示します。 FOREACH cursor1 FOR SELECT * INTO pnt FROM TABLE(vertexes) . . . END FOREACH 図 433. 図 433 の SELECT 文では、コレクション (COLLECTION) 型変数 vertexes をコ レクション (COLLECTION) 型導出表として使用しています。コレクション (COLLECTION) 型導出表は、コレクション (COLLECTION) 型データの各要素が表 の行になっている、1 列の表と考えることができます。例えば、vertexes に格納さ 第 11 章 SPL ルーチンの作成と使用 301 れた 4 つのセット (SET) 型ポイントを、4 つの行を持つ表 として使用できます。 図 434 に例を示します。 ’(3.0,1.0)’ ’(8.0,1.0)’ ’(3.0,4.0)’ ’(8.0,4.0)’ 図 434. 図 434 の FOREACH 文の最初の反復の後、コレクション (COLLECTION) 型デー タ問合せは vertexes の最初の要素を選択し、それを pnt に格納します。つまり、 pnt は値 ’(3.0,1.0)’ を保持するようになります。 ヒント: コレクション (COLLECTION) 型変数 vertexes がリスト (LIST) 型ではな くセット (SET) 型を保持するため、vertexes の要素には決まった順序が ありません。実際のデータベースでは、値 ’(3.0,1.0)’ がセット (SET) 型データの最初になっていない場合があります。 コレクション (COLLECTION) 型データ問合せの SPL ルーチンへの 追加 これで、SPL ルーチンに FOREACH およびコレクション (COLLECTION) 型デー タ問合せで定義したカーソルを追加できます。 図 435 に例を示します。 CREATE PROCEDURE shapes() DEFINE vertexes SET( point NOT NULL ); DEFINE pnt point; SELECT definition INTO vertexes FROM polygons WHERE id = 207; FOREACH cursor1 FOR SELECT * INTO pnt FROM TABLE(vertexes); . . . END FOREACH . . . END PROCEDURE; 図 435. 図 435 の文は、コレクション (COLLECTION) 型変数を処理する SPL ルーチンの フレームワークを形成します。コレクションを要素に分解するには、コレクション (COLLECTION) 型導出表 を使用します。コレクション (COLLECTION) 型データを 要素に分解した後では、ルーチンは、コレクション (COLLECTION) 型導出表の行 のように、要素に個別にアクセスできます。pnt の要素を 1 つ選択し、それを更新 または削除できます。306 ページの『コレクション (COLLECTION) 型要素の更 新』と 303 ページの『コレクション (COLLECTION) 型要素の削除』で説明しま す。 コレクション (COLLECTION) 型データ問合せの構文については、「IBM Informix: SQL ガイド: 構文」の SELECT 文に関する説明を参照してください。コレクション 302 IBM Informix: SQL ガイド: チュートリアル (COLLECTION) 型導出表の構文については、「IBM Informix: SQL ガイド: 構文 」 のコレクション (COLLECTION) 型導出表に関する説明を参照してください。 ヒント: 要素を含まないか、あるいはゼロ要素を含むコレクション (COLLECTION) 型データから選択する場合は、カーソルを宣言しないでコレクション (COLLECTION) 型データの問合せを使用することができます。ただし、コ レクション (COLLECTION) 型データに複数の要素が含まれており、カー ソルを使用しない場合には、エラー メッセージが表示されます。 コレクション (COLLECTION) 型要素の削除 コレクション (COLLECTION) 型変数から要素変数へ各要素を選択した後では、コ レクション (COLLECTION) 型データから要素を削除できます。例えば、コレクシ ョン問合せによってコレクション (COLLECTION) 型変数 vertexes からあるポイ ントを選択したら、コレクション (COLLECTION) 型データからそのポイントを削 除できます。 コレクション (COLLECTION) 型データ要素の削除に必要な手順は次のとおりで す。 1. コレクション (COLLECTION) 型変数と要素変数を宣言します。 2. データベースからコレクション (COLLECTION) 型変数へコレクション (COLLECTION) 型データを選択します。 3. コレクション (COLLECTION) 型変数から一度に 1 つの要素を選択できるよう にカーソルを宣言します。 4. 削除する要素を検索するループまたは分岐を記述します。 5. コレクション (COLLECTION) 型変数をコレクション (COLLECTION) 型導出表 として使用する DELETE WHERE CURRENT OF 文を使用してコレクション (COLLECTION) 型データから要素を削除します。 図 436 に示すルーチンは vertexes の 4 ポイントの 1 つを削除するため、多角形 は四角形ではなく三角形になります。 第 11 章 SPL ルーチンの作成と使用 303 CREATE PROCEDURE shapes() DEFINE vertexes SET( point NOT NULL ); DEFINE pnt point; SELECT definition INTO vertexes FROM polygons WHERE id = 207; FOREACH cursor1 FOR SELECT * INTO pnt FROM TABLE(vertexes) IF pnt = ’(3,4)’ THEN -- calls the equals function that -- compares two values of point type DELETE FROM TABLE(vertexes) WHERE CURRENT OF cursor1; EXIT FOREACH; ELSE CONTINUE FOREACH; END IF; END FOREACH . . . END PROCEDURE; 図 436. 図 436 では、 FOREACH 文でカーソルを宣言しています。SELECT 文はコレクシ ョン (COLLECTION) 導出型問合せであり、コレクション (COLLECTION) 型変数 vertexes から要素変数 pnt へ要素を 1 回に 1 つ選択します。 IF THEN ELSE 構造が、現在 pnt に格納されている値をテストし、それがポイン ト ’(3,4)’ であるかどうか調べます。式 pnt = ’(3,4)’ は point データ型につい て定義された関数 equal() の実現値を呼び出すことに注意してください。 pnt の 現行値が ’(3,4)’ の場合、 DELETE 文がそれを削除し、 EXIT FOREACH 文がカ ーソルを終了します。 ヒント: コレクション (COLLECTION) 型変数に格納されたコレクション (COLLECTION) 型データから要素を削除しても、データベースに格納され たコレクション (COLLECTION) 型データからは削除されません。コレク ション(COLLECTION) 型変数から要素を削除した場合は、データベースに 格納されているコレクション (COLLECTION) 型データを新しいコレクシ ョン (COLLECTION) 型データに更新する必要があります。コレクション (COLLECTION) 型データの列を更新する方法を示す例については、304 ペ ージの『データベース内のコレクション (COLLECTION) 型データの更 新』を参照してください。 DELETE 文の構文については、「IBM Informix: SQL ガイド: 構文 」に記載されて います。 データベース内のコレクション (COLLECTION) 型データの更新 要素の削除、更新、または挿入により、SPL ルーチンの中のコレクション (COLLECTION) 型変数の内容を変更した場合は、データベースを新しいコレクショ ン (COLLECTION) 型データで更新する必要があります。 データベース内のコレクション (COLLECTION) 型データを更新するには、 UPDATE 文を追加して、表の中のコレクション (COLLECTION) 型の列を、更新さ 304 IBM Informix: SQL ガイド: チュートリアル れたコレクション (COLLECTION) 型変数の内容に設定します。例えば、図 437 の UPDATE 文は、コレクション (COLLECTION) 型変数 vertexes に格納される新し いコレクション (COLLECTION) 型データに列 definition を設定して、表 polygons を更新する方法を示します。 CREATE PROCEDURE shapes() DEFINE vertexes SET(point NOT NULL); DEFINE pnt point; SELECT definition INTO vertexes FROM polygons WHERE id = 207; FOREACH cursor1 FOR SELECT * INTO pnt FROM TABLE(vertexes) IF pnt = ’(3,4)’ THEN -- calls the equals function that -- compares two values of point type DELETE FROM TABLE(vertexes) WHERE CURRENT OF cursor1; EXIT FOREACH; ELSE CONTINUE FOREACH; END IF; END FOREACH UPDATE polygons SET definition = vertexes WHERE id = 207; END PROCEDURE; 図 437. これで shapes( ) ルーチンは完成です。 shapes( ) ルーチンを実行すれば、列 ID が 207 である行に格納されるコレクション (COLLECTION) 型データは更新され て、4 つではなく 3 つの値が含まれます。 コレクション (COLLECTION) 型データを操作する他の SPL ルーチンを記述するた めに、shapes( ) ルーチンをフレームワークとして使用することができます。 表 polygons の行 207 の列 definition に、現在格納されるコレクション (COLLECTION) 型データの要素は次のようにリストされます。 ’(3,1)’ ’(8,1)’ ’(8,4)’ コレクション全体の削除 コレクションのすべての要素を削除する場合は、単一の SQL 文を使用できます。 カーソルを宣言する必要はありません。コレクション全体を削除するには、次のタ スクを行う必要があります。 v コレクション (COLLECTION) 型変数を定義します。 v データベースからコレクション (COLLECTION) 型変数へコレクションを選択し ます。 v コレクション (COLLECTION) 型変数をコレクション (COLLECTION) 型導出表 として使用する DELETE 文を入力します。 第 11 章 SPL ルーチンの作成と使用 305 v データベースからコレクションを更新します。 図 438 に、SPL ルーチンでコレクション全体を削除するのに使用する文を示しま す。 DEFINE vertexes SET( INTEGER NOT NULL ); SELECT definition INTO vertexes FROM polygons WHERE id = 207; DELETE FROM TABLE(vertexes); UPDATE polygons SET definition = vertexes WHERE id = 207; 図 438. このフォームの DELETE 文は、コレクション (COLLECTION) 型変数 vertexes の コレクション (COLLECTION) 型データ全体を削除します。コレクション (COLLECTION) 型導出表を使用する DELETE 文では、WHERE 節を使用できませ ん。 UPDATE 文の後の表 polygons には空のコレクションが含まれ、列 id は 207 に 等しくなります。 DELETE 文の構文については、「IBM Informix: SQL ガイド: 構文 」に記載されて います。 コレクション (COLLECTION) 型要素の更新 各要素を選択あるいは削除するように、カーソルの範囲内でコレクション (COLLECTION) 型データにアクセスすることにより、コレクション (COLLECTION) 型データの要素を更新できます。 コレクション SET{100, 200, 300, 500} を更新して値 500 を 400 にする場合、図 439 に示すようにデータベースからコレクション (COLLECTION) 型変数にセット (SET) 型を抽出し、その後カーソルを宣言してセット (SET) 型の要素内を移動させ ます。 306 IBM Informix: SQL ガイド: チュートリアル DEFINE s SET(INTEGER NOT NULL); DEFINE n INTEGER; SELECT numbers INTO s FROM orders WHERE order_num = 10; FOREACH cursor1 FOR SELECT * INTO n FROM TABLE(s) IF ( n == 500 ) THEN UPDATE TABLE(s)(x) SET x = 400 WHERE CURRENT OF cursor1; EXIT FOREACH; ELSE CONTINUE FOREACH; END IF; END FOREACH 図 439. UPDATE 文では、コレクション (COLLECTION) 型変数 s をコレクション (COLLECTION) 型導出表として使用します。コレクション (COLLECTION) 型導出 表を指定するには、キーワード TABLE を使用します。 UPDATE 文内で (s) に続 く値 (x) は、導出列 です。この列名は、コレクション (COLLECTION) 型導出表 には列がないにもかかわらず、SET 節には必要です。 次のような 1 行を持つコレクション (COLLECTION) 型導出表を想定してくださ い。 100 200 300 500 この例では、x は値 500 を持つ「列」の架空の列名です。導出列は、組込み型、不 透明 (OPAQUE) 型、ディスティンクト (DISTINCT) 型、またはコレクション (COLLECTION) 型要素のコレクションを更新するときにのみ指定します。行 (ROW) 型のコレクション (COLLECTION) 型データを更新する場合は、309 ページ の『行 (ROW) 型のコレクション (COLLECTION) 型データの更新』で説明するよ うに導出列の代わりにフィールド名を使用します。 変数によるコレクション (COLLECTION) 型データの更新 リテラル値の代わりに変数に格納された値でも、コレクション (COLLECTION) 型 データを更新することができます。 図 440 の SPL プロシジャでは、図 439 に示したのと同じような文を使用していま す。ただし、このプロシジャでは、表 manager の列 direct_reports の セット (SET) 型データを、定数値ではなく変数を使用して更新しています。表 manager は、289 ページの図 410 で定義されています。 第 11 章 SPL ルーチンの作成と使用 307 CREATE PROCEDURE new_report(mgr VARCHAR(30), old VARCHAR(30), new VARCHAR(30) ) DEFINE s SET (VARCHAR(30) NOT NULL); DEFINE n VARCHAR(30); SELECT direct_reports INTO s FROM manager WHERE mgr_name = mgr; FOREACH cursor1 FOR SELECT * INTO n FROM TABLE(s) IF ( n == old ) THEN UPDATE TABLE(s)(x) SET x = new WHERE CURRENT OF cursor1; EXIT FOREACH; ELSE CONTINUE FOREACH; END IF; END FOREACH UPDATE manager SET mgr_name = s WHERE mgr_name = mgr; END PROCEDURE; 図 440. FOREACH ループに入れ子になっている UPDATE 文は、コレクション (COLLECTION) 型導出表 s および導出列 x を使用します。現在値の n が old と 同じであれば、UPDATE 文はこれを new の値に変更します。 2 番目の UPDATE 文は、表 manager の新しいコレクションを格納します。 コレクション全体の更新 コレクション (COLLECTION) 型データのすべての要素を同じ値に更新する場合、 あるいはコレクション (COLLECTION) 型データに含まれる要素が 1 つのみの場合 は、カーソルを使用する必要がありません。 図 441 の文は、コレクション (COLLECTION) 型データをコレクション (COLLECTION) 型変数へ抽出して、次に 1 つの文で更新する方法を示します。 DEFINE s SET (INTEGER NOT NULL); SELECT numbers INTO s FROM orders WHERE order_num = 10; UPDATE TABLE(s)(x) SET x = 0; UPDATE orders SET numbers = s WHERE order_num = 10; 図 441. この例の最初の UPDATE 文では x という名前の導出列とコレクション (COLLECTION) 型導出表 s を使用して、コレクション (COLLECTION) 型データ のすべての要素に値 0 を与えます。2 番目の UPDATE 文は新しいコレクション (COLLECTION) 型データをデータベースに格納します。 308 IBM Informix: SQL ガイド: チュートリアル 行 (ROW) 型のコレクション (COLLECTION) 型データの更新 行 (ROW) 型のコレクション (COLLECTION) 型データを更新する場合は、導出列 の名前の代わりに更新するフィールドの名前を UPDATE 文の中で使用できます。 289 ページの図 410 の表 manager には、図 442 のように定義される projects と いう列があり、行 (ROW) 型のリスト (LIST) 型データを含みます。 projects LIST( ROW( pro_name VARCHAR(15), pro_members SET(VARCHAR(20) NOT NULL) ) NOT NULL) 図 442. リスト (LIST) 型データの中の各行 (ROW) 型にアクセスするには、カーソルを宣言 して、コレクション (COLLECTION) 型変数へリスト (LIST) 型データを選択しま す。各行 (ROW) 型を抽出した後では、図 443 に示すように、フィールド名および 新しいデータを指定することによりフィールド pro_name または pro_members を更新できます。 CREATE PROCEDURE update_pro( mgr VARCHAR(30), pro VARCHAR(15) ) DEFINE p LIST(ROW(a VARCHAR(15), b SET(VARCHAR(20) NOT NULL) ) NOT NULL); DEFINE r ROW(p_name VARCHAR(15), p_member SET(VARCHAR(20) NOT NULL) ); LET r = ROW("project", "SET{’member’}"); SELECT projects INTO p FROM manager WHERE mgr_name = mgr; FOREACH cursor1 FOR SELECT * INTO r FROM TABLE(p) IF (r.p_name == ’Zephyr’) THEN UPDATE TABLE(p) SET pro_name = pro WHERE CURRENT OF cursor1; EXIT FOREACH; END IF; END FOREACH UPDATE manager SET projects = p WHERE mgr_name = mgr; END PROCEDURE; 図 443. SPL プログラムで行 (ROW) 型変数を使用する前に、 LET 文または SELECTINTO 文で行変数を初期化する必要があります。 図 443 の FOREACH ループに入れ子に なっている UPDATE 文は、行 (ROW) 型のフィールド pro_name を、変数 pro に格納された値に設定します。 ヒント: 行 (ROW) 型のフィールド pro_members の SET 内の値を更新するに は、カーソルを宣言し、導出列に対して UPDATE 文を使用します。この 操作については、306 ページの『コレクション (COLLECTION) 型要素の 更新』で説明されています。 第 11 章 SPL ルーチンの作成と使用 309 入れ子コレクション (COLLECTION) 型データの更新 コレクションのコレクション (COLLECTION) 型データを更新する場合は、カーソ ルを宣言して外部コレクション (COLLECTION) 型データにアクセスし、次に、入 れ子カーソルを宣言して内部コレクション (COLLECTION) 型データにアクセスす る必要があります。 例えば、表 manager には図 444 に示すような追加の列 scores があり、要素型が 整数のマルチセット (MULTISET) 型であるリスト (LIST) 型を含むと仮定します。 scores LIST(MULTISET(INT NOT NULL) NOT NULL) 図 444. マルチセット (MULTISET) 型の値を更新するには、図 445 に示すように、リスト (LIST) 型の各値を移動するカーソルと、マルチセット (MULTISET) 型の中の各値 を移動する入れ子カーソルを宣言します。 CREATE FUNCTION check_scores ( mgr VARCHAR(30) ) SPECIFIC NAME nested; RETURNING INT; DEFINE DEFINE DEFINE DEFINE l m n c LIST( MULTISET( INT NOT NULL ) NOT NULL ); MULTISET( INT NOT NULL ); INT; INT; SELECT scores INTO l FROM manager WHERE mgr_name = mgr; FOREACH list_cursor FOR SELECT * FROM TABLE(l) INTO m; FOREACH set_cursor FOR SELECT * FROM TABLE(m) INTO n; IF (n == 0) THEN DELETE FROM TABLE(m) WHERE CURRENT OF set_cursor; ENDIF; END FOREACH; LET c = CARDINALITY(m); RETURN c WITH RESUME; END FOREACH END FUNCTION WITH LISTING IN ’/tmp/nested.out’; 図 445. 図 445 の SPL 関数は、列 scores の マルチセット (MULTISET) 型を l に選択 し、マルチセット (MULTISET) 型の各値を m に選択します。m の値が 0 の場 合、関数はそれをマルチセット (MULTISET) 型から削除します。 0 の値を削除し た後で、関数は各マルチセット (MULTISET) 型の中に残った要素をカウントして、 整数を戻します。 310 IBM Informix: SQL ガイド: チュートリアル ヒント: この関数はリスト (LIST) 型の各 マルチセット (MULTISET) 型に値を戻す ため、関数を実行するときはカーソルを使用して EXECUTE FUNCTION 文を囲む必要があります。 コレクション (COLLECTION) 型データへの挿入 カーソルを宣言しないでコレクション (COLLECTION) 型データに値を挿入できま す。コレクション (COLLECTION) 型データがセット (SET) 型またはマルチセット (MULTISET) 型の場合は、コレクション (COLLECTION) 型データに値を追加でき ますが、コレクション (COLLECTION) 型データは特定の順序を持たないため新し い要素の位置は未定義です。値がリスト (LIST) 型の場合は、新しい要素をリスト (LIST) 型の特定のポイントか、またはリスト (LIST) 型の終わりに追加できます。 表 manager の列 direct_reports はセット (SET) 型のコレクション (COLLECTION) 型データを含み、列 projects はリスト (LIST) 型を含みます。列 direct_reports のセット (SET) 型に名前を追加するには、図 446 に示すように、 INSERT 文とコレクション (COLLECTION) 型導出表を使用します。 CREATE PROCEDURE new_emp( emp VARCHAR(30), mgr VARCHAR(30) ) DEFINE r SET(VARCHAR(30) NOT NULL); SELECT direct_reports INTO r FROM manager WHERE mgr_name = mgr; INSERT INTO TABLE (r) VALUES(emp); UPDATE manager SET direct_reports = r WHERE mgr_name = mgr; END PROCEDURE; 図 446. この SPL プロシジャは、引数として従業員名とマネージャ名を取ります。次にプロ シジャはユーザが入力した manager について列 direct_reports のコレクション (COLLECTION) 型データを選択し、ユーザが入力した従業員名を追加し、新しいコ レクション (COLLECTION) 型データにより表 manager を更新します。 図 446 の INSERT 文はユーザが入力する新しい従業員名を、コレクション (COLLECTION) 型変数 r に含まれるセット (SET) 型データに挿入します。次に UPDATE 文が新しいコレクション (COLLECTION) 型データを表 manager に格納 します。 VALUES 節の構文に注意してください。リテラル データと変数をコレクション (COLLECTION) 型変数に挿入するための構文規則は次のとおりです。 v キーワード VALUES の後の値の完全なリストを括弧で囲みます。 v コレクション (COLLECTION) 型データがセット (SET) 型、マルチセット (MULTISET) 型、またはリスト (LIST) 型の場合は、型コンストラクタとその後 にブラケットで囲んだ挿入する値のリストを使用します。また、コレクション (COLLECTION) 型の値は引用符で囲みます。 VALUES( "SET{ 1,4,8,9 }" ) 第 11 章 SPL ルーチンの作成と使用 311 v コレクション (COLLECTION) 型データが行 (ROW) 型を含む場合は、行 (ROW) 型と、その後に括弧で囲んだ挿入する値のリストを使用します。 VALUES( ROW( ’Waters’, ’voyager_project’ ) ) v コレクション (COLLECTION) 型データが入れ子コレクション (COLLECTION) 型、入れ子キーワード、括弧、および大括弧の場合は、データ型の定義方法に従 います。 VALUES( "SET{ ROW(’Waters’, ’voyager_project’), ROW(’Adams’, ’horizon_project’) }") コレクション (COLLECTION) 型データへの値の挿入の詳細については、第 6 章 を参照してください。 入れ子コレクションへの挿入 入れ子コレクション (COLLECTION) 型へ挿入する場合は、 VALUES 節の構文を 変更します。例えば、296 ページの図 420 に示すように、表 numbers の列 twin_primes に値を挿入すると仮定します。 また、列 twin_primes について、セット (SET) 型をリスト (LIST) 型に挿入、あ るいは要素を内側の セット (SET) 型に挿入する場合も考えられます。次のセクシ ョンでは、このような各タスクを説明します。 外部コレクション(COLLECTION) 型データへのコレクション (COLLECTION) 型 データの挿入: セット (SET) 型をリスト (LIST) 型へ挿入することは、単一値を単 純コレクション (COLLECTION) 型に挿入するのと類似しています。 セット (SET) 型をリスト (LIST) 型に挿入するには、コレクション (COLLECTION) 型変数を宣言して、リスト (LIST) 型を保持し、その中にコレクション (COLLECTION) 型データ全体を選択します。コレクション (COLLECTION) 型変数 をコレクション (COLLECTION) 型導出表として使用すると、リスト (LIST) 型の中 の各セット (SET) 型が表 の中の行 になります。これで、別のセット (SET) 型を リスト (LIST) 型の終わりまたは指定したポイントに挿入できます。 例えば、表 number の 1 行の列 twin_primes は図 447 に示すように、次のリスト (LIST) 型を含む可能性があります。 LIST( SET{3,5}, SET{5,7}, SET{11,13} ) 図 447. リスト (LIST) 型をコレクション (COLLECTION) 型導出表として考える場合は、図 448 に示すようになります。 {3,5} {5,7} {11,13} 図 448. 312 IBM Informix: SQL ガイド: チュートリアル 値 "SET{17,19}" をリスト (LIST) 型の 2 番目の項目として挿入する場合は、 図 449 のように記述します。 CREATE PROCEDURE add_set() DEFINE l_var LIST( SET( INTEGER NOT NULL ) NOT NULL ); SELECT twin_primes INTO l_var FROM numbers WHERE id = 100; INSERT AT 2 INTO TABLE (l_var) VALUES( "SET{17,19}" ); UPDATE numbers SET twin_primes = l WHERE id = 100; END PROCEDURE; 図 449. INSERT 文の中の VALUES 節は、値 SET {17,19} をリスト (LIST) 型の 2 番目の 位置に挿入します。これで、リスト (LIST) 型データは図 450 に示すように表示さ れます。 {3,5} {17,19} {5,7} {11,13} 図 450. 図 451 に示すように、セット (SET) 型を引数として SPL ルーチンに渡すことによ り、同じ内容の挿入を行うことができます。 CREATE PROCEDURE add_set( set_var SET(INTEGER NOT NULL), row_id INTEGER ); DEFINE list_var LIST( SET(INTEGER NOT NULL) NOT NULL ); DEFINE n SMALLINT; SELECT CARDINALITY(twin_primes) INTO n FROM numbers WHERE id = row_id; LET n = n + 1; SELECT twin_primes INTO list_var FROM numbers WHERE id = row_id; INSERT AT n INTO TABLE( list_var ) VALUES( set_var ); UPDATE numbers SET twin_primes = list_var WHERE id = row_id; END PROCEDURE; 図 451. 第 11 章 SPL ルーチンの作成と使用 313 ユーザは add_set() の中で、リスト (LIST) 型に追加するセット (SET) 型データ と、そのセット (SET) 型データを挿入する行の id である整数 (INTEGER) 型の値 を指定します。 内部コレクション (COLLECTION) 型データへの値の挿入: SPL ルーチンでは、入 れ子コレクションの内部コレクション (COLLECTION) 型データに値を挿入するこ ともできます。一般的に、入れ子コレクション (COLLECTION) 型の内部コレクシ ョン (COLLECTION) 型データにアクセスして値を追加するには、次の手順を実行 します。 1. コレクション (COLLECTION) 型変数を宣言して、表の 1 行に格納されるコレ クション (COLLECTION) 型データ全体を保持します。 2. 要素変数を宣言して、外部コレクション (COLLECTION) 型データの 1 つの要 素を保持します。要素変数自体はコレクション (COLLECTION) 型変数です。 3. コレクション (COLLECTION) 型変数に対して表の 1 行からコレクション (COLLECTION) 型データを選択します。 4. 外部コレクション (COLLECTION) 型データの要素を移動できるようにカーソル を宣言します。 5. 要素変数に対して 1 回に 1 つの要素を選択します。 6. 分岐またはループを使用して、更新する内部コレクション (COLLECTION) 型デ ータを検索します。 7. 新しい値を内部コレクション (COLLECTION) 型データに挿入します。 8. カーソルをクローズします。 9. データベース表を新しいコレクション (COLLECTION) 型データで更新します。 例として、表 numbers の列 twin_primes についてこの処理を使用できます。例 えば、twin_primes には図 452 に示す値が含まれており、値 18 をリスト (LIST) 型の最後のセット (SET) 型に挿入すると仮定します。 LIST( SET( {3,5}, {5,7}, {11,13}, {17,19} ) ) 図 452. 図 453 は、値を挿入するプロシジャの先頭を示します。 CREATE PROCEDURE add_int() DEFINE list_var LIST( SET( INTEGER NOT NULL ) NOT NULL ); DEFINE set_var SET( INTEGER NOT NULL ); SELECT twin_primes INTO list_var FROM numbers WHERE id = 100; 図 453. ここまでで、add_int プロシジャはステップ 1、2 、および 3 を終了しました。最 初の DEFINE 文は、表 numbers の 1 行に格納されるコレクション (COLLECTION) 型データ全体を保持するコレクション (COLLECTION) 型変数を宣 言します。 314 IBM Informix: SQL ガイド: チュートリアル 2 番目の DEFINE 文は、コレクション (COLLECTION) 型データの要素を保持する 要素変数を宣言します。この場合、要素変数自体はセット (SET) 型を保持するので コレクション (COLLECTION) 型変数です。 SELECT 文は、コレクション (COLLECTION) 型変数 list_var に 1 行からコレクション (COLLECTION) 型デー タ全体を選択します。 図 454 に示す方法でカーソルを宣言すれば、外部コレクション (COLLECTION) 型 データの要素を移動できます。 FOREACH list_cursor FOR SELECT * INTO set_var FROM TABLE( list_var); FOREACH element_cursor FOR 図 454. ルーチンの実行 SPL ルーチンまたは外部ルーチンは、以下のいずれかの方法で実行できます。 v DB–Access から実行するスタンドアロンの EXECUTE PROCEDURE 文または EXECUTE FUNCTION 文を使用します。 v 別の SPL ルーチンまたは外部ルーチンから明示的にルーチンを呼び出します。 v SQL 文の式でルーチン名を使用します。 外部ルーチン とは、C または他の外部言語で記述されたルーチンです。 EXECUTE 文の使用 EXECUTE PROCEDURE または EXECUTE FUNCTION を使用して、SPL ルーチ ンまたは外部ルーチンを実行できます。一般的に、EXECUTE PROCEDURE をプロ シジャに使用し、EXECUTE FUNCTION を関数に使用するのが最良です。 ヒント: 下位方向の互換性のために、EXECUTE PROCEDURE 文では、 SPL 関数 名と INTO 節を使用して値を戻すことができます。ただし、EXECUTE PROCEDURE 文はプロシジャとともにのみ、また EXECUTE FUNCTION 文は関数とともにのみ使用することをお勧めします。 EXECUTE PROCEDURE 文と EXECUTE FUNCTION 文はスタンド アロン文とし て DB–Access から、または SPL ルーチンまたは外部ルーチン内から発行できま す。ルーチン名は、データベースの範囲内で一意であり、引数を必要としない場合 は、図 455 に示すように、EXECUTE PROCEDURE 文の後にその名前と括弧を入力 することにより実行できます。 EXECUTE PROCEDURE update_orders(); 図 455. 第 11 章 SPL ルーチンの作成と使用 315 EXECUTE 文でプロシジャを起動する場合はプロシジャが値を戻さないため INTO 節は存在しません。 ルーチンに引数が含まれるよう予定されている場合は、図 456 に示すように、引数 の値を括弧で囲んで入力する必要があります。 EXECUTE FUNCTION scale_rectangles(107, 1.9) INTO new; 図 456. 図 456 の文は関数を実行します。関数は値を戻すため、EXECUTE FUNCTION 文 は、戻り値が格納される変数を指定する INTO 節を使用します。関数を実行するた めに EXECUTE 文を使用する場合は、必ず INTO 節が必要です。 Dynamic Server データベースが同じ名前で複数のプロシジャまたは関数を持つ場合は、Dynamic Server は引数のデータ型に基づいて正しい関数を検索します。例えば、図 456 の文 は引数として整数 (INTEGER) 型および小桁実数 (REAL) 型の値を供給するため、 データベースに scale_rectangles() という名前の複数のルーチンが含まれている場 合は、データベース サーバは整数 (INTEGER) 型および小桁実数 (REAL) 型を受け 付ける関数 scale_rectangles() のみを実行します。 SPL ルーチンのパラメータ リストは、常にパラメータ名とデータ型を持ちます。ル ーチンを実行すると、パラメータ名はオプションになります。ただし 図 457 のよう に、値ではなく名前による引数を EXECUTE PROCEDURE 文または EXECUTE FUNCTION 文に渡すと、Dynamic Server は部分ルーチン分析 として知られる処理 により、ルーチンごとの名前と引数のみを解決します。 EXECUTE FUNCTION scale_rectangles( rectid = 107, scale = 1.9 ) INTO new_rectangle; 図 457. Dynamic Server の終り 修飾ルーチン名 を文に追加することにより、別のデータベース サーバに格納され る SPL ルーチンを実行することもできます。この名前は、図 458 に示すように、 database@dbserver:owner_name.routine_name というフォームになります。 EXECUTE PROCEDURE informix@davinci:bsmith.update_orders(); 図 458. ルーチンをリモートで実行する場合は、修飾のあるルーチン名の所有者名 はオプシ ョンです。 316 IBM Informix: SQL ガイド: チュートリアル CALL 文の使用 CALL 文を使用して、SPL ルーチンまたは外部ルーチンを SPL ルーチンから呼び 出すことができます。 CALL は、プロシジャと関数の両方を実行できます。関数を 実行するのに CALL 文を使用する場合は、 RETURNING 節と関数が戻す値 (1 つ 以上) を受け取る SPL 変数 (1 つ以上) の名前を追加します。 例えば、図 459 のように、関数 scale_rectangles で四角形の面積を計算し、次に 四角形の記述とともに面積を戻す外部関数を呼び出すと仮定します。 CREATE FUNCTION scale_rectangles( rectid INTEGER, scale REAL ) RETURNING rectangle_t, REAL; DEFINE rectv rectangle_t; DEFINE a REAL; SELECT rect INTO rectv FROM rectangles WHERE id = rectid; IF ( rectv IS NULL ) THEN LET rectv.start = (0.0,0.0); LET rectv.length = 1.0; LET rectv.width = 1.0; LET a = 1.0; RETURN rectv, a; ELSE LET rectv.length = scale * rectv.length; LET rectv.width = scale * rectv.width; CALL area(rectv.length, rectv.width) RETURNING a; RETURN rectv, a; END IF; END FUNCTION; 図 459. 図 459 の SPL 関数は、関数 area( ) を呼び出す CALL 文を使用しています。関 数 area( ) が戻す値は a に格納され、RETURN 文により呼出しルーチンに戻され ます。 この例では area( ) は外部関数ですが、 CALL 文を同じ方法で SPL 関数でも使用 できます。 式の中のルーチンの実行 組込み関数と同じように、SPL ルーチン、および SPL ルーチンからの外部ルーチ ンを SQL 文と SPL 文の式で使用することにより、実行することができます。式の 中で使用するルーチンは、他の文に値を戻すため、通常は関数になります。 例えば、LET 文により、戻り値を変数に代入する関数を実行できます。 図 460 の 文はこれと同じタスクを実行します。これらの文は SPL ルーチンの範囲内の外部関 数を実行して、戻り値を変数 a に代入します。 第 11 章 SPL ルーチンの作成と使用 317 LET a = area( rectv.length, rectv.width ); CALL area( rectv.length, rectv.width ) RETURNING a; -- these statements are equivalent 図 460. また、図 461 に示すように、SQL 文からSPL ルーチンを実行することもできま す。特定の割合で特定の価格を増加する SPL 関数 increase_by_pct を記述すると 仮定します。作成した SPL ルーチンは、他のいかなる SPL ルーチンでも使用でき ます。 CREATE FUNCTION raise_price ( num INT ) RETURNING DECIMAL; DEFINE p DECIMAL; SELECT increase_by_pct(price, 20) INTO p FROM inventory WHERE prod_num = num; RETURN p; END FUNCTION; 図 461. 図 461 の例は inventory の指定された行の列 price を選択して、その値を SPL 関数 increase_by_pct への引数として使用します。次に、関数は 20% 増加した price の新しい値を変数 p に戻します。 RETURN 文による外部関数の実行 RETURN 文を使用し て SPL ルーチンの範囲内からあらゆる外部関数を実行できま す。図 462 に示す外部関数は SPL プログラムの RETURN 文で使用されます。 CREATE FUNCTION c_func() RETURNS int LANGUAGE C; CREATE FUNCTION spl_func() RETURNS INT; RETURN(c_func()); END FUNCTION; EXECUTE FUNCTION spl_func(); 図 462. 関数 spl_func() を実行すると、関数 c_func() が起動され、外部関数が戻す値が SPL 関数により戻されます。 SPL ルーチンからのカーソル関数の実行 カーソル関数はユーザ定義関数であり、1 つ以上のデータの行を戻します。そのた めに実行するカーソルが必要です。カーソル関数は、次の関数のいずれかです。 v キーワード WITH RESUME を含む RETURN 文をともなう SPL 関数 v 反復関数として定義される外部関数 318 IBM Informix: SQL ガイド: チュートリアル カーソル関数の動作は、関数が SPL 関数でも外部関数でも同じです。ただし、SPL カーソル関数は反復のたびに複数の値を戻すことができますが、外部カーソル関数 (反復関数) は反復のたびに 1 つの値しか戻すことができません。 SPL ルーチンからカーソル関数を実行するには、SPL ルーチンの FOREACH ルー プに関数を含める必要があります。次の例は FOREACH ループの中のカーソル関数 を実行するそれぞれの方法を示します。 FOREACH SELECT cur_func1(col_name) INTO spl_var FROM tab1 INSERT INTO tab2 VALUES (spl_var); END FOREACH FOREACH EXECUTE FUNCTION cur_func2() INTO spl_var INSERT INTO tab2 VALUES (spl_var); END FOREACH 動的ルーチン名の指定 動的ルーチン名指定 の機能を使用すると、呼出しルーチンの範囲内で呼出されるル ーチンの名前を作成することにより、別の SPLルーチンから SPL ルーチンを実行 できます。動的ルーチン名指定の機能は、実行時まで名前がわからない別の SPL ル ーチンを呼び出す SPL ルーチンの記述を簡略化します。データベース サーバでは EXECUTE PROCEDURE 文または EXECUTE FUNCTION 文中の SPL ルーチンの 明示的な名前の代わりに SPL 変数を指定することができます。 図 463 の SPL プロシジャ company_proc は、サイズの大きい全社販売表を更新 します。次に salesperson_proc という名前の SPL 変数を割り当てて、各販売員 の月間販売を含む別の小さい表を更新する SPL プロシジャの動的作成名を保持しま す。 CREATE PROCEDURE company_proc ( no_of_items INT, itm_quantity SMALLINT, sale_amount MONEY, customer VARCHAR(50), sales_person VARCHAR(30) ) DEFINE salesperson_proc VARCHAR(60); -- Update the company table INSERT INTO company_tbl VALUES (no_of_items, itm_quantity, sale_amount, customer, sales_person); -- Generate the procedure name for the variable salesperson_proc LET salesperson_proc = sales_person || "." || "tbl" || current_month || "_" || current_year || "_proc" ; -- Execute the SPL procedure that the salesperson_proc -- variable specifies EXECUTE PROCEDURE salesperson_proc (no_of_items, itm_quantity, sale_amount, customer) END PROCEDURE; 図 463. 図 463 のプロシジャ company _proc は 5 つの引数を受け付けて company_tbl に挿入します。次に、LET 文は、様々な値と連結演算子 || を使用して別の SPL プ ロシジャの名前を生成して実行します。 LET 文では、 v sales_person は、プロシジャ company_proc に渡される引数です。 v current_month は、システム日付の今月です。 第 11 章 SPL ルーチンの作成と使用 319 v current_year は、システム日付の今年です。 そのため、Bill という名前の販売員の 1998 年 7 月の販売の記録は、 company_proc が company_tbl に挿入して、各販売員の月間販売を含む小さい表 を更新する SPL プロシジャ bill.tbl07_1998_proc を実行します。 動的ルーチン名指定のルール 動的に実行される SPL ルーチンの名前を 文字 (CHAR) 型、可変長文字 (VARCHAR) 型、各国語文字 (NCHAR) 型、または 各国語可変長文字 (NVARCHAR) 型として保持する SPL 変数を定義する必要があります。また、SPL 変数に有効な非 NULL の名前を与える必要があります。 動的ルーチン名指定の機能が識別する SPL ルーチンは、実行される前に存在してい る必要があります。 SPL 変数に、有効な SPL ルーチン名を代入すると、 EXECUTE PROCEDURE 文、または EXECUTE FUNCTION 文は、同じ名前の組込 み関数が存在する場合でも、変数に含まれる名前のルーチンを実行します。 EXECUTE PROCEDURE 文または EXECUTE FUNCTION 文に 2 つの SPL 変数 を使用して owner.routine_name のような形の変数名を作成することはできません。 ただし、例えば bill.proc1 のような完全修飾ルーチン名を含む SPL 変数を使用する ことはできます。図 464 で両方の場合を説明します。 EXECUTE PROCEDURE owner_variable.proc_variable -- this is not allowed ; LET proc1 = bill.proc1; EXECUTE PROCEDURE proc1 -- this is allowed ; 図 464. ルーチンのアクセス権 アクセス権は、ルーチンを作成できるユーザと、ルーチンを実行できるユーザを区 別します。アクセス権によっては別のアクセス権の一部として生じるものもありま す。例えば、DBA アクセス権には、ルーチンを作成し、ルーチンを実行する権限、 およびそのアクセス権を他のユーザに付与する権限が含まれます。 ルーチンを登録する権限 ルーチンをデータベースに登録するには、許可されたユーザが CREATE CREATE FUNCTION 文または CREATE PROCEDURE 文の中の SPL コマンドをラップしま す。データベース サーバにより、登録された SPL ルーチンが内部に格納されま す。次のユーザは新しいルーチンをデータベースに登録する資格があります。 v DBA アクセス権を持つすべてのユーザは、CREATE 文の中にキーワード DBA があってもなくてもルーチンを登録することができます。 DBA キーワードの説明については、323 ページの『ルーチンを実行するための DBA アクセス権』を参照してください。 320 IBM Informix: SQL ガイド: チュートリアル v DBA アクセス権を持たないユーザが SPL ルーチンを登録するには Resource ア クセス権が必要です。ルーチンの作成者はその所有者になります。 DBA アクセス権を持たないユーザは、キーワード DBA を使用してルーチンを 登録することはできません。 DBA は、ルーチンの作成に必要な Resource アクセス権を他のユーザに与える必 要があります。 また DBA は Resource アクセス権を取り消すことにより、取り 消されたユーザがさらにルーチンを作成することを防止することができます。 DBA およびルーチンの所有者は DROP FUNCTION 文または DROP PROCEDURE 文により登録をキャンセルできます。 ルーチンを実行する権限 Execute アクセス権によりユーザはルーチンを起動できるようになります。 EXECUTE 文または CALL 文により、あるいは式の中で関数を使用することにより ルーチンを起動できます。次のユーザはデフォルトの Execute アクセス権を持ち、 ルーチンを起動できます。 v デフォルトでは、DBA アクセス権を持つあらゆるユーザがデータベース内のあら ゆるルーチンを実行できます。 v ルーチンが修飾のある CREATE DBA FUNCTION または CREATE DBA PROCEDURE 文で登録される場合は、 DBA アクセス権を持つユーザだけがその ルーチンに対してデフォルトの Execute アクセス権を持ちます。 v データベースが ANSI 標準準拠でない場合は、ユーザ public (Connect データベ ース アクセス権を持つユーザ) はキーワード DBA で登録されていないルーチン への Execute アクセス権を自動的に持ちます。 米国規格協会 (ANSI) v ANSI 標準準拠のデータベースでは、プロシジャの所有者および DBA アクセス 権を持つユーザは追加のアクセス権を受け取らなくてもルーチンを実行できま す。 米国規格協会 (ANSI) の終り Execute アクセス権の付与と取消し ルーチンの、GRANT および REVOKE 要件は、以下の通りです。 v DBA は、データベース内のあらゆるルーチンに Execute アクセス権を付与また は取り消すことができます。 v ルーチンの作成者は、その特定のルーチンの Execute アクセス権を付与または取 り消すことができます。作成者は AS grantor 節を GRANT EXECUTE ON 文に 含めることにより、付与または取消しの能力を失います。 v 所有者 が GRANT EXECUTE ON 文の中にキーワード WITH GRANT を適用す ると、別のユーザは Execute アクセス権を付与できます。 DBA またはルーチンの所有者は、次の条件において、Execute アクセス権を DBA でないユーザに対して明示的に付与する必要があります。 v ANSI 標準準拠データベース内のルーチン 第 11 章 SPL ルーチンの作成と使用 321 v yes に設定された環境変数 NODEFDAC を持つデータベース v DBA キーワードで作成されたルーチン データベース サーバによりデフォルトでパブリックにアクセス権が付与された場合 でも、所有者はルーチンの Execute アクセス権を制限できます。そのためには、 REVOKE EXECUTION ON. PUBLIC 文を発行します。それでも DBA および所有 者は、なおルーチンを実行することが可能であり、該当する特定のユーザに Execute アクセス権を付与できます。 COMMUTATOR 関数と NEGATOR 関数をともなう Execute アク セス権 (IDS のみ) 重要: COMMUTATOR 修飾子または NEGATOR 修飾子とともに作成した SPL 関 数の Execute アクセス権を明示的に付与する必要がある場合は、被権限授与 者が COMMUNICATOR 修飾子または NEGATOR 修飾子のどちらかを使用 する前にその Execute アクセス権を明示的に付与することも必要です。 COMMUTATOR 修飾子または NEGATOR 修飾子は、SPL プロシジャでは指 定できません。 次の例では、関数についてのアクセス権の制限と 1 つのユーザ グループに対する その否定素子の両方を示しています。次のような否定素子関数のペアを作成すると 仮定します。 CREATE FUNCTION greater(y PERCENT, z PERCENT) RETURNS BOOLEAN NEGATOR= less(y PERCENT, z PERCENT) . . . CREATE FUNCTION less(y PERCENT, z PERCENT) RETURNS BOOLEAN NEGATOR= greater(y PERCENT, z PERCENT) デフォルトでは、あらゆるユーザが関数と否定素子の両方を実行できます。次の文 は、accounting のみが、これらの関数を実行できるよう許可します。 REVOKE EXECUTE ON greater FROM PUBLIC REVOKE EXECUTE ON less FROM PUBLIC GRANT ROLE accounting TO mary, jim, ted GRANT EXECUTE ON greater TO accounting GRANT EXECUTE ON less TO accounting ユーザは、他のユーザに Execute アクセス権を付与するための WITH GRANT オプ ションの許可をともなう Execute アクセス権を受け取ることがあります。ユーザが ルーチンの Execute アクセス権を失った場合には、そのユーザから Execute アクセ ス権を付与されたすべてのユーザからも Execute アクセス権が取り消されます。 詳細については、「IBM Informix: SQL ガイド: 構文」の GRANT 文および REVOKE 文の説明を参照してください。 ルーチンに関連付けられたオブジェクトのアクセス権 データベース サーバはあらゆる被参照側オブジェクトの存在をチェックして、ルー チンを起動しているユーザが被参照側オブジェクトにアクセスするのに必要なアク セス権を持っているかどうかを検証します。例えば、ユーザが表の中のデータを更 新するルーチンを実行する場合は、ユーザはルーチンの中で参照される表または列 の更新アクセス権を持つ必要があります。 322 IBM Informix: SQL ガイド: チュートリアル ルーチンにより参照されるオブジェクトには次のものがあります。 v 表と列 v ユーザ定義 (user-defined) 型 v ルーチンにより実行される他のルーチン ルーチンの所有者が Execute アクセス権を付与する場合は、オブジェクトのアクセ ス権には自動的に Execute アクセス権がともないます。GRANT EXECUTE ON 文 は、キーワード WITH GRANT を含む GRANT 文から権限授与者が受け取るあら ゆる表レベルのアクセス権を被権限授与者に付与します。 ルーチンの所有者は、ルーチンの実行中に作成される修飾のないオブジェクトを所 有しますが、ルーチンを実行するユーザは所有しません。例えば、ユーザ howie が、次の SPL ルーチンにより、2 つの表を作成する SPL ルーチンを登録すると仮 定します。 CREATE PROCEDURE promo() . . . CREATE TABLE newcatalog ( catlog_num INTEGER cat_advert VARCHAR(255, 65) cat_picture BLOB ) ; CREATE TABLE dawn.mailers ( cust_num INTEGER interested_in SET(catlog_num INTEGER) ); END PROCEDURE; ユーザ julia は、表 newcatalog を作成するルーチンを実行します。表の名前 newcatalog を修飾する所有者名がないため、ルーチンの所有者 (howie) が newcatalog を所有します。対照的に、修飾のある名前 dawn.maillist は dawn を maillist の所有者として識別します。 ルーチンを実行するための DBA アクセス権 DBA がキーワード DBA を使用してルーチンを作成すると、データベース サーバ は DBA アクセス権を持つ他のユーザのみに、Execute アクセス権を自動的に付与 します。ただし DBA は、DBA ルーチンの Execute アクセス権を DBA アクセス 権を持たないユーザに対して明示的に付与することもできます。 キーワード DBA で登録されたルーチンをユーザが実行する場合、ユーザはルーチ ンの継続期間中は DBA のアクセス権を所有します。 DBA アクセス権を持たない ユーザが DBA ルーチンを実行する場合は、データベース サーバが一時的な DBA アクセス権を起動者に暗黙的に付与します。 DBA ルーチンを終了する前に、デー タベース サーバは一時的な DBA アクセス権を暗黙的に取り消します。 DBA ルーチンの実行中に作成されたオブジェクトは、ルーチンの文が所有者として 他のユーザを明示的に指定しない限り、ルーチンを実行するユーザが所有します。 例えば、tony がキーワード DBA により、次のようにルーチン promo() を登録す ると仮定します。 第 11 章 SPL ルーチンの作成と使用 323 CREATE DBA PROCEDURE promo() . . . CREATE TABLE catalog . . . CREATE TABLE libby.mailers . . . END PROCEDURE; tony がルーチンを所有しているにもかかわらず、marty がルーチンを実行した場 合は、marty が表 catalog を所有します。ただし、ユーザ libby の名前が表の名 前を修飾するため libby が表の所有者になって libby.mailers を所有します。 呼び出されたルーチンは DBA アクセス権を継承しません。 DBA ルーチンが、キ ーワード DBA なしで作成されたルーチンを実行する場合、DBA アクセス権は呼び 出されたルーチンには影響しません。 キーワード DBA なしで登録されたルーチンが DBA ルーチンを呼び出す場合は、 呼出す DBA ルーチンの Execute アクセス権を所有している必要があります。 DBA ルーチン内の文は、いかなる DBA ルーチン内でも同じように実行されます。 次の例は DBA ルーチンと DBA でないルーチンが相互に作用するとき何が起きる かを示します。プロシジャ dbspc_cleanup() が別のプロシジャ clust_catalog() を実行すると仮定します。また、プロシジャ clust_catalog() がインデックスを作 成し、clust_catalog() 用の SPL ソース コードに次の文が含まれると仮定します。 CREATE CLUSTER INDEX c_clust_ix ON catalog (catalog_num); DBA プロシジャ dbspc_cleanup() は、次の文を使用して他のルーチンを呼び出し ます。 EXECUTE PROCEDURE clust_catalog(catalog) tony は dbspc_cleanup() を DBA プロシジャとして登録し、clust_catalog() は 次の文に示すようにキーワード DBA なしで登録されると仮定します。 CREATE DBA PROCEDURE dbspc_cleanup(loc CHAR) CREATE PROCEDURE clust_catalog(catalog CHAR) GRANT EXECUTION ON dbspc_cleanup(CHAR) to marty; ユーザ marty は dbspc_cleanup() を実行すると仮定します。インデックス c_clust_ix は、DBA でないルーチンによって作成されるため、両方のルーチンを 所有する tony は c_clust_ix も所有します。対照的に、次の登録文と付与文が示 すように clust_catalog() が DBA プロシジャである場合、marty はインデックス c_clust_ix を所有します。 CREATE PROCEDURE dbspc_cleanup(loc CHAR) CREATE DBA PROCEDURE clust_catalog(catalog CHAR) GRANT EXECUTION ON clust_catalog(CHAR) to marty; dbspc_cleanup() は DBA プロシジャを呼び出すためのDBA プロシジャである必 要はないことに注意してください。 SPL ルーチンのエラー検出 DB–Access で SPL ルーチンを記述するのに CREATE PROCEDURE 文または CREATE FUNCTION 文を使用する場合、メニューから「Run」を選択し、構文エ ラーがルーチン本体で発生すると、文は失敗します。 324 IBM Informix: SQL ガイド: チュートリアル DB–Access でルーチンを作成しているときにメニューから「Modify」オプションを 選択すると、カーソルは構文エラーを含む行に移動します。「Run」と「Modify」 を再度選択すると次の行をチェックできます。 コンパイル時の警告の表示 データベース サーバにより問題の可能性を検出されたにも関わらず、SPL ルーチン の構文が正しい場合は、警告が生成されリスト ファイルに入ります。このファイル を調べるとルーチンを実行する前に可能性がある問題をチェックできます。 リスト ファイルのファイル名とパス名は、CREATE PROCEDURE 文または CREATE FUNCTION 文の WITH LISTING IN 節で指定します。リスト ファイル のパス名の指定方法の詳細については、270 ページの『DOCUMENT 節の指定』を 参照してください。 ネットワーク上で作業している場合は、リスト ファイルはデータベースが常駐する システム上に作成されます。ファイルの絶対パス名とファイル名を入力すると、指 定した場所にファイルが作成されます。 UNIX のみ リスト ファイルの相対パス名を入力した場合は、ファイルはデータベースが常駐す るコンピュータのホーム ディレクトリに作成されます。 (ホーム ディレクトリが ない場合、ファイルはルート ディレクトリに作成されます。) UNIX のみ の終り Windows のみ リスト ファイルの相対パス名を入力したときに、データベースがローカル コンピ ュータ上にある場合は、デフォルトのディレクトリは現在の作業ディレクトリにな ります。それ以外の場合は、%INFORMIXDIR%¥bin がデフォルトのディレクトリ になります。 Windows のみ の終り ルーチンを作成した後では、WITH LISTING IN 節で指定したファイルを表示し て、含まれている警告を見ることができます。 ルーチンのテキストの生成 SPL ルーチンは、作成後にシステム カタログ表 sysprocbody に格納されます。 sysprocbody システム カタログ表には、実行可能ルーチンとそのテキストが含ま れます。 ルーチンのテキストを抽出するには、システム カタログ表 sysprocbody から列 data を選択します。テキスト エントリの列 datakey はコード T を持ちます。 図 465 の SELECT 文は、SPL ルーチン read_address のテキストを読み込みま す。 第 11 章 SPL ルーチンの作成と使用 325 SELECT data FROM informix.sysprocbody WHERE datakey = ’T’ -- find text lines AND procid = ( SELECT procid FROM informix.sysprocedures WHERE informix.sysprocedures.procname = ’read_address’ ) 図 465. SPL ルーチンのデバッグ SPL ルーチンを正常に作成および実行した後に、論理エラーが発生することがあり ます。ルーチンに論理エラーがある場合は、TRACE 文を使用するとエラーの検出に 役立ちます。次の項目の値をトレースできます。 v 変数 v 引数 v 戻り値 v SQL エラー コード v ISAM エラー コード トレースした値のリストを生成するには、最初に SQL 文 SET DEBUG FILE を使 用してトレースされた出力を含むファイルに名前を付けます。 SPL ルーチンを作成 する場合は、TRACE 文を含めます。 次の方法で TRACE 出力のフォームを指定します。 文 アクション TRACE ON SQL 文を除くすべての文をトレースします。使用す る前に変数の内容を印刷します。ルーチン呼出しと 戻り値をトレースします。 TRACE PROCEDURE ルーチン呼出しと戻り値のみをトレースします。 TRACE 式 リテラルまたは式を印刷します。必要な場合は、フ ァイルに送る前に式の値が計算されます。 図 466 では、 TRACE 文を使用して SPL 関数の実行を監視する方法を示します。 326 IBM Informix: SQL ガイド: チュートリアル CREATE FUNCTION read_many (lastname CHAR(15)) RETURNING CHAR(15), CHAR(15), CHAR(20), CHAR(15), CHAR(2), CHAR(5); DEFINE DEFINE DEFINE DEFINE DEFINE p_lname,p_fname, p_city CHAR(15); p_add CHAR(20); p_state CHAR(2); p_zip CHAR(5); lcount, i INT; LET lcount = 1; TRACE ON; -- Trace every expression from here on TRACE ’Foreach starts’; -- Trace statement with a literal FOREACH SELECT fname, lname, address1, city, state, zipcode INTO p_fname, p_lname, p_add, p_city, p_state, p_zip FROM customer WHERE lname = lastname RETURN p_fname, p_lname, p_add, p_city, p_state, p_zip WITH RESUME; LET lcount = lcount + 1; -- count of returned addresses END FOREACH TRACE ’Loop starts’; -- Another literal FOR i IN (1 TO 5) BEGIN RETURN i , i+1, i*i, i/i, i-1,i WITH RESUME; END END FOR; END FUNCTION; 図 466. TRACE ON 文により、トレースするルーチンを実行するたびに、SET DEBUG FILE 文により指定したファイルにエントリが追加されます。デバッグ エントリを 参照するには、任意のテキスト エディタで出力ファイルを表示します。 次のリストには、図 466 の関数が生成する出力のいくつかが含まれます。各トレー ス文の次には、内容の説明があります。 文 アクション TRACE ON TRACE ON 文へエコーイングします。 TRACE Foreach starts 式、この場合、リテラル文字列 Foreach Start をト レースします。 start select cursor FOREACH ループを処理するためにカーソルがオー プンされていることを通知します。 select cursor iteration 選択したカーソルの各反復の起動を通知します。 expression: (+lcount, 1) 検出した式、(lcount+1) を評価して 2 を出力しま す。 let lcount = 2 各 LET 文を値とともにエコーイングします。 第 11 章 SPL ルーチンの作成と使用 327 例外処理 ON EXCEPTION 文を使用して、データベース サーバにより SPL ルーチンに戻さ れるあらゆる例外 (またはエラー)、またはルーチンにより生成されるあらゆる例外 をトラップできます。 RAISE EXCEPTION 文を使用すると SPL ルーチン内に例外 を生成できます。 SPL ルーチンでは、次の条件を処理する例外処理を使用することはできません。 v 正常終了 (戻り行あり) v 正常終了 (戻り行なし) エラー トラッピングと復旧 ON EXCEPTION 文は、あらゆるエラーをトラップするメカニズムを提供します。 エラーをトラップするには、文のグループを BEGIN 文と END 文でマークされた 文ブロックで囲み ON EXCEPTION IN 文を文ブロックの始めに追加します。 ON EXCEPTION 文に後続するブロックでエラーが発生する場合は、復旧アクションを 実行することができます。 図 467 に、文ブロック内の ON EXCEPTION 文を示します。 BEGIN DEFINE c INT; ON EXCEPTION IN ( -206, -- table does not exist -217 -- column does not exist ) SET err_num IF err_num = -206 THEN CREATE TABLE t (c INT); INSERT INTO t VALUES (10); -- continue after the insert statement ELSE ALTER TABLE t ADD(d INT); LET c = (SELECT d FROM t); -- continue after the select statement. END IF END EXCEPTION WITH RESUME INSERT INTO t VALUES (10); -- fails if t does not exist LET c = (SELECT d FROM t); END -- fails if d does not exist 図 467. エラーが発生すると、SPL インタープリタは、エラーをトラップする最も内側の ON EXCEPTION 宣言を検索します。エラー トラッピング後に行う最初のアクショ ンはエラーのリセットです。エラー アクション コードの実行が完了し、生成され た ON EXCEPTION 宣言にキーワード WITH RESUME が含まれていた場合は、エ ラーを生成した文に後続する 文から自動的に実行が再開されます。 ON EXCEPTION 宣言にキーワード WITH RESUME が含まれていなかった場合には、 実行は現在のブロックで完全に終了します。 328 IBM Informix: SQL ガイド: チュートリアル ON EXCEPTION 文の制御の有効範囲 ON EXCEPTION 文が有効な文ブロックは、 ON EXCEPTION 文、続く文ブロック の範囲内で入れ子になっているすべての文ブロック、および ON EXCEPTION 文に 後続するすべての文ブロックに後続する文ブロックです。 ON EXCEPTION 文を含 む文ブロックでは有効ではありません。 図 468 の疑似コードは、ルーチンの範囲内で例外が有効な場所を示します。つま り、エラー 201 が、指定されたブロックの 1 つで発生した場合は、a201 というラ ベルのアクションが発生します。 CREATE PROCEDURE scope() DEFINE i INT; . . . BEGIN -- begin statement block A . . . ON EXCEPTION IN (201) -- do action a201 END EXCEPTION BEGIN -- statement block aa -- do action, a201 valid here END BEGIN -- statement block bb -- do action, a201 valid here END WHILE i < 10 -- do something, a201 is valid here END WHILE END BEGIN -- begin statement block B -- do something -- a201 is NOT valid here END END PROCEDURE; 図 468. ユーザが生成する例外 図 469 に示すように、RAISE EXCEPTION 文を使用して独自のエラーを生成するこ とができます。 BEGIN ON EXCEPTION SET esql, eisam -- trap all errors IF esql = -206 THEN -- table not found -- recover somehow ELSE RAISE exception esql, eisam; -- pass the error up END IF END EXCEPTION -- do something END 図 469. 第 11 章 SPL ルーチンの作成と使用 329 図 469 では、ON EXCEPTION 文が 2 つの変数 esql および eisam を使用してデ ータベース サーバが戻すエラー番号を保持します。 IF 節は、エラーが発生し、 SQL エラー番号が -206 である場合に実行されます。その他の SQL エラーが検出 されると、この BEGIN END ブロックから、前述の例の最後の BEGINEND ブロッ クに渡されます。 SQL エラーのシミュレート 図 470 に示すように、SQL エラーを生成してシミュレートすることができます。ユ ーザが pault である場合には、ユーザが実際には更新アクセス権を持っている場合 であっても SPL ルーチンは、ユーザがそのアクセス権を持っていないかのように動 作します。 BEGIN IF user = ’pault’ THEN RAISE EXCEPTION -273; END IF END -- deny Paul update privilege 図 470. 入れ子コードを終了する RAISE EXCEPTION の使用 図 471 では、RAISE EXCEPTION 文を使用して深い入れ子ブロックを終了して外に 出る方法を示します。 BEGIN ON EXCEPTION IN (1) END EXCEPTION WITH RESUME -- do nothing significant (cont) BEGIN FOR i IN (1 TO 1000) FOREACH select ..INTO aa FROM t IF aa < 0 THEN RAISE EXCEPTION 1; -- emergency exit END IF END FOREACH END FOR RETURN 1; END --do something; -- emergency exit to -- this statement. TRACE ’Negative value returned’; RETURN -10; END 図 471. 最も内側の条件が TRUE (aa が負の場合) の場合には、例外が発生して実行はブロ ックの END 文に後続するコードにジャンプします。この場合、例外は TRACE 文 にジャンプします。 330 IBM Informix: SQL ガイド: チュートリアル BEGINEND ブロックが単一 文であることに注意してください。ブロック内部のど こかでエラーが発生し、トラップがブロックの外にある場合は、実行が再開された ときブロックの残りはスキップされ、次の文から実行が始まります。 このエラーに対してブロック内のどこかにトラップを設定しない場合には、エラー 条件は呼出しを含むあらゆるブロック、およびそのブロックを含むあらゆるブロッ クに戻されます。エラーを処理するように設定された ON EXCEPTION 文が存在し ない場合は、SPL ルーチンの実行は停止し、SPL ルーチンを実行しているルーチン のエラーが作成されます。 SPL ルーチンで処理される行数のチェック SPL 内で DBINFO 関数を使用し、 SELECT、 INSERT、 UPDATE、 DELETE、 EXECUTE PROCEDURE、および EXECUTE FUNCTION 文で処理された行数を検 出できます。 図 472 では、オプション ’sqlca.sqlerrd2’ とともに DBINFO 関数を使用して、表か ら削除される行数を判断する SPL 関数を示します。 CREATE FUNCTION del_rows ( pnumb INT ) RETURNING INT; DEFINE nrows INT; DELETE FROM sec_tab WHERE part_num = pnumb; LET nrows = DBINFO(’sqlca.sqlerrd2’); RETURN nrows; END FUNCTION; 図 472. 有効な結果を確保するために、SELECT 文と EXECUTE PROCEDURE 文、または EXECUTE FUNCTION 文が完了した後で、このオプションを使用します。また、オ プション ’sqlca.sqlerrd2’ をカーソル内で使用する場合は、有効な結果を確保するた めにカーソルがクローズする前にすべての行を取り出す必要があります。 サマリ SPL ルーチンは、データベースのパフォーマンスの向上、アプリケーションの簡略 化、およびデータ アクセスの制限または監視など、データベース処理を能率化する 多くの可能性を提供します。また、SPL ルーチンを使用してコレクション (COLLECTION) 型、行 (ROW) 型、不透明 (OPAQUE) 型、およびディスティンク ト (DISTINCT) 型などの拡張 (extended) 型を扱うことができます。 SPL 文の構文 ダイヤグラムは、「IBM Informix: SQL ガイド: 構文」に記載されています。 第 11 章 SPL ルーチンの作成と使用 331 332 IBM Informix: SQL ガイド: チュートリアル 第 12 章 トリガの作成と使用 トリガを使用するタイミング . . . . . . . . . . . . . トリガの作成方法 . . . . . . . . . . . . . . . . . トリガ名の割当て . . . . . . . . . . . . . . . . トリガ イベントの指定 . . . . . . . . . . . . . . トリガ アクションの定義 . . . . . . . . . . . . . 完全な構成の CREATE TRIGGER 文 . . . . . . . . . トリガ アクションの使用方法 . . . . . . . . . . . . . BEFORE および AFTER トリガ アクションの使用方法 . . . FOR EACH ROW トリガ アクションの使用方法 . . . . . REFERENCING 節の使用方法 . . . . . . . . . . . WHEN 条件の使用方法 . . . . . . . . . . . . . トリガ アクションとしての SPL ルーチンの使用方法 . . . . SPL ルーチンへのデータ引き渡し . . . . . . . . . SPL の使用 . . . . . . . . . . . . . . . . . SPL ルーチンからのデータによる非トリガ列の更新 . . . 表階層のトリガ (IDS のみ) . . . . . . . . . . . . . . 選択トリガの使用 (IDS のみ) . . . . . . . . . . . . . トリガ アクションを実行する SELECT 文 . . . . . . . スタンドアロン SELECT 文 . . . . . . . . . . . SELECT 文の選択リストにあるコレクション (COLLECTION) ユーザ定義ルーチンに埋め込まれた SELECT 文. . . . . ビュー. . . . . . . . . . . . . . . . . . . 選択トリガの実行についての制限. . . . . . . . . . . 表階層の表に対する選択トリガ . . . . . . . . . . . リエントラント トリガ . . . . . . . . . . . . . . . ビューの INSTEAD OF トリガ (IDS のみ) . . . . . . . . INSTEAD OF トリガを使用してビュー上で更新 . . . . . . トリガ アクションのトレース . . . . . . . . . . . . . SPL ルーチン内の TRACE 文の例 . . . . . . . . . . TRACE 出力の例 . . . . . . . . . . . . . . . . エラー メッセージの生成 . . . . . . . . . . . . . . 固定エラー メッセージの適用 . . . . . . . . . . . . 可変エラー メッセージの生成 . . . . . . . . . . . . サマリ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 型副問合せ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 334 335 335 336 336 337 337 338 338 339 339 340 340 340 340 341 341 341 341 341 342 342 342 342 343 343 344 344 344 345 345 346 347 本章について この章では、CREATE TRIGGER 文の各コンポーネントの目的を説明し、トリガの 使い方をいくつか紹介します。また、SPL ルーチンをトリガ アクションとして使用 する利点についても説明します。 Dynamic Server さらに、ビューで使用される INSTEAD OF トリガについても説明します。 Dynamic Server の終り SQL トリガは、データベースに常駐する機構です。使用許可さえ受けていれば、ど のようなユーザでも使用することができます。 SQL トリガは、特定の表に対して © Copyright IBM Corp. 1996, 2003 333 挿入、選択、削除、更新などの特定の操作を行う場合に、データベース サーバが自 動的に 1 つ以上の追加操作を実行するように指定します。追加のアクションは、 INSERT 文、DELETE 文、 UPDATE 文、EXECUTE PROCEDURE 文、または EXECUTE FUNCTION 文です。 Dynamic Server Dynamic Server はまた、C 言語または Java で作成されたユーザ定義ルーチンもト リガ アクションとしてサポートします。 Dynamic Server の終り トリガを使用するタイミング トリガはデータベース内に存在し、必要なアクセス権を持つユーザは誰でも使用で きるため、トリガを使用して、複数のアプリケーションで使用可能な一連の SQL 文を書くことができます。トリガを使えば、複数のプログラムが同じデータベース 操作を実行する必要がある場合に、コードが冗長になりません。 トリガを使用して、以下に示すアクションを実行できます。また、このリスト以外 のアクションを実行することもできます。 v データベースでの動作更新記録の作成。例えば、監査表に対する確認情報を更新 することによって、表 orders に対する更新を追跡することができます。 v ビジネス ルールの実現。例えばオーダーが顧客の信用限度を超える条件を決め て、それに応じたメッセージを表示することができます。 v 表やデータベース内で使用できない補助データの導出。例えば表 items の列 quantity が更新されると、それに応じて列 total_price を再計算できます。 v 参照整合性の確保。例えば、ある顧客を削除するときに、トリガを使用して表 orders 内の対応する行 (同じ顧客番号を持つ行) を削除することができます。 トリガの作成方法 トリガの作成には CREATE TRIGGER 文を使用します。 CREATE TRIGGER 文 は、 SQL 文を表内の促進的アクションと共用するデータ定義文です。促進的アク ションが発生すると、それによりデータベースに格納された関連する SQL 文がト リガされます。図 473 は、促進的アクションまたはトリガ イベントのトリガ アク ションとの関係を示しています。 334 IBM Informix: SQL ガイド: チュートリアル 図 473. トリガ イベントとトリガ アクション CREATE TRIGGER 文は、以下のアクションを実行する節で構成されます。 v トリガ名の割当て v トリガ イベント、つまり、表とトリガを開始するアクションの型の指定 v トリガされる SQL アクションの定義 オプションの節 REFERENCING 節は、338 ページの『FOR EACH ROW トリガ アクションの使用方法』で説明されています。 トリガを作成するには、DB–Access または SQL API のうち 1 つを使用します。こ の章では、DB–Access の問合せ言語オプションを使用して入力した、 CREATE TRIGGER 文について説明します。 SQL API では、文 (その文を組込みステートメ ントとして識別する記号またはキーワードを含む) を先行させます。 トリガ名の割当て トリガは、トリガ名によって識別されます。これはデータベース内で固有である必 要があります。トリガ名は文中の文字列 CREATE TRIGGER に続きます。トリガ名 の長さは最高 18 バイトで、先頭が文字、その後は文字と 0 から 9 までの数字と 下線で構成することができます。次の例の CREATE TRIGGER 文では、トリガに upqty という名前を割り当てています。 CREATE TRIGGER upqty -- assign trigger name トリガ イベントの指定 トリガ イベント は、トリガを起動する文のタイプです。このタイプの文が表に対 して実行されると、データベース サーバは、トリガ アクションを構成する SQL 文を実行します。トリガ イベントには、INSERT、SELECT、DELETE、または UPDATE 文が含まれます。UPDATE または SELECT トリガ イベントを定義する 場合は、表内の複数の列を指定してトリガをアクティブにできます。列名を指定し ない場合は、表のどの列が更新または SELECT されてもトリガが起動されます。各 表あたり 1 つの INSERT および DELETE トリガーのみ作成できますが、トリガす る列が相互に排他的である限り、複数の UPDATE または SELECT トリガを作成で きます。 現行のデータベース内の表にのみ、トリガを作成できます。トリガはリモート表を 参照できません。 第 12 章 トリガの作成と使用 335 次の CREATE TRIGGER 文の例では、表 items の列 quantity の更新動作とし て、トリガ イベントが定義されています。 CREATE TRIGGER upqty UPDATE OF quantity ON items -- an UPDATE trigger event 文のこの部分は、トリガを作成する表を特定しています。トリガ イベントが挿入ま たは削除の場合、次の例に示すように、このタイプの文と表名のみが必要になりま す。 CREATE TRIGGER ins_qty INSERT ON items -- an INSERT trigger event トリガ アクションの定義 トリガ アクション は、トリガ イベントが発生するときに実行される SQL 文で す。トリガ アクションには、INSERT、DELETE、UPDATE、および EXECUTE PROCEDURE 文が含まれます。ただし、実行するアクションを指定するだけでな く、トリガ文を基準にして実行するタイミング も指定する必要があります。このタ イミングは次のいずれかです。 v トリガ文の実行前 v トリガ文の実行後 v トリガ文の影響を受けるそれぞれの行ごと 1 つのトリガで、このようなそれぞれのタイミングに対して、実行する処理を定義 することができます。 トリガ アクションを定義するには、発生するタイミングと、実行する SQL 文を指 定します。キーワード BEFORE、AFTER、または FOR EACH ROW を使用するア クションを実行するタイミングを指定します。その後にトリガ アクションを置き、 括弧で囲みます。次のトリガ アクション定義は、SPL ルーチン upd_items_p1 が トリガ文の前に実行されることを指定します。 BEFORE(EXECUTE PROCEDURE upd_items_p1) -- a BEFORE action 完全な構成の CREATE TRIGGER 文 完全な CREATE TRIGGER 文を定義するには、トリガ名節、トリガ イベント節、 およびトリガ アクション節を結合します。次の CREATE TRIGGER 文は、上記の 例の文のコンポーネントを結合したものです。このトリガは、表 items の列 quantity が更新されると必ず、SPL ルーチン upd_items_p1 を実行します。 CREATE TRIGGER upqty UPDATE OF quantity ON items BEFORE(EXECUTE PROCEDURE upd_items_p1) データベース サーバが CREATE TRIGGER 文を処理するときに、例えば、この例 の SPL ルーチン upd_items_p1 などのトリガ定義内のデータベース オブジェク トが存在しない場合、データベース サーバはエラーを戻します。 336 IBM Informix: SQL ガイド: チュートリアル トリガ アクションの使用方法 トリガを効果的に使用するには、トリガ文とそれによって引き起こされるトリガ ア クションの関係を理解する必要があります。トリガ アクションを発生させるタイミ ング、つまり BEFORE、AFTER、および FOR EACH ROW のいずれかを指定する ときに、この関係を定義してください。 BEFORE および AFTER トリガ アクションの使用方法 トリガ イベントの前または後に起こるトリガ アクションは、1 回のみ実行されま す。 BEFORE トリガ アクションは、トリガ文 の前、つまり、トリガ イベントの 発生前に実行します。AFTER トリガ アクションは、トリガ文のアクションの完了 後に実行されます。また、BEFORE トリガ アクションと AFTER トリガ アクショ ンは、トリガ文によって行が処理されない場合も実行されます。 さまざまな使用方法がありますが、特に、トリガ文の影響を調べるために、 BEFORE トリガ アクションと AFTER トリガ アクションを使用することができま す。例えば、次の例に示すように、表 items の列 quantity を更新する前に、SPL ルーチン upd_items_p1 を呼び出して、表内のすべての品目に対するオーダーの合 計数量を計算することができます。このプロシジャは、old_qty と呼ばれる広域変 数に合計数量を格納します。 CREATE PROCEDURE upd_items_p1() DEFINE GLOBAL old_qty INT DEFAULT 0; LET old_qty = (SELECT SUM(quantity) FROM items); END PROCEDURE; トリガ更新の終了後、再び合計数量を計算してどのくらい変化したかを調べること ができます。次の SPL ルーチン upd_items_p2 は、 quantityの合計を再計算 し、その結果を局所変数 new_qty に格納します。次に、new_qty と広域変数 old_qty を比較して、全オーダーの合計数量が 50% 以上増加しているかどうかを 調べます。増加している場合、プロシジャは RAISE EXCEPTION 文を使用して、 SQL エラーをシミュレートします。 CREATE PROCEDURE upd_items_p2() DEFINE GLOBAL old_qty INT DEFAULT 0; DEFINE new_qty INT; LET new_qty = (SELECT SUM(quantity) FROM items); IF new_qty > old_qty * 1.50 THEN RAISE EXCEPTION -746, 0, ’Not allowed - rule violation’; END IF END PROCEDURE; 次のトリガは、upd_items_p1 と upd_items_p2 を呼び出して、表 items の列 quantity に異常な更新が行われないようにします。 CREATE TRIGGER up_items UPDATE OF quantity ON items BEFORE(EXECUTE PROCEDURE upd_items_p1()) AFTER(EXECUTE PROCEDURE upd_items_p2()); 更新によって全品目に対するオーダーの合計数量が 50% 以上増加すると、 upd_items_p2 の RAISE EXCEPTION 文によってトリガが終了し、エラーになり ます。トリガがデータベース サーバで失敗し、データベースにログ機能がある場合 には、データベース サーバは、トリガ文とトリガ アクションの両方によって加え 第 12 章 トリガの作成と使用 337 られた変更をロール バックします。トリガが失敗した場合について、詳しくは、 「IBM Informix: SQL ガイド: 構文」の CREATE TRIGGER 文を参照してくださ い。 FOR EACH ROW トリガ アクションの使用方法 FOR EACH ROW トリガ アクションは、トリガ文が影響を与える各行に対して 1 回ずつ実行されます。例えば、トリガ文が次の構文を持っているとします。FOR EACH ROW トリガ アクションは、列 manu_code が値 ‘KAR’ を持つ表 items の各行に対して 1 回ずつ実行されます。 UPDATE items SET quantity = quantity * 2 WHERE manu_code = ’KAR’ トリガ文によって行が処理されない場合には、 FOR EACH ROW トリガ アクショ ンは実行されません。 トリガ文が SELECT 文の場合、つまりトリガが選択トリガの場合、トリガ アクシ ョンは、抽出行に対するすべての処理が完了した後に実行されます。ただし、トリ ガ アクションはただちに実行されるわけではありません。FOR EACH ROW アク ションは、ユーザに戻す行の実現値ごとに実行されます。例えば、 ORDER BY 節 を含む SELECT 文では、すべての行は、ソートされ戻される前に WHERE 節に対 し修飾されます。 REFERENCING 節の使用方法 FOR EACH ROW トリガ アクションを作成するときは、通常、トリガ文の実行前 または後に列の値を参照するかどうかを、トリガ アクション文で指定する必要があ ります。例えば、表 items の列 quantity に対する更新の記録を追跡すると仮定し ます。この処理を実行するには、次のような表を作成し、動作を記録します。 CREATE TABLE log_record (item_num SMALLINT, ord_num INTEGER, username CHARACTER(8), update_time DATETIME YEAR TO MINUTE, old_qty SMALLINT, new_qty SMALLINT); この表の列 old_qty と列 new_qty の値を指定するには、表 items 内の列 quantity の元の値と新しい値、つまりトリガ文の実行前と実行後の値を参照できな ければなりません。 REFERENCING 節により、この処理が有効になります。 REFERENCING 節では、列名と結合できる 2 つのプレフィックスを作成すること ができます。 1 つは列の元の値の参照用、もう 1 つは列の新しい値の参照用で す。これらのプレフィックスは、関連名 と呼ばれます。これらの関連名は、要求に 応じて、1 つあるいは、両方作成することもできます。キーワード OLD および NEW を使用して作成する関連名を示します。次の REFERENCING 節では、関連名 として pre_upd と post_upd を作成して、行の元の値と新しい値を参照していま す。 REFERENCING OLD AS pre_upd NEW AS post_upd 次のトリガ アクションは、表 items の行で quantity が更新されたときに、 log_record に行を作成します。 INSERT 文は列 item_num と列 order_num の 元の値を参照し、さらに列 quantity の元の値と新しい値を参照します。 338 IBM Informix: SQL ガイド: チュートリアル FOR EACH ROW(INSERT INTO log_record VALUES (pre_upd.item_num, pre_upd.order_num, USER, CURRENT, pre_upd.quantity, post_upd.quantity)); REFERENCING 節で定義される関連名は、トリガ文の影響を受けるすべての行に適 用されます。 重要: トリガ表内の列名を参照する場合に関連名を使用しないと、データベース サ ーバはトリガ表内に定義されたこの列を探索するために特別な動作は行いま せん。文がトリガ アクションにかかわらず有効でない限り、関連名を FOR EACH ROW トリガ アクションの SQL 文中の列名とともに、常に使用する 必要があります。詳しくは、「IBM Informix: SQL ガイド: 構文」の CREATE TRIGGER 文を参照してください。 WHEN 条件の使用方法 オプションとして、トリガ アクションの前に WHEN 節を使用し、テストの結果に 基づくアクションを実行することができます。 WHEN 節は、キーワード WHEN とそれに続く括弧内に示される条件文で構成されます。 CREATE TRIGGER 文で は、 WHEN 節はキーワード BEFORE、AFTER、または FOR EACH ROW の後に 続き、トリガ アクション リストに先行します。 WHEN 条件が存在していて、その条件が TRUE の場合には、トリガ アクション は、指定されたアクションの並びの順に実行されます。 WHEN 条件が FALSE ま たは unknown を評価する場合、トリガ アクション リストのアクションは実行しま せん。トリガにFOR EACH ROWの指定がある場合は、WHEN 条件は行ごとにも評 価されます。 次のトリガの例では、トリガ アクションは WHEN 節の中の条件が TRUE である 場合のみ実行されます。つまり、更新後の単価が更新前の単価の 2 倍を超える場合 に実行されます。 CREATE TRIGGER up_price UPDATE OF unit_price ON stock REFERENCING OLD AS pre NEW AS post FOR EACH ROW WHEN(post.unit_price > pre.unit_price * 2) (INSERT INTO warn_tab VALUES(pre.stock_num, pre.manu_code, pre.unit_price, post.unit_price, CURRENT)) WHEN 条件について、詳しくは、「IBM Informix: SQL ガイド: 構文」の CREATE TRIGGER 文を参照してください。 トリガ アクションとしての SPL ルーチンの使用方法 もっとも有効なトリガの機能は、SPL ルーチンをトリガ アクションとして呼び出せ ることです。 SPL ルーチンを呼び出す EXECUTE PROCEDURE 文は、トリガ表か ら SPL ルーチンへのデータの受け渡しを可能にし、トリガ表を SPL ルーチンから 戻されたデータで更新します。 SPL はまた、変数の定義とそれらに対するデータの 割り当て、比較の作成も可能にします。さらに、プロシジャ ステートメントを使用 したトリガ アクション内の複雑なタスクの実行も可能にします。 第 12 章 トリガの作成と使用 339 SPL ルーチンへのデータ引き渡し データを EXECUTE PROCEDURE 文の引数リスト内の SPL ルーチンに引き渡すこ とができます。以下のトリガ例の EXECUTE PROCEDURE 文は、値を表 items の 列 quantity および total_price から SPL ルーチン calc_totpr に受け渡します。 CREATE TRIGGER upd_totpr UPDATE OF quantity ON items REFERENCING OLD AS pre_upd NEW AS post_upd FOR EACH ROW(EXECUTE PROCEDURE calc_totpr(pre_upd.quantity, post_upd.quantity, pre_upd.total_price) INTO total_price) SPL ルーチンにデータを渡すと、プロシジャが実行する操作の中でそのデータを使 用することができます。 SPL の使用 先行するトリガの EXECUTE PROCEDURE 文は、以下の例に示す SPL ルーチンを 呼び出します。このプロシジャは、表 items の quantity が更新されたときに列 total_price に加える変更を計算するために、SPL を使用します。プロシジャは、 quantity の新旧の値と、total_price の古い値を受け取ります。古い合計金額の値 を古い数量の値で割り、単価を求めます。次に単価に新しい数量を乗算して新しい 合計金額を求めます。 CREATE PROCEDURE calc_totpr(old_qty SMALLINT, new_qty SMALLINT, total MONEY(8)) RETURNING MONEY(8); DEFINE u_price LIKE items.total_price; DEFINE n_total LIKE items.total_price; LET u_price = total / old_qty; LET n_total = new_qty * u_price; RETURN n_total; END PROCEDURE; この例の SPL は、トリガ表から直接取得できないデータをトリガによって導出して います。 SPL ルーチンからのデータによる非トリガ列の更新 トリガ アクション内で、EXECUTE PROCEDURE 文のINTO 節を使用して、トリ ガ表の非トリガ列を更新することができます。以下の例の EXECUTE PROCEDURE 文は、列 total_price を参照する INTO 節を含む、 calc_totpr SPL プロシジャを 呼び出します。 FOR EACH ROW(EXECUTE PROCEDURE calc_totpr(pre_upd.quantity, post_upd.quantity, pre_upd.total_price) INTO total_price); total_price に更新された値は、 SPL プロシジャの結論で RETURN 文により戻さ れます。トリガ文の影響を受ける各行に対して、列 total_price (合計金額) が更新 されます。 表階層のトリガ (IDS のみ) 上位表でトリガを定義すると、その表階層にあるすべての副表にもそのトリガが継 承されます。したがって、階層内の表に対して操作を実行するときには、階層内 で、トリガが定義された表の副表になっているすべての表に対してトリガを実行で きます。 340 IBM Informix: SQL ガイド: チュートリアル 選択トリガの使用 (IDS のみ) 表または列に対して選択トリガを作成することにより、表内ヒット数の追跡のよう な、特定のタイプの監査をアプリケーションごとに実行できます。選択トリガを作 成すると、ユーザが特定の表に問合せを行うたびに、監査記録を監査表に挿入する ことができます。例えば、DBA は、Web DataBlade モジュールの Web トランザク ション履歴を提供するため、選択トリガを作成する可能性があります。 トリガ アクションを実行する SELECT 文 選択トリガを作成すると、特定の型の SELECT 文のみが、そのトリガに対して定義 されたアクションを実行できます。選択トリガは、次の型の SELECT 文に対しての み実行されます。 v スタンドアロン SELECT 分 v SELECT 文の選択リストにあるコレクション (COLLECTION) 型副問合せ v ユーザ定義ルーチンに埋め込まれた SELECT 文 v ビュー スタンドアロン SELECT 文 次のような選択トリガを表に定義すると仮定します。 CREATE TRIGGER hits_trig SELECT OF col_a ON tab_a REFERENCING OLD AS hit FOR EACH ROW (INSERT INTO hits_log VALUES (hit.col_a, CURRENT, USER)); 選択トリガが実行されるのは、スタンド アロン SELECT 文の選択リストにトリガ 列が表示された場合です。次の文は、データベース サーバが戻す行の実現値ごと に、トリガ hits_trig に対してトリガ アクションを実行します。 SELECT col_a FROM tab_a SELECT 文の選択リストにあるコレクション (COLLECTION) 型副 問合せ 選択トリガが実行されるのは、別の SELECT 文の選択リストに現れたコレクション (COLLECTION) 型副問合せにトリガ列が表示された場合です。次の文は、コレクシ ョン (COLLECTION) 型副問合せが戻す行の実現値ごとに、トリガ hits_trig に対 してトリガ アクションを実行します。 SELECT MULTISET(SELECT col_a FROM tab_a) FROM ... ユーザ定義ルーチンに埋め込まれた SELECT 文 ユーザ定義ルーチン (UDR) に埋め込まれた SELECT 文に対して定義された選択ト リガは、次のような実現値のみでトリガ アクションを実行します。 v SELECT 文の選択リストに表示される UDR v 実行プロシジャ ステートメントで呼び出される UDR 文 SELECT col_a FROM tab_a を含むルーチン new_proc を作成すると仮定しま す。次の各文は、埋め込まれた SELECT 文が戻す行の実現値ごとに、トリガ hits_trig に対してトリガ アクションを実行します。 SELECT new_proc() FROM tab_b EXECUTE PROCEDURE new_proc 第 12 章 トリガの作成と使用 341 ビュー 選択トリガは、基本表にトリガ列への参照を含むビューに対してトリガ アクション を実行します。ただし、ビューに対して選択トリガを定義することはできません。 次のようなビューを作成すると仮定します。 CREATE VIEW view_tab AS SELECT * FROM tab_a 次の文は、ビューが戻す行の実現値ごとに、トリガ hits_trig に対してトリガ アク ションを実行します。 SELECT * FROM view_tab SELECT col_a FROM tab_a 選択トリガの実行についての制限 次のような場合、その文は選択トリガに対して何のアクションも起こしません。 v トリガ列が選択リストにない場合 (例えば、SELECT 文の WHERE 節に表示され ている列は選択トリガを実行しません)。 v SELECT 文がリモート表をインクルードする場合。 v SELECT 文が集計関数を含む場合。 v SELECT 文が UNION または UNION ALL 演算子をインクルードする場合。 v SELECT 文がキーワード DISTINCT または UNIQUE をインクルードする場合。 v SELECT 文を含む UDR 表現式が選択リストに存在しない場合。 v SELECT 文が INSERT INTO 文に表示される場合。 v SELECT 文がスクロール カーソルに表示される場合。 v トリガがカスケードされる選択トリガである場合。 カスケード選択トリガは、トリガ SELECT 文を自前で持つ SPL ルーチンをその アクションに含むトリガです。ただし、カスケード選択トリガのアクションは実 行されず、データベース サーバはエラーを戻しません。 表階層の表に対する選択トリガ 上位表に対して選択トリガを定義すると、その表階層にあるすべての副表もそのト リガを継承します。 継承されたトリガを上書きする方法、または無効にする方法については、340 ペー ジの『表階層のトリガ (IDS のみ)』を参照してください。 リエントラント トリガ リエントラント トリガ は、トリガ アクションがトリガ表を参照できるケースを指 します。言い換えると、トリガ イベントとトリガ アクションの両方が同じ表で動 作できます。例えば、次のUPDATE文がトリガ イベントを表しているとします。 UPDATE tab1 SET (col_a, col_b) = (col_a + 1, col_b + 1) 列 col_c はトリガ イベントが更新した列ではないので、次のトリガ アクションは 有効です。 UPDATE tab1 SET (col_c) = (col_c + 3) 342 IBM Informix: SQL ガイド: チュートリアル この前の例では、トリガ アクションが、トリガ イベントによって更新される列を 参照している UPDATE 文であってはならないので、col_a または col_b に対する トリガ アクションは無効です。 重要: 選択トリガはリエントラント トリガにはなり得ません。トリガ イベントが SELECT 文である場合、同じ表でトリガ アクションを動作させることはでき ません。 トリガをリエントラント可能および不可能な状態を説明するルールのリストについ て、詳しくは、「IBM Informix: SQL ガイド: 構文」の CREATE TRIGGER 文を参 照してください。 ビューの INSTEAD OF トリガ (IDS のみ) ビューは CREATE VIEW 文を使用して作成し、 SELECT 文を使用して定義する仮 想表です。それぞれのビューは、問い合わせのビューを参照する度にビュー定義の SELECT 文が戻す、一連の行と列で構成されます。ビューは仮想表であるため、ビ ュー内で行を挿入、更新、または削除するには、 INSTEAD OF トリガを使用する 必要があります。 ビューで行を挿入する INSTEAD OF トリガの例を含む、 CREATE VIEW 文およ び INSTEAD OF トリガ構文ルールについて、詳しくは、「IBM Informix: SQL ガ イド: 構文」を参照してください。 INSTEAD OF トリガを使用してビュー上で更新 1 つ以上の表 (以下の例の表名 dept および emp など) を作成し、さらに dept および emp からビュー (ビュー名 manager_info など) を作成後、 INSTEAD OF トリガを使用してそのビューを更新できます。 以下の CREATE TRIGGER 文は、表 dept および emp 内の行を、 manager_info ビューを使用して更新するために設計された、 INSTEAD OF トリ ガである manager_info_update を作成します。 CREATE TRIGGER manager_info_update INSTEAD OF UPDATE ON manager_info REFERENCING NEW AS n FOR EACH ROW (EXECUTE PROCEDURE updtab (n.empno, n.empname, n.deptno,)); CREATE PROCEDURE updtab (eno INT, ename CHAR(20), dno INT,) DEFINE deptcode INT; UPDATE dept SET manager_num = eno where deptno = dno; SELECT deptno INTO deptcode FROM emp WHERE empno = eno; IF dno !=deptcode THEN UPDATE emp SET deptno = dno WHERE empno = eno; END IF; END PROCEDURE; 表、ビュー、トリガ、および SPL ルーチンを作成後、データベース サーバは、以 下の UPDATE 文をトリガ イベントとして扱います。 UPDATE manager_info SET empno = 3666, empname = “Steve” WHERE deptno = 01; 第 12 章 トリガの作成と使用 343 このトリガされる UPDATE 文は実行されませんが、このイベントは updtab() SPL を呼び出して、代わりにトリガ アクションを実行させます。 SPL ルーチン内の UPDATE 文は、 manager_info ビューの emp および dept ベースの表両方に、 値を更新します。 トリガ アクションのトレース トリガ アクションが意図した動作を行わない場合、SPL ルーチンに配置し、 SPLTRACE 文を使用してその操作を監視してください。トレースを開始する前に SET DEBUG FILE TO 文を使用してトレース結果がファイルに出力されるようにし ます。 SPL ルーチン内の TRACE 文の例 以下の例は、SPL ルーチン items_pct に追加した TRACE 文を示しています。 SET DEBUG FILE TO 文は、パス名で指定されるファイルにトレースが出力される ようにします。 TRACE ON 文は、文および変数のトレースをプロシジャ内で開始 します。 CREATE PROCEDURE items_pct(mac CHAR(3)) DEFINE tp MONEY; DEFINE mc_tot MONEY; DEFINE pct DECIMAL; SET DEBUG FILE TO ’pathname’; TRACE ’begin trace’; TRACE ON; LET tp = (SELECT SUM(total_price) FROM items); LET mc_tot = (SELECT SUM(total_price) FROM items WHERE manu_code = mac); LET pct = mc_tot / tp; IF pct > .10 THEN RAISE EXCEPTION -745; END IF TRACE OFF; END PROCEDURE; CREATE TRIGGER items_ins INSERT ON items REFERENCING NEW AS post_ins FOR EACH ROW(EXECUTE PROCEDURE items_pct (post_ins.manu_code)); TRACE 出力の例 items_pct プロシジャからのトレース出力の例を次に示します。このプロシジャ は、SET DEBUG FILE TO 文の中で指定されたファイルに出力されています。この 出力に示されているのは、プロシジャ変数の値、プロシジャ引数、戻り値、および エラー コードです。 trace expression :begin trace trace on expression: (select (sum total_price) from items) evaluates to $18280.77 ; let tp = $18280.77 expression: (select (sum total_price) from items where (= manu_code, mac)) 344 IBM Informix: SQL ガイド: チュートリアル evaluates to $3008.00 ; let mc_tot = $3008.00 expression:(/ mc_tot, tp) evaluates to 0.16 let pct = 0.16 expression:(> pct, 0.1) evaluates to 1 expression:(- 745) evaluates to -745 raise exception :-745, 0, ’’ exception : looking for handler SQL error = -745 ISAM error = 0 error string = exception : no appropriate handler = ’’ TRACE 文を使用して SPL ルーチン内の論理エラーを診断する方法について、詳し くは、 259 ページの『第 11 章 SPL ルーチンの作成と使用』を参照してください。 エラー メッセージの生成 SQL 文が原因でトリガが失敗する場合、データベース サーバは、失敗の特定の原 因に適用する SQL エラー番号を戻します。 トリガ アクションが SPL ルーチンの場合は、2 つの予約エラー番号のうちの 1 つ を使用して、他のエラー条件を表すエラー メッセージを生成することができます。 1 つはエラー番号 -745 で、これには一般的な固定エラー メッセージが割り当てら れています。もう 1 つは -746 であり、最大 70 バイトからなるメッセージテキス トを指定することができます。 固定エラー メッセージの適用 エラー番号 -745 を、SQL エラーでないすべてのトリガの失敗に適用できます。こ のエラーには、次の固定メッセージがあります。 -745 トリガの実行に失敗しました。 このメッセージは、SPL の RAISE EXCEPTION 文を使用して適用できます。次の 例では、new_qty が old_qty の 1.5 倍を超える場合にエラー - 745 を生成しま す。 CREATE PROCEDURE upd_items_p2() DEFINE GLOBAL old_qty INT DEFAULT 0; DEFINE new_qty INT; LET new_qty = (SELECT SUM(quantity) FROM items); IF new_qty > old_qty * 1.50 THEN RAISE EXCEPTION -745; END IF END PROCEDURE DB–Access を使用している場合は、エラー -745 のメッセージ テキストは、 図 474 に示すように画面の一番下に表示されます。 第 12 章 トリガの作成と使用 345 ヘルプは CTRL-W SQL: N/新規 R/実行 M/変更 U/編集 O/出力 C/選択 SQL エディタを使用して現行の SQL 文を変更します。 S/保存 I/情報 D/削除 E/終了 --------------------- stores8@myserver --------- ヘルプは CTRL-W ---INSERT INTO items VALUES( 2, 1001, 2, ’HRO’, 1, 126.00); 745: Trigger execution has failed. 図 474. 固定メッセージが表示されるエラー -745 ご使用の SQL API の SQL 文を使用して、エラーを含むプロシジャをトリガする 場合、データベース サーバは、SQL エラー状態変数を -745 に設定し、プログラム に戻します。このメッセージ テキストを表示するには、SQL エラー メッセージの テキストを抽出するために IBM Informix アプリケーション開発支援ツールが提供 しているプロシジャに従います。 可変エラー メッセージの生成 エラー番号 -746 では、エラー メッセージのテキストを指定することができます。 前述の例のように、次の例も new_qty が old_qty に 1.50 を掛けた値より大きい 場合にエラーを生成します。ただし、この場合のエラー番号は -746 であり、Too many items for Mfr. というメッセージ テキストが、 RAISE EXCEPTION 文の 3 番目の引数として出力されます。構文およびこの文の使用方法について、詳しくは 259 ページの『第 11 章 SPL ルーチンの作成と使用』の RAISE EXCEPTION 文を 参照してください。 CREATE PROCEDURE upd_items_p2() DEFINE GLOBAL old_qty INT DEFAULT 0; DEFINE new_qty INT; LET new_qty = (SELECT SUM(quantity) FROM items); IF new_qty > old_qty * 1.50 THEN RAISE EXCEPTION -746, 0, ’Too many items for Mfr.’; END IF END PROCEDURE; DB–Access を使用してトリガ文を実行要求する場合や、new_qty が old_qty より 大きい場合には、図 475 に示す結果になります。 346 IBM Informix: SQL ガイド: チュートリアル ヘルプは CTRL-W SQL: N/新規 R/実行 M/変更 U/編集 O/出力 C/選択 SQL エディタを使用して現行の SQL 文を変更します。 S/保存 I/情報 D/削除 E/終了 -------------------- store7@myserver --------- ヘルプは CTRL-W ----INSERT INTO items VALUES( 2, 1001, 2, ’HRO’, 1, 126.00); 746: Too many items for Mfr. 図 475. ユーザ指定のメッセージテキストが表示されるエラー番号 -746 トリガを SQL API の SQL 文から呼び出す場合、データベース サーバは sqlcode を -746 に設定し、SQL 通信領域 (SQLCA) の sqlerrm フィールド内のメッセー ジ テキストを戻します。 SQLCA の使用方法について、詳しくは、ご使用の SQL API マニュアルを参照してください。 サマリ トリガ導入の観点から、この章では次のトピックについて説明しました。 v CREATE TRIGGER 文の各コンポーネントの目的 v BEFORE トリガ アクションとAFTER トリガ アクションの作成方法と、それら のトリガ アクションを使用したトリガ文の影響の調査方法 v FOR EACH ROW トリガ アクションの作成方法と、REFERENCING 節を使用し た、トリガ文の実行前後の列値の参照方法 v SPL ルーチンをトリガ アクションとして使用する利点 v トリガ アクションが期待どおりに動作しないときのトレース方法 v トリガ アクション内の 2 種類のエラー メッセージの生成方法 第 12 章 トリガの作成と使用 347 348 IBM Informix: SQL ガイド: チュートリアル 特記事項 本書に記載の製品、サービス、または機能が日本においては提供されていない場合 があります。日本で利用可能な製品、サービス、および機能については、日本 IBM の営業担当員にお尋ねください。本書で IBM 製品、プログラム、またはサービス に言及していても、その IBM 製品、プログラム、またはサービスのみが使用可能 であることを意味するものではありません。これらに代えて、IBM の知的所有権を 侵害することのない、機能的に同等の製品、プログラム、またはサービスを使用す ることができます。ただし、IBM 以外の製品とプログラムの操作またはサービスの 評価および検証は、お客様の責任で行っていただきます。 IBM は、本書に記載されている内容に関して特許権 (特許出願中のものを含む) を 保有している場合があります。本書の提供は、お客様にこれらの特許権について実 施権を許諾することを意味するものではありません。 〒106-0032 東京都港区六本木 3-2-31 IBM World Trade Asia Corporation Licensing 以下の保証は、国または地域の法律に沿わない場合は、適用されません。IBM およ びその直接または間接の子会社は、本書を特定物として現存するままの状態で提供 し、商品性の保証、特定目的適合性の保証および法律上の瑕疵担保責任を含むすべ ての明示もしくは黙示の保証責任を負わないものとします。 国または地域によって は、法律の強行規定により、保証責任の制限が禁じられる場合、強行規定の制限を 受けるものとします。 この情報には、技術的に不適切な記述や誤植を含む場合があります。本書は定期的 に見直され、必要な変更は本書の次版に組み込まれます。 IBM は予告なしに、随 時、この文書に記載されている製品またはプログラムに対して、改良または変更を 行うことがあります。 本書において IBM 以外の Web サイトに言及している場合がありますが、便宜のた め記載しただけであり、決してそれらの Web サイトを推奨するものではありませ ん。それらの Web サイトにある資料は、この IBM 製品の資料の一部ではありませ ん。それらの Web サイトは、お客様の責任でご使用ください。 IBM は、お客様が提供するいかなる情報も、お客様に対してなんら義務も負うこと のない、自ら適切と信ずる方法で、使用もしくは配布することができるものとしま す。 本プログラムのライセンス保持者で、(i) 独自に作成したプログラムとその他のプロ グラム(本プログラムを含む)との間での情報交換、および (ii) 交換された情報の 相互利用を可能にすることを目的として、本プログラムに関する情報を必要とする 方は、下記に連絡してください。 IBM Corporation J46A/G4 © Copyright IBM Corp. 1996, 2003 349 555 Bailey Avenue San Jose, CA 95141-1003 U.S.A. 本プログラムに関する上記の情報は、適切な使用条件の下で使用することができま すが、有償の場合もあります。 本書で説明されているライセンス・プログラムまたはその他のライセンス資料は、 IBM 所定のプログラム契約の契約条項、IBM プログラムのご使用条件、またはそれ と同等の条項に基づいて、 IBM より提供されます。 この文書に含まれるいかなるパフォーマンス・データも、管理環境下で決定された ものです。そのため、他の操作環境で得られた結果は、異なる可能性があります。 一部の測定が、開発レベルのシステムで行われた可能性がありますが、その測定値 が、一般に利用可能なシステムのものと同じである保証はありません。さらに、一 部の測定値が、推定値である可能性があります。実際の結果は、異なる場合があり ます。お客様は、お客様の特定の環境に適したデータを確かめる必要があります。 IBM 以外の製品に関する情報は、その製品の供給者、出版物、もしくはその他の公 に利用可能なソースから入手したものです。IBM は、それらの製品のテストは行っ ておりません。したがって、他社製品に関する実行性、互換性、またはその他の要 求については確証できません。 IBM 以外の製品のパフォーマンスに関する質問 は、それらの製品の供給者にお願いします。 IBM の将来の方向または意向に関する記述については、予告なしに変更または撤回 される場合があり、単に目標を示しているものです。 表示されている IBM の価格は IBM が小売り価格として提示しているもので、現行 価格であり、通知なしに変更されるものです。卸価格は、異なる場合があります。 本書には、日常の業務処理で用いられるデータや報告書の例が含まれています。よ り具体性を与えるために、それらの例には、個人、企業、ブランド、あるいは製品 などの名前が含まれている場合があります。これらの名称はすべて架空のものであ り、名称や住所が類似する企業が実在しているとしても、それは偶然にすぎませ ん。 著作権使用許諾: 本書には、様々なオペレーティング・プラットフォームでのプログラミング手法を 例示するサンプル・アプリケーション・プログラムがソース言語で掲載されていま す。お客様は、サンプル・プログラムが書かれているオペレーティング・プラット フォームのアプリケーション・プログラミング・インターフェースに準拠したアプ リケーション・プログラムの開発、使用、販売、配布を目的として、いかなる形式 においても、IBM に対価を支払うことなくこれを複製し、改変し、配布することが できます。このサンプル・プログラムは、あらゆる条件下における完全なテストを 経ていません。従って IBM は、これらのサンプル・プログラムについて信頼性、 利便性もしくは機能性があることをほのめかしたり、保証することはできません。 これらの例は、すべての場合について完全にテストされたものではありません。 IBM はこれらのプログラムの信頼性、可用性、および機能について法律上の瑕疵担 保責任を含むいかなる明示または暗示の保証責任も負いません。 350 IBM Informix: SQL ガイド: チュートリアル それぞれの複製物、サンプル・プログラムのいかなる部分、またはすべての派生的 創作物にも、次のように、著作権表示を入れていただく必要があります。 © (お客様の会社名) (西暦年). このコードの一部は、IBM Corp. のサンプル・プ ログラムから取られています。 © Copyright IBM Corp. (年を入れる). All rights reserved. この情報をソフトコピーでご覧になっている場合は、写真やカラーの図表は表示さ れない場合があります。 特記事項 351 商標 以下は、IBM Corporation の商標です。AIX; DB2; DB2 Universal Database; Distributed Relational Database Architecture; NUMA-Q; OS/2, OS/390, and OS/400; IBM Informix®; C-ISAM®; Foundation.2000™; IBM Informix ® 4GL; IBM Informix®DataBlade®Module; Client SDK™; Cloudscape™; Cloudsync™; IBM Informix®Connect; IBM Informix®Driver for JDBC; Dynamic Connect™; IBM Informix®Dynamic Scalable Architecture™(DSA); IBM Informix®Dynamic Server™; IBM Informix®Enterprise Gateway Manager (Enterprise Gateway Manager); IBM Informix®Extended Parallel Server™; i.Financial Services™; J/Foundation™; MaxConnect™; Object Translator™; Red Brick™; IBM Informix® SE; IBM Informix® SQL; InformiXML™; RedBack®; SystemBuilder™; U2™; UniData®; UniVerse®; wintegrate® Java およびすべての Java 関連の商標およびロゴは、Sun Microsystems, Inc. の米国 およびその他の国における商標です。 Windows、Windows NT、および Excel は、Microsoft Corporation の米国およびその 他の国における商標です。 UNIX は、X/Open Company Limited がライセンスしている米国およびその他の国に おける商標です。 本書で使用する他の会社名、製品名、およびサービス名は、他社の商標またはサー ビス・マークである場合があります。 352 IBM Informix: SQL ガイド: チュートリアル 索引 日本語, 数字, 英字, 特殊文字の 順に配列されています。なお, 濁 音と半濁音は清音と同等に扱われ ています。 説明 188 データベース サーバ メソッド トランザクション ログ 188 188 定義 処理 のアクティブ セット 210 228 203 184 252 172 データベース レベル 172 データベースでの 172 表示 173 表レベル 172 アクティブ セット カーソルの 213 定義 34, 206 アスタリスク、SELECT 内のワイルドカ ード文字 22 アスタリスク表記、SELECT 文 74 アプリケーション エラー処理 208 排他レベル 245 UPDATE カーソル 250 意味整合性 175 一時表 およびカーソルのアクティブ セット 213 列名の割当て 120 例 165 意図ロック 251 違反の検出 178 違反表 アクセス権の例 183 開始 182 開始の例 182 説明 181 名前の割当て 182 © Copyright IBM Corp. 1996, 2003 209 カーソル安定性排他レベル 213 カーソルの選択 DELETE の後 オープン 224 203 210 使用 210 外部キー 176 外部結合構文 346 適用する固定 345 トリガ失敗への 345 トリガでの生成 345 xvii 255 213 プログラム操作のシーケンス FETCH での値の抽出 211 (Informix) 247 カーソルのオープン 208 可変、生成 227 トランザクションの終わり 198 198 ISAM エラー コード エラー メッセージ xvii データ修正の必要 使用可能な言語 コード 更新中 アイコン 機能 xvii 警告 xvii アクセス モード、説明 アクセス権 概要 5 挿入のため 定義 209 カーソルを使用した挿入 アーカイブ 製品 xvii ヒント xvii プラットフォーム カーソル (続き) 例 179 埋込み SQL エラー カーソルのオープン時の検出 [ア行] 重要 違反表 (続き) ANSI 124 Informix 124 外部データベース 193 プログラム内のトリガ テキストの検索 346, 347 エラー メッセージ ファイル 205 外部表 189 階層 表および行 エラー メッセージのメッセージ ファイル xxii 拡張性、説明 9 確定読込み排他レベル (ANSI) エラー検査 エラーのシミュレート 確定読込み排他レベル (Informix) カスケード削除 330 SPL ルーチン 328, 331 エンティティ保全性 174 大文字小文字変換 INITCAP 関数を使用 100 LOWER 関数を使用 99 UPPER 関数を使用 99 オブジェクト モード 説明 178 停止 178 フィルタ 178 有効 178 オブジェクト リレーショナル データベー ス、説明 9 オンライン ヘルプ xxi オンライン マニュアル xxi [カ行] カーソル オープン 210, 213 クローズ 255 更新 244 更新のため 232 順 212, 213 スクロール 212 宣言 210 78 246 246 関連したロック 176 子表 176 参照整合性 176 制約事項 177 定義 176 ロギング 177, 187 型付き表 から選択 71 行の挿入 159 定義 70 型なし 276 各国語可変長文字 (NVARCHAR) 型、問 合せ 17 各国語文字 (NCHAR) 型、問合せ 17 可変長文字 (VARCHAR) 型、LENGTH 関数の使用 105 画面、例 345 関係演算 18 関係演算子 BETWEEN 36 EXISTS 132 IN 132 LIKE 41 MATCHES 41 NULL 39 OR 38 353 関係演算子 (続き) WHERE 節内 関係モデル 結合 20 射影 19 選択 関数 18 117 日付関連 変換 93 文字列操作 構文記法 xvii 構文ダイヤグラム 34 キーワード INTO 表記 格納場所の選択 211 単一行の抽出 206 89 複数行の抽出 98 FETCH 文 93 108 DECODE 108 INITCAP 100 xxii 規則 積の構成 148 WHERE 節での使用 97 256 規格準拠 業界標準 キーワード IN 89 39 キーワード WITH HOLD、HOLD カーソ ルの宣言 列番号 117 キーワード HAVING スマート ラージ オブジェクト DBINFO 値の範囲 36 NULL データのテスト 説明 114 89 84 DATE キーワード WHERE ORDER BY との競合 227 キーワード FROM、別名 64 キーワード GROUP BY 式への適用 時刻 集計 キーワード FOR UPDATE (続き) 34 機能のアイコン 行 関係モデル 210 更新 211 xvii xvi xvii 7 166 PREPARE 文で処理された文の制約事 処理された行数の検出 項 217 SQLWARN でシグナル通知されるミス 除去 挿入 108 153 157 LOWER 99 LPAD 103 NVL 110 マッチ 204 キーワード INTO TEMP、説明 66 キーワード IS NOT NULL 39 定義 7, 18 戻される行数 ロック 241 REPLACE 100 RPAD 104 キーワード IS NULL 39 キーワード ITEM、コレクション SPL ルーチン内で処理された行数 331 SELECT 文内 84 SPL ルーチンでの名前の混同 280 説明 41 WHERE 節での使用 キーワード MATCHES SUBSTR 102 SUBSTRING 101 TO_CHAR 94 GLS の使用 45 WHERE 節での使用 TO_DATE 95 UPPER 99 キーワード 構文ダイヤグラム内 xx 副問合せ内 132 WHERE 節内 34 キーワード ALL 副問合せ 132 副問合せの開始 132 キーワード ANY、SELECT 文内 133 キーワード BETWEEN 行範囲の指定に使用 36 WHERE 節での使用 34 キーワード DISTINCT COUNT 関数で使用 85 GROUP BY との関係 114 SELECT での使用 27 キーワード ESCAPE、WHERE 節での使 用 46 キーワード EXCLUSIVE DATABASE 文の 239 キーワード EXISTS 148 SELECT 文内 136 WHERE 節内 132 キーワード FOR UPDATE 特定の列 232 ANSI 標準準拠データベースで必要と されない 233 354 (COLLECTION) 型の副問合せ キーワード LIKE 139, 140 34 34 47 行 ID、内部行番号の検索に使用 行 (ROW) 型 からのデータ選択 からの列選択 72 更新 168 55 ピリオド表記 73 フィールド、定義 69 72 キーワード MULTISET コレクション (COLLECTION) 型の副 フィールド射影 73 DELETE 文内 155 問合せ 139 キーワード NOT EXISTS 149 キーワード NOT IN 149 SELECT でのアスタリスク表記の使用 74 SELECT でのフィールド射影 73 キーワード ORDER BY および GLS 32 行 (ROW) 型データ、の列を選択 行 (ROW) 型変数、宣言 277 キーワード DESC 25, 31 行のソート 24 昇順 24 番号で列を選択 30 表示ラベル 54 複数の列 25 FOR UPDATE の制約事項 227 GROUP BY との関係 116 INSERT の制約事項 165 キーワード REFERENCES、SPL 関数内 276 キーワード SCROLL、DECLARE 内での 使用 212 キーワード SOME、副問合せの開始 132 キーワード TABLE、ロック モードの 241 キーワード UNION、集合演算で 142 キーワード UNIQUE、SELECT 文内 27 キーワード UPDATE 232 行 (ROW) 型列 定義 72 NULL 値 169 業界標準、準拠 xxii 共有クラス ライブラリ 9 共有ロック 238 局所変数、説明 274 切捨て、SQLWARN でシグナル通知され る 204 金額 (MONEY) 型 INSERT 文内 158 組込み変数 275 クラス ライブラリ、共有 9 繰り返し可能読込み排他レベル 249 警告、SPL ルーチンでのコンパイル時 325 警告のアイコン xvii 計数関数 説明 96 IBM Informix: SQL ガイド: チュートリアル 72 結合 コレクション (COLLECTION) 型導出表 入れ子になった単純 外部 123 結合性 127 制約事項 61 交差 説明 57 削除結合 作成 57 自然 120 56 定義 20, 56 等価結合 58 左外部 複数表結合 8 射影、定義 19 124 Informix 外部結合構文 124 UPDATE 文内 172 コード、サンプル、の規則 xx コード例の表記 xx 広域言語サポート (GLS) xiv およびキーワード MATCHES 45 およびキーワード ORDER BY 32 ソート順 32 デフォルト ロケール 広域変数 32 説明 説明 138 76 交換子関数 定義 269 交差結合 57 更新ロック、保存 構成パラメータ 再帰的関係、の例 215 細分性、ロック 239 差集合演算 149 サブスクリプト付け SPL 変数 279 WHERE 節内 46 サブ文字列 31, 280 参照制約、定義 シーケンス 定義 8 250 ISOLATION_LOCKS 構文ダイヤグラム 136 176 時間隔 (INTERVAL) 型 関係式 247 キーワード xx の規則 xvii 変数 xx コマンド行の表記規則 読み方 xviii コメントのアイコン xvii 固有名、SPL ルーチンの 265 コレクション (COLLECTION) 型 アクセス 69, 75 更新 169, 170 説明 75 単純 75 要素、IN での検索 77 要素のカウント 97 CARDINALITY 関数の使用 97 DELETE 文内 156 SPL ルーチン内 271 コレクション (COLLECTION) 型値、列へ の挿入 162 86 COUNT 162 88 134 85 ESQL 内 206 MAX 86 MIN 86 [サ行] 作用素、存在 84, 93 標準偏差 副問合せ AVG 276 算術演算子、式 49 算術式 49 参照整合性、定義 175 281 281 115 84 シグナル通知するされる NULL 値 204 コレクション、INSERT 文の使用 62 集計関数 および GROUP BY 節 式 定義、制約事項 右外部 126 ANSI 外部結合構文 説明 宣言 射影、説明 xiv キーワード ITEM 139, 140 キーワード ITEM の使用 140 選択 124 データベース 自然結合 60 142 コレクション (COLLECTION) 型変数 入れ子 75, 76 56 システム要件 (続き) 139, 302 せ 60 単純 141 SPL での使用 307 コレクション (COLLECTION) 型の副問合 157 条件 56 セルフ結合 複合 141 コレクションの要素へのアクセス 34 式 説明 49 の表示ラベル 51 日付関連 89 CASE 53 SPL ルーチン内 284 時刻関数 説明 89 DAY および CURRENT 89 SELECT での使用 84 WEEKDAY 91 YEAR 92 自己参照型問合せ 120, 177 システム カタログ アクセス権 173 照会 173 sysprocbody 325 systabauth 173 システム記述子領域 219 システム要件 ソフトウェア xiv NULL 値の検索 208 RANGE 87 SPL ルーチン内 284 STDEV 88 SUM 87 VARIANCE 集合演算 88 差 149 使用 142 積 147 和集合 142 重要なパラグラフ、アイコン xvii 主キー、定義 174 主キー制約、定義 176 順カーソル、定義 212 循環型問合せ 177 上位表 80 から削除 から選択 154 80 表階層内 78 別名の使用 81 への挿入 162 照合順序と GLS 32 シリアル (SERIAL) 型 開始値の挿入 159 最後に挿入されたシリアル値の検索 108 SQLERRD で生成される値 203 診断表 アクセス権の例 183 開始の例 182 説明 181 シンプル ラージ オブジェクト、SPL 変 数 275 スクロール カーソル アクティブ セット 214 定義 212 索引 355 データ レプリケーション データ型 ストアド プロシジャ言語 参照: SPL ストアド ルーチン、一般的なプログラミ ング 11 スマート ラージ オブジェクト インポートおよびエクスポート SPL 変数 97, UPDATE 文内 171 整合性がある削除 静的 SQL 199 225 231 202, 208 説明 120 INTO TEMP を使用した列名の割当て 120 選択、説明 8, 18 選択トリガ、説明 341 サブ文字列の指定 式 49 ラベル 146 ソート 入れ子 25 ロケールの影響 32 GLS の効果 32 ORDER BY を使用 24 相関副問合せ カスケード削除の制約事項 定義 131 増進可能なロック 239, 244 [タ行] 多重順序付け、SELECT 25 単一行 SELECT 文 34, 206 単純読込み排他レベル (Informix) 246 チェック制約、定義 175 中括弧 (` }) コメント区切り 271 重複値、検索 55 データ モデル、説明 1 データ モデルとして記述 複合 142 等価結合 3 58 動的 SQL 説明 200, 216 動的ルーチン名指定 のルール 320 319 制御 ドキュメント ノート、プログラム項目 5 定義 6 内容の変更 並行使用 xxii 特殊文字、プロテクト 4 終わり 5 6 255 説明 185 の終りに解除されるロック の終りへのロック保持 239 178 178 データベース オブジェクト モード 例 179 データベース サーバ アーカイブ 188 バージョン番号の識別 108 文のキャッシュ 256 ホスト コンピュータ名の識別 108 ロック表 239 SQLWARN でのシグナル通知 204 定数データの行の挿入 229 ディスティンクト (DISTINCT) 型変数 278 デカルト積 結合の基本 57 説明 56 テキスト (TEXT) 型 関係式 34 制約事項 GROUP BY の 116 LENGTH 関数の使用 105 デッドロック検出 254 IBM Informix: SQL ガイド: チュートリアル 46 トランザクション 2 リモート 193 リレーショナル、説明 トリガ 177 177 177 SPL ルーチン用 319 ドキュメント ノート xxi インデックス 178 オブジェクト モード 制約 178 すべての列を選択 22 特定の列を選択 27 表示ラベル 51 138 SPL 関数用 193 ANSI 標準準拠 11 データベース オブジェクト 違反の検出 178 31 監査 管理 5 サーバ 5 ロック 選択リスト 関数 84, 107 175 219 ファイルとの比較 120 209 列内 問合せ xiv PREPARE 文で処理された文の解放 189 オブジェクト リレーショナル、説明 9 外部 147 定義 148 積集合演算 148 セッション ID、DBINFO 関数が戻す 356 210 データベース 174 使用 循環型 219 SQLCODE 211 SQLCODE のシグナル xvii デフォルト ロケール デフォルト値 自己参照型の データのロード 制約、エンティティ保全性 積 108 セルフ結合 174 184 SELECT のみのシグナル 163 SELECT 文内 97 集合演算 データ整合性 データの終り カーソルのオープン時 275 69, 75 自動変換 207 変換 158, 206 データ定義文 97 SQL 関数の使用 INSERT 文内 製品のアイコン コレクション、アクセス 障害 163 コピーする関数 190 244 244 ロギング 185 DELETE の例 224 SQLWARN でのシグナルの使用 トランザクション ログ 説明 185 ログの内容 188 XPS 186 トリガ 作成 334 使用時 334 選択 実行の制約事項 342 説明 341 表階層における定義 342 定義 334 名前の割当て 335 表階層内 340 リエントラント 342 INSTEAD OF 343 トリガ アクション エラー メッセージの生成 345 使用 337 定義 336 トリガ文を基準にする 336 トレース 344 文 334 BEFORE および AFTER 337 FOR EACH ROW 338 204 トリガ アクション (続き) REFERENCING 節 SELECT 文 341 338 SPL ルーチンを使用する WHEN 条件 339 プログラム グループ ドキュメント ノート 等しくない (!=) 関係演算子 35 等しくない () 関係演算子 35 リリース ノート プログラム変数 等しくない、関係演算子 339 から削除 定義 7 336 名前付き行 (named row) 型、VALUES 節 内 160 名前なし行 (unnamed row) 型、VALUES 160 二重ハイフン (--) コメント標識 271 関数からの戻り 形式の表示 93 文字列への変換 94 ORDER BY シーケンスで 日時 (DATETIME) 型値、形式 24 93 バージョン番号、DBINFO 関数が戻す 108 排他レベル カーソル安定性 (Informix) 繰り返し可能読込み 説明 245 単純読込み 246 カーソル安定性排他レベル 階層 78 (Informix) 関係モデル 6 現行データベースにない 説明 40 デッドロック 6 247 249 246 ANSI 246, 249 Informix 246 排他ロック 238 バイト (BYTE) 型 関係式 34 GROUP BY の制約事項 116 LENGTH 関数の使用 105 パフォーマンス ストアド ルーチンによる増加 261 並行性の効果 236 パブリックに付与されたアクセス権に影響 力を持つ環境変数 NODEFDAC 322 バリアント SPL 関数 268 比較条件、説明 34 非確定読込み排他レベル (ANSI) 246 左外部結合 124 日付 (DATE) 型 関係式 34 関数からの戻り 89 文字列への変換 94 ORDER BY シーケンスで 24 239 254 排他レベル 245 表ロック 239 複数のプログラム 189 onload ユーティリティの使用 ロギング 186 ログなし 186 ロック 247 説明 189, 236 データベース ロック 189 237 ロックの継続期間 244 ロックの種類 238 ロック範囲 239 ANSI 排他レベル 239 表階層 のトリガ 340 UPDATE 文 170 [ハ行] 256 アクセス モード 252 アクティブ セット 214 343 表 外部表の使用 89 200 並行性 343 操作 8 データのロード 日時 (DATETIME) 型 関係式 34 xxii xxii 文ブロック 284 ページ ロック 241 343 の INSTEAD OF トリガ への挿入 343 [ナ行] 非確定読込み SPL 文キャッシュ、SQL で更新 節内 35 ビュー トリガ イベント 定義 335 例 必要なソフトウェア xiv 等しい (=) 関係演算子 35, 58 246 Informix 排他レベル 246 別名 一時表での列名の割当て 120 標識変数、定義 207 標準偏差、集計関数 88 使用 上位表で 表示ラベル 267 ORDER BY 節 54 SELECT で 51 問合せのショートカットとして セルフ結合 120 表名の 64 ピリオド表記 73 ヒントのアイコン ヘルプ xxi 変換関数、説明 xvii ブール (BOOLEAN) 式 40 ファイル、データベースとの比較 フィールド、定義 72 フィールド射影 73 フィルタ モード 178 複合問合せ 142 複数表結合 62 複数表の SELECT 文 56 副問合せ 一価 134 キーワード ALL 132 キーワード ANY 133 選択リスト内 131 相関 131, 135, 177 DELETE 文内 156, 157 SELECT 文内 130 UPDATE 文内 166 SET 節を使用 167 WHERE 節内 132 不透明 (OPAQUE) 型変数 278 太文字 xvi 部品展開 215 プラットフォームのアイコン xvii 1 81 64 93 変数 キーワードと同じ名前をもつ 280 SPL ルーチンでの定義および使用 273 SPL ルーチンでの範囲 274 変数、構文ダイヤグラム内 xx ホスト変数 201 区切り記号 200 シグナル通知される切捨て 204 説明 200 へのデータの取出し 211 DELETE 文内 224 INSERT 文内 227 INTO キーワード セット 206 NULL 標識 207 PREPARE 文で処理された文の制約事 項 217 UPDATE 文内 231 WHERE 節内 206 索引 357 [マ行] マシン ノート ロケール xxi マニュアル、タイプ xxi ドキュメント ノート xxi マシン ノート リリース ノート xxi xxi 126 文字 (CHAR) 型 関係式 34 サブ文字列 行とキーのロック ALTER INDEX 文、ロック表 241 AND 論理演算子 ANSI 更新ロック 250 異なるロック タイプの動作 204 95 95 254 ロック モードの設定 253 ロックされる行数 247 行とキーのロック 要件、ソフトウェア xiv より小または等しい 36 より大または等しい (>=) 関係演算子 表ロック 239 ページ ロック 36 [ラ行] ラベル 51, 146 リエントラント トリガ、説明 ロック モード、TABLE 論理演算子 342 193 リリース ノート、プログラム項目 xxii リレーショナル データベース、説明 6 ループ、RAISE EXCEPTION を使用した 終了 330 列 関係モデル 7 行 (ROW) 型、定義 72 降順 25 説明 7 選択の順序付け 23 定義 18 ラベル 146 列の定義域 175 列番号、使用 30 レプリケーション データの 190 透過性 190 ログスライス、説明 186 ログなし表 186 C 説明 53 UPDATE 文内 171 CLOSE DATABASE 文、データベース ロ ックへの効果 239 COMMIT WORK 文 244 カーソルのクローズ 255 ロック解除 244, 255 SQLCODE の設定 225 241 COUNT 関数 188 [ワ行] ワイルドカード、単一文字の使用 ワイルドカード文字 アスタリスク 22 プロテクト 46 和集合演算 142 42 [数字] 10 進数 (DECIMAL) 型、SQLWARN で シグナル通知される 204 9.4 機能、概要 xv IBM Informix: SQL ガイド: チュートリアル 187 CASE 式 使用 53 239 AND 40 NOT 40 OR 40 = (等しい) 40 論理ログ およびバックアップ 説明 185 BEGIN WORK 文 CALL 文、SPL 関数内 317 CARDINALITY 関数 97 244 241, 242 ロック範囲 239 DELETE で 224 UPDATE カーソル 86 B 241 データベース ロック 排他 238 onload 189 onunload 189 で必要とされない FOR UPDATE 233 SQLWARN でのシグナル通知 204 AVG 関数、集計関数として 238 243 増進可能 239 増進可能なロック ユーザ、対象 xiv ユーティリティ プログラム 10 ANSI 標準準拠データベース 255 コアース インデックス ロック 243 スマート ラージ オブジェクト [ヤ行] 249 ANSI 標準準拠 レベル xxii 238 共有 排他レベル 240 40 SQL バージョン ロックの継続期間 244 ロックの種類 238 文字列 日時 (DATETIME) 型値への変換 日付 (DATE) 型値への変換 93 戻りの型、SPL 関数内 267 251 時間制限 254 整合性 236 トランザクションの終わり 日時 (DATETIME) 型値への変換 日付 (DATE) 型値への変換 93 リモート データベース リリース ノート xxi A 189 253 デッドロック 31 xv キーワード WAIT 説明 シグナル通知される切捨て 358 251 および並行性 マルチスレッド アプリケーション、定義 199 右外部結合 9.4 の機能 xiv ロック 意図ロック および GROUP BY 116 削除する行のカウント 155 集計関数として 85 副問合せでの使用 156 DISTINCT を使用 85 CREATE DATABASE 文 共有ロックの設定 239 の後の SQLWARN 204 CREATE FUNCTION FROM 文、埋込み 言語で 272 CREATE FUNCTION 文 使用 263 CREATE FUNCTION FROM 文内 272 WITH LISTING IN 節 325 CREATE FUNCTION、RETURN 節 267 CREATE INDEX 文、ロック表 240 CREATE PROCEDURE FROM 文、埋込 み言語で 272 DELETE 文 (続き) CREATE PROCEDURE 文 使用 263 CREATE PROCEDURE FROM 内 272 WITH LISTING IN 節 325 CREATE TABLE 文 階層 78 カスケード削除 F 使用 223 上位表に対して 153, 154 整合性がある削除 225 説明 153 選択された行 重複行 177 コレクション (COLLECTION) 型 76 表のすべての行 主キー 176 スマート ラージ オブジェクト列 副問合せの使用 156 ロック モード 251 マルチセット (MULTISET) 型列 139 ロック モードの設定 XPS での結合の使用 ON DELETE CASCADE 節 CREATE TRIGGER 文 336 CURRENT 関数 使用 89 列の値の比較 211 xxii 147 ORDER BY 節との併用 48 FLUSH 文 157 挿入された行のカウント バッファへの行の書込み 157 270 DROP INDEX 文、ロック表 212 47 説明 47 ユニオン問合せ内 DOCUMENT 節、SPL ルーチンでの使用 153 212 説明 使用 224 153 WHERE 節の制約事項 242 LOCK MODE 節 241 順次 finderr ユーティリティ FIRST 節 229 特定の行 154 とのトランザクション 211 キーワード ABSOLUTE 順カーソル 213 154 型付き表 70 行 (ROW) 型列 70 98 FETCH 文 156 すべての行の削除 ロール バック 228 228 229 Dynamic Server、オブジェクト リレーシ ョナル データベース 9 FOREACH 文 285 FREE 文、PREPARE 文で処理された文の 解放 219 E G 240 89 D en_us.8859-1 ロケール ESQL xiv DATABASE 文 の後の SQLWARN 204 ロック 239 DataBlade モジュール エラー処理 208 カーソルからの行の取出し 9 カーソルの使用 209, 216 概要 198, 222, 223 スクロール カーソル 212 DATE 関数、変換関数として DAY 関数 89 93 DBDATE 環境変数 158 DBINFO 関数、SELECT 文内 108 DBSERVERNAME 関数、SELECT 文内 107 dbspace、DBINFO 関数が戻す名前 DB-Access 108 を使用したデータベースの作成 219 DECLARE CURSOR 文 227 DECLARE 文 キーワード SCROLL 212 説明 210 FOR INSERT 節 227 FOR UPDATE 232 WITH HOLD 節 256 DECODE 関数 108 DEF_TABLES_LOCKMODE 構成パラメー タ 242 DELETE 文 埋込み 200, 223 カーソルの使用 226 行 (ROW) 型 155 行数 203 行のカウント 224 コレクション (COLLECTION) 型 156 作成 156 処理 217 静的埋込み 211 199 単一行の選択 206 での INSERT 227 での UPDATE 231 動的埋込み 200, 216 標識変数 207 プリプロセッサ 198 ホスト変数 200, 201 ホスト変数を区切る 200 DELETE 文 223 SQL 通信領域 (SQLCA) 201 SQLCODE 202 SQLERRD フィールド 203 EXECUTE FUNCTION 文 SPL で 315 EXECUTE IMMEDIATE 文、説明 219 EXECUTE PROCEDURE 文 SPL で 315 Execute アクセス権 キーワード DBA、影響 323 ルーチンが参照するオブジェクト 323 EXTEND 関数 式での使用 93 日付 (DATE) 型、日時 (DATETIME) 型、および時間隔 (INTERVAL) 型 89 GET DIAGNOSTICS 文 205 GLS 参照: 広域言語サポート GRANT 文、埋込み SQL で 220, 221 GROUP BY 節 説明 114 GROUP BY 節と HAVING 節の使用 114 H HAVING 節、説明 114 HEX 関数、式での使用 107 HOLD カーソル、定義 255 I IF 文、SPL 内 288 IFX_DEF_TABLE_LOCKMODE 環境変数 242 IN 関係演算子 132 INFORMIXDIR/bin ディレクトリ xv INITCAP 関数、文字列操作関数として 100 INSERT カーソル 使用 229 定義 227 INSERT 文 埋込み 227 およびデータの終わり 231 行 (ROW) 型で 160 行数 203 索引 359 INSERT 文 (続き) コレクション (COLLECTION) 型列 162 コレクション内の NULL 値 シリアル値 158 上位表へ 163 159 挿入 コレクション 162 MONTH 91 MONTH 関数、時刻関数として 89 名前付き行 (named row) 型 関数 40 ESQL 内での検出 NVL 関数 207 110 229 ロック モード 251 SELECT の制約事項 164 SELECT 文 164 SELECT 文で 164 VALUES 節 157 INSERT の制約事項 INTO 節 211 164 ISAM エラー コード 203 ISO 8859-1 コード セット xiv, 32 ISOLATION_LOCKS 構成パラメータ O 247 176 328 ユーザが生成するエラー 330 onload ユーティリティ 189 onunload ユーティリティ 189 210 OR 関係演算子 OR 論理演算子 38 40 LENGTH 関数 84 可変長文字 (VARCHAR) 型 105 式での使用 105 テキスト (TEXT) 型またはバイト (BYTE) 型文字列 105 LET 文 282 LIKE 節 SPL 関数内 278 LOCK TABLE 文、明示的に表をロック 239 LOWER 関数、文字列操作関数として 99 LPAD 関数、文字列操作関数として 103 MATCHES 関係演算子 ロケールの影響 45 WHERE 節内 41 MAX 関数、集計関数として 86 MDY 関数、時刻関数として 89 MIN 関数、集計関数として 86 360 PREPARE 文 説明 217 複数の SQL 文 218 SQLERRD のエラー戻り 203 PROCEDURE 型変数 279 PUT 文 状態コード 228 挿入された行のカウント 228 データの挿入 227 の定数データ 229 戻されたデータのバッファへの送信 228 RAISE EXCEPTION 文 328 RANGE 関数、集計関数として 87 REPLACE 関数、文字列操作関数として 100 REVOKE 文、埋込み SQL で 220, 221 ROLLBACK WORK 文 カーソルのクローズ 255 ロック解除 244, 255 SQLCODE の設定 225 IBM Informix: SQL ガイド: チュートリアル 84, 107 関数の使用 84 キーワード ALL 132 キーワード ANY 133 18 行 (ROW) 型の選択 結合 57 結合された表 高度 114 69 67 コレクション (COLLECTION) 型導出 表 141 コレクション (COLLECTION) 型の副 問合せ 139 コレクションの式 自然結合 集計関数 集合演算 R M 209, 210 123 138 コレクションへのアクセス サブ文字列の選択 31 P L 34, 206 206, 208 基本的な概念 エラーのトラッピング 制御範囲 329 OPEN 文 104 キーワード DISTINCT 27 キーワード EXISTS 136 ON DELETE CASCADE オプション ON EXCEPTION 文 INSTEAD OF トリガ 343 INTO キーワード 24 カーソル 外部結合 40 39 論理演算子 160 名前なし行 (unnamed row) 型 160 24 SELECT の昇順 SELECT 文 埋込み NULL 値 テスト 228 SELECT の降順 アクティブ セット NOT 論理演算子 162 RPAD 関数、文字列操作関数として S 使用、時刻関数 N 複数行 164 挿入された行のカウント の定数データ MONTH 関数 163 スマート ラージ オブジェクト 説明 157 選択された列 MODE ANSI キーワード、トランザクシ ョンの指定 187 69, 75 60 84, 93 142 使用 結合 20 射影 選択 19 18 スタンドアロン 341 スマート ラージ オブジェクト関数 97 説明 16 セルフ結合 120 選択式 49 選択リスト 19, 22 単一行 34, 206 単一表 22, 107 単純 16 データの終わり復帰コード 231 トリガ アクションの実行 341 の日付関数 89 排他レベル 245 表示ラベル 51 フォーム 17 複合問合せ 142 複数表 56 副問合せ 130 別名 64 SELECT 文 (続き) SPL ルーチン (続き) ESQL を使用した INTO 節 206 FIRST 節 47 実行 使用 GROUP BY 節 データの引き渡し HAVING 節 114 定義 117 SQLCODE フィールド (続き) シグナル通知されるデータの終わり 208 315 261 説明 340 INTO TEMP 節 66 ORDER BY 節 24 デバッグ 326 動的ルーチン名指定 UNION 演算子 142 トリガ アクションとして のテキスト の例 271 SET ISOLATION 文 非トリガ列を更新する SET LOCK MODE 文、説明 245 戻りの型 および SET ISOLATION SQLERRM 文字列 274 SQLSTATE 値 SET 節、UPDATE 文 168 SITENAME 関数、SELECT 文内 107 SPL EXECUTE PROCEDURE EXIT 文 291 FOR ループ 289 IF..ELIF..ELSE 構造 SELECT 文内 110 文ブロック 284 変数への値の代入 282, 284 FOREACH ループ 285 SYSPROCPLAN 262 TRACE 文 344 WHILE ループ 289 SQL との関係 261 WITH LISTING IN 節 270 SPL 関数 コレクション (COLLECTION) 型デー タ問合せ 302 定義 261 動的ルーチン名指定 319 バリアントと非バリアント 268 ラージ オブジェクト変数 276 CALL 文 317 WITH 節 268 SPL ルーチン アクセス権 320 値の戻り 291 埋込み言語で 272 エラー検出 324 概要 261 行 (ROW) 型データ 294 構文エラー 324 コメント 271 固有名 265 コレクション (COLLECTION) 型 295 コンパイラ メッセージ 325 削除 272 作成 262 システム カタログ エントリ 325 340 208 SQLSTATE、問題のある値 SQLWARN 配列 208 説明 204 命名構文 201 288 SPL 関数での名前の混同 SQL 式 284 XPS で SQL 205 205 カーソルを使用して 211 ANSI 標準準拠でないデータベースで パラメータ リスト 265 プログラム変数 200 LET 文 282 RETURN 節 267 228 SQLSTATE 変数 291 例外 328, 331 CONTINUE 文 291 344 224 203 挿入された行のカウント 命名構文 201 270 使用 245 SET キーワード、UPDATE 文内 166 カーソルの使用 285 トリガ アクションのトレース 説明 340 267 ループの終了 245 行のカウント 231 削除された行のカウント ピリオド表記 294 へのコメントの追加 231 SQLERRD 配列 339 325 変数、の範囲 253 SET TRANSACTION 文 224 PUT 文で設定 228 SELECT のみのデータの終わり 319 UPDATE 文内 166, 167 SET COLLATION 45 および SET TRANSACTION 使用 245 202 DELETE 文で設定 261 PREPARE 文で 217 START VIOLATIONS TABLE 281 182 STDEV 関数、集計関数として 88 stores_demo データベース xv SUBSTR 関数、文字列操作関数として 262 102 SUBSTRING 関数、文字列操作関数とし アプリケーション プログラム インタ ーフェイス (API) 198 て 101 SUM 関数、集計関数として アプリケーション言語 エラー処理 208 カーソル 209 superstores_demo データベース xv sysprocbody、システム カタログ表 325 SYSPROCPLAN 静的埋込み 説明 10 199 SPL ルーチン 199 対話型使用 11 動的文 200 ヒストリー 10 標準化 10 ANSI 標準に準拠した文 11 Informix SQL と ANSI SQL 11 SQL コード xx SQL 通信領域 (SQLCA) 行の挿入 228 説明 201 トランザクションの終わりに変更 SQL 文キャッシュ 256 SQLCODE データの終わり 211 負の値 208 SQLCODE フィールド および FLUSH 操作 229 カーソルのオープン後 210 87 262 T 225 TODAY 関数、定数式内 106, 158 TO_CHAR 関数、変換関数として 94 TO_DATE 関数、変換関数として 95 TRACE 文 出力 344 SPL ルーチンのデバッグ 326 TRUNCATE TABLE 文 154 TRUNCATE TABLE を使用した削除 154 U UNION 演算子、表示ラベル 146 UPDATE カーソル 250 UPDATE カーソル、定義 232 索引 361 WHERE 節でのワイルドカード比較 UPDATE 文 一様値を使用 埋込み 231 およびデータの終わり 231 の使用 270 行 (ROW) 型で 168 行数 203 結合を使用した列の更新 WITH 節、SPL 関数内 268 172 コレクション (COLLECTION) 型 170 処理 217 上位表で 170 障害 41 WHERE 節内のキーワード NOT BETWEEN 37 WITH LISTING IN 節、SPL ルーチンで 167 X X/Open 準拠レベル xxii 184 スマート ラージ オブジェクト 説明 166 副問合せの制約事項 ロック モード SET 節 171 Y 167 YEAR 関数 251 時刻関数として 使用 92 168 WHERE 節 166 UPPER 関数、文字列操作関数として USER 関数、式内 89 99 105 [特殊文字] V !=、等しくない、関係演算子 35 =、等しい、関係演算子 35, 58 VALUES 節 可能な値 ?、疑問符 PREPARE 文の位置指定子として 158 >=、より大か等しい、関係演算子 制約事項 158 選択された列 159 INSERT 文内 157 NULL 値 161 VARIANCE 関数、集計関数として 88 W WEEKDAY 関数 時刻関数として 89, 92 使用 91 WHERE CURRENT OF 節 DELETE 文内 226 UPDATE 文内 232 WHERE 節 関係演算子 34 キーワード NOT を使用 37 キーワード OR を使用 38 説明 34 等号関係演算子 35 内のホスト変数 206 の日付関数 92 比較条件 34 ブール (BOOLEAN) 式 40 副問合せ 132 不等号関係演算子 35 文字範囲の選択 46 より小関係演算子 36 ワイルドカード比較 41 DELETE 文内 153 UPDATE 文内 166 362 IBM Informix: SQL ガイド: チュートリアル 36 217 Printed in Japan GB88-8633-00