# CHAPTER 5: データ操作言語

## 5.1 はじめに

データ操作言語 (DML)コマンドは、ユーザがアクセスするかデータを操作 することを可能にします。利用可能なDMLコマンドの概略を以下に示します。

Table 5-1: データ操作言語コマンド

コマンド | 概要
`INSERT` | テーブルにデータを入力します。
`SELECT` | テーブルから情報を検索します。クエリーは他テーブルとのジョインなど複雑に なるかもしれません。
`UPDATE` | テーブル中の既存レコードを更新します。
`DELETE` | テーブル中の不必要なレコードを削除します。
`EMPTY` | テーブル中の全レコードを削除します。
`CALL` | ストアドプロシージャ-またはエキスプレッション（表現）を呼び出します。
`LOCK TABLE` | トランザクション中にテーブルをロックします。
`SORT` | 一つ以上のフィールドによりテーブルを並び替えます。

## 5.2 INSERT

`INSERT`コマンドは、フィールド値をコマンドラインから、他のテーブル から、ファイルからまたはオペレーティングシステムコマンドの出力から直接取得し、 テーブル中にデータを格納します。

Syntax

  Syntax 1:

  |  |  | `INSERT [INTO] table [(` | `| * |attr {, attr}` | `|)] |`

  |  |  |  |  |  | `|VALUES [(] attr_value {, attr_value} [)] |SET TO attr_value {, attr_value} |select_command |FROM data_source` | `|; | | |`

  Syntax 2:

  |  |  | `INSERT [INTO] table SET attr` | `|TO |=` | `| |` | `attr_value {, attr` | `|TO |=` | `| |` | `attr_value};`

  Syntax 3:

  |  |  | `INSERT [INTO] table SET` | `| * | attr {, attr}` | `| |`

  |  |  |  |  |  | `|VALUES [(] attr_value {, attr_value} [)] |select_command |FROM data_source` | `|; | |`

  説明

  `attr_value` |
  いずれか１つ。 | `|expr |NULL |DIRECT_FROM data_source` | `| | |`
  `expr` | フィールドに与えられた適した値。 詳細はExpressionsを参照してください。
  `data_source` |
  いずれか１つ。 | `|file |!os_command` | `| |`
  `os_command` | システムコマンドの出力がテーブルに直接挿入されます。 Unixにのみ有効な機能です。
  `select_command` | `SELECT`文。`SELECT`を 参照してください。

注意

1. フィールドが指定されない場合、フィールド値は`DISPLAY TABLE`コマンド にリストされる順にフィールドに割り当てられます。いくつかのフィールドが指定 される場合、指定されなかったフィールドには`NULL`値がセットされます。 フィールド値がそれぞれのフィールドに問題なく割り当てられたならば、レコードは テーブルに加えられます。
2. いくつかのレコードを、テーブルに一度に加えることができます。この時 `attr_value`の数はフィールド数の挿入数分なくてはいけません。 数が一致しない場合、最後の不完全なレコードはテーブルに挿入されずに エラーメッセージを表示します。
3. コマンド`DIRECT_FROM data_source`は、ファイルあるいは オペレーティングシステムコマンドの出力から直接`BULK`または`TEXT` のデータを読込みます。
4. 文字列または日付の`attr_value`は、引用符で囲む必要があります。 しかし数値の値(`DECIMAL`,`DOLLAR`,`INTEGER`, `SHORTINTEGER`,`LONGINTEGER`,`FLOAT`,`LONGFLOAT`) は、引用符で囲ってはいけません。`DOLLAR`データタイプのために、ドル記号 が`attr_value`として含まれている場合、それはもう一つのドル記号 (例えば$$100.00)を前に付けなくてはなりません。これはEmpress変数と分離 するためです。`CHAR`属性に数値または日付の価値を挿入することは可能 ですが、反対のことを行なうとエラーメッセージを表示します。
5. データは`SELECT`コマンドによりテーブルから検索され、 `INSERT INTO table`を指定することにより別のテーブルに挿入する ことができます。挿入されるテーブルが存在しない場合には、そのテーブルはデータ 挿入の前に自動的に作成されます。
   `select_item`がヘッダー(本章中の `SELECT`を参照)を含んでいる場合、ヘッダーは、新しいテーブルの フィールド名として使用されます。
6. ファイルからのテーブルへデータを挿入する場合、ファイル中のデータと、 テーブル用にリストされたフィールドが一致していなくてはなりません。データの フォーマットは次のフォーマットのうちの1つに該当するはずです。

   - `SELECT ... DUMP INTO file;`コマンドと同一フォーマットである。
   - 一つのフィールド値が1行にある。
   - 変数`MSVALSEP`(初期値は<Ctrl+V>)によって指定された文字に よって分離されたフィールド値を備えた1行のデータ当たり1レコード。レコードは 新しい行によって分離されます。新しい行が、`MSLINECONT`(省略値は バックスラッシュ(\))によって指定された行継続文字でつながれている場合、データ行 は1行以上になる場合があります。

   バッチによる挿入(insert .. from ファイル)の場合、途中でエラーが発生すると Empressはエラーメッセージを出力し処理を中止します。その場合、途中まで レコードが挿入されてしまうので、再試行する時にはエラー個所を修正してそのデータ から始めなくてはならなくなり、非常に面倒な作業となります。この場合バッチでの 挿入を再開するベストな方法は以下の方法です。

   - トランザクション開始
   - バッチでの挿入開始
   - 次の操作で挿入完了を保証します。
     - データの挿入が全て成功した場合、トランザクションをコミットする。
     - データの挿入でエラーが発生した場合、トランザクションをキャンセルし、 エラー個所を修正してから再試行する。
7. オペレーティングシステムコマンドからの出力を、直接テーブルに挿入するのは `!os_command`をファイル名の変わりに使用します。オペレーティング システムコマンドは複雑かもしれないし、もし望まれればPIPEを含んでいるかもしれ ません。これはUNIXのみ利用可能です。

必要な特権

- データを挿入するテーブルには`INSERT`特権が必要です。
- データを検索してくるテーブルには`SELECT`特権が必要です。
- 新しいテーブルを作成する場合には`sys_tables`テーブルに`INSERT` 特権が必要です。

例

1. 数値、日付、文字列を持ったレコードを挿入します。

   `loans`テーブルに1990年6月27日にKilroyが$100,00のローンを組んだ レコードを追加します。

          INSERT INTO loans VALUES (10, 'Kilroy', '27 June 1990', 100.00);

   データの順番が重要です。`DISPLAY TABLE`コマンドにリストされた フィールド名を順番に左から右へ指定してください。 順番どおりに指定しない以下のような場合。

          INSERT INTO loans VALUES (10, '27 June 1990', 'Kilroy', 100.00);

   名前フィールドに日付データがセットされ、日付フィールドに名前データがセット されるため、Empressは変換エラーの表示をします。

2. DOLLAR値を持ったレコードを挿入します。

   次のコマンドは、最初の例題と同じ値を挿入することになります。 (ドル記号を2つ指定していることに注意してください。)

          INSERT INTO loans (name, date, amount) VALUES ('Kilroy','27 June
             1990','$$100.00';

3. NULL値を持ったレコードを挿入します。

   `personnel`テーブルの`credit_limit`フィールドと `phone`フィールドにNULL値をセットしてレコードを挿入します。

          INSERT INTO personnel (number, name, phone, credit_limit) VALUES (14,
             'Martin', null, null);

4. 部分的なフィールド値を持ったレコードを挿入します。

   指定されないフィールド値には自動的にNULL値が設定されます。よって前の例題と 同様の結果となります。

          INSERT INTO personnel (number, name) VALUES (14, 'Martin');

5. 様々なシンタックスによりレコードを挿入します。

   対話型でない挿入コマンドのいろいろな形式で、Martinに対して 個人番号は`20`、電話番号は`962-2587`、クレジット限度額 `$500`を`personnel`テーブルに入力します。

          INSERT INTO personnel
               SET number TO 20,
               name TO 'Martin',
               phone TO '962-2587',
               credit_limit TO 500;

          INSERT INTO personnel
               (number, name, phone, credit_limit)
               SET TO 20, 'Martin', '962-2587', 500;

          INSERT INTO personnel
               SET TO 20, 'Martin', '962-2587', 500;

          INSERT INTO personnel
               SET number, name, phone, credit_limit
               20, 'Martin', '962-2587', 500;

          INSERT INTO personnel
               SET number, name, phone, credit_limit
               VALUES 20, 'Martin', '962-2587', 500;

6. 複数レコードを挿入します。

   同時に複数レコードを追加します。

          INSERT personnel VALUES
               20, 'Martin', '962-2587', 500,
               21, 'Stevens', '973-7721', 250,
               22, 'DuRoche', '922-8047', 500;

7. 他のテーブルから挿入します。

   `loans`テーブルから`jonesloans`というテーブルを作成します。

          INSERT INTO jonesloans
               SELECT FROM loans
               WHERE name = 'Jones';

   作成されるテーブルは`loans`テーブルと同一の構造ですが、レコードは `name`フィールドのデータが<Jones>のものしか存在しません。

8. ファイルからレコードを挿入します。

   セパレータに`"|"`を設定し、以下のようなデータが入っている `newloans`ファイルからレコードを挿入します。

          10|Kilroy|August 24, 1990|200
          5|Mosca|September 3, 1990|100
          4|Scarlatti|September 23, 1990|75

   以下のコマンドで上記ファイルから3レコード挿入します。

          INSERT loans FROM 'newloans';

9. オペレーティングシステムコマンドから挿入します。

   コメントが記述された`comments.n`ファイルを`nroff`コマンドに 渡した出力を挿入します。

          INSERT customers SET COMMENTS
             DIRECT_FROM '!nroff comments.n';

## 5.3 SELECT

`SELECT`コマンドはテーブルからデータを検索します。検索結果は スクリーン上にテーブルとして表示されます。しかしリスト形式で表示したり オペレーティングシステムに転送したりできます。 コマンドには最低でも１つ以上のテーブルを指定しなければなりません。指定できる ものには以下のようなものがあります。

- 出力のカラムを構成する項目のリスト。項目にはフィールド名、フィールドを含む 関数名や式などがあります。このリストを指定しない場合には全フィールドが `DISPLAY TABLE`コマンドで表示される順番で検索されます。 リストを指定した場合には出力はリストの順番に並べ替えられます。また各項目には `PRINT`句が指定でき`PRINT`句にはカラムの表示やレイアウトのために、 見出しや幅の指定ができます。
- 特定の条件で検索するために`WHERE`句があります。`WHERE`句は ブール式（真また偽のいずれかで評価）で構成されます。指定された全条件を満たした レコードが出力されます。また複数テーブルへのアクセスを可能とするジョイン条件を 設定するのに使用されます（詳細はWHERE句 を参照)
- フィールドのリストに従って出力をグループ化する`GROUP BY`句。リスト に指定したフィールド値が同一であるレコードはまとめて表示されます。 グループ化の優先順位はリストの左から右への指定に従います。リストのフィールドに 基づくグループは、リストで左側に指定されたフィールドのサブグループになります。 `GROUP BY`句の指定がない場合、出力全体が1つのグループと解釈されます。 (詳細はGROUP BY句を参照)
- 特定の条件を満たすグループを制限する`HAVING`句。`HAVING`句 は、ブール式で構成され、条件を満たす各グループが出力されます。(詳細は HAVING句を参照)
- 各グループで出力を順番付けるのは`SORT`句、または`ORDER BY`句 です。

Syntax 1

      SELECT [|BYPASS     |] [|DISTINCT|] [|*                          |]
              |BYPASS_LOCK|   |ALL     |   |select_item {, select_item}|

         FROM table_expression {, table_expression }

            [where_clause]

            [GROUP BY attr {, attr}]

            [having_clause]

            [sort_clause]

            [|LIST  |] [DUMP] [|INTO| file];
             |REPORT|          |ONTO|

Syntax 2

      SELECT [|BYPASS     |] [|DISTINCT|] [|*                          |]
              |BYPASS_LOCK|   |ALL     |   |select_item {, select_item}|

         FROM table_expression {, table_expression }

            [|LIST  |] [DUMP] [|INTO| file]
             |REPORT|          |ONTO|

            [where_clause]

            [GROUP BY attr {, attr}]

            [having_clause]

            [sort_clause];

Syntax 3

      SELECT [|BYPASS     |] [|DISTINCT|] [|*                          |]
              |BYPASS_LOCK|   |ALL     |   |select_item {, select_item}|

         FROM table_expression {, table_expression }

            [where_clause]

            [GROUP BY attr {, attr}]

            [having_clause]

            [sort_clause]

         INSERT [INTO] table [|(attr {, attr})  |] ;
                              |SET *             |
                              |SET attr {, attr} |
                              |(*)               |

Syntax 4

      TABLE table [ sort_clause ]

                   [ |LIST  | ] [DUMP] [ |INTO| file ];
                     |REPORT|            |ONTO|

Syntax 5

       query_expression  [ |LIST  | ] [DUMP] [ |INTO| file ]
                           |REPORT|            |ONTO|

                            [ sort_clause ];

説明

  `select_item` | いずれか１つ。
       |table.*                                   |
       |alias.*                                   |
       |expr                       [print_clause] |
       |column_alias = expr                       |
       |function ([DISTINCT] attr) [print_clause] |
       |COUNT [|(*)              |][print_clause] |
               |([DISTINCT] expr)|
  attrのデータタイプがbulkまたはtextの場合。
        attr |DIRECT_INTO| file
             |DIRECT_ONTO|
  `table_expression` | いずれか１つ。
      a) table [[| ALIAS |] alias ]
                 | AS    |

      b) ( query_expression ) alias

      c) table_expression CROSS JOIN table_expression

      d) table_expression NATURAL |INNER         | JOIN table_expression
                                  |LEFT  [OUTER] |
                                  |RIGHT [OUTER] |
                                  |FULL  [OUTER] |

      e) table_expression  |INNER         | JOIN table_expression
                           |LEFT  [OUTER] |
                           |RIGHT [OUTER] |
                           |FULL  [OUTER] |

               | ON where_clause_condition |
               | USING ( attr {, attr } )  |
  `expr` | 表現式です。詳細はExpressions を参照してください。
  `column_alias` | 出力時にフィールド名に換えて表示する名前です。
  `function` | 集計関数の１つを指定します`AVG`, `MAX`, `MIN`, `SUM`。 複数レコードに対して実行されます。関数は指定されたフィールドに対して実行され 結果を出力します。関数`SUM`と`AVG`は数値フィールドのみ有効です。 詳細は、Functionsを参照してください。
  `print_clause` |
      |PRINT| header [WIDTH integer][ |LEFT      |]
      |AS   |                         |RIGHT     |
                                      |CENTRE    |
                                      |CENTER    |
                                      |LEFTRIGHT |

                [WRAPMARGIN integer]
  `sort_clause` | 以下のシンタックスです。
        |SORT | [ |BY|] |attr      | [|ASCENDING |]
        |ORDER|   |ON|  |attr_num  |  |ASC       |
                        |column_num|  |DESCENDING|
                                      |DESC      |

           {, |attr      | [|ASCENDING |]}
              |attr_num  |  |ASC       |
              |column_num|  |DESCENDING|
                            |DESC      |
  キーワード`ASC`と`DESC`は、それぞれ `ASCENDING`と`DESCENDING`の同義語です。省略値は`ASCENDING` です。 `SORT`と`ORDER`は同義語です。
  `having_clause` | シンタックスはHAVING句を参照 してください。
  `where_clause` | シンタックスはWHERE句を参照 してください。
  `query_expression` | １つ以上のselect_commandを含み、演算子で繋がれています。 `UNION`は、`EXCEPT`と`INTERSECT`をサポートしています。 `query_expression`は以下のようになります。
          |select_command| { |UNION    | [ALL] |select_command| }
          |TABLE table   |   |EXCEPT   |       |TABLE table   |
                             |INTERSECT|
  `UNION`は、全ての重複値以外に一方の`select_command`によって検索 された、すべてのレコードを返します。 `UNION ALL`は、重複値を含む、`select_command`で検索された、両方の レコードを返します。 `EXCEPT`は、すべての重複値以外に、2つの`select_command` オペランドによって選択された2セットのレコードの間の違いを返します。 `ALL`オプションは重複値を含みます。 `INTERSECT`は、すべての重複値以外に、2つの`select_command` オペランドによって選択されたレコードの2つのセットの交差を返します。 `ALL`オプションは重複値を含みます。 `UNION`、`EXCEPT`あるいは`INTERSECT`操作の2つの `select_command`オペランドは、同一でなくてはいけません。 それらの`select_items`が同数のフィールドを持たなくてはいけないことを 意味します。また対応するフィールドは、同じデータタイプでなくてはいけません。 `UNION`、`EXCEPT`、`INTERSECT`操作の結合した結果は、 フィールド、フィールド名(別名)、対応するデータタイプの、第1の `select_command`オペランドの`select_item`と同じ数を持っています。
  1. `select_command` | どちらか一方。
             SELECT  [ |DISTINCT| ] | *           |
                       |ALL     |   | select_item |

                FROM [OUTER] table [ [ALIAS] alias]
                  {, [OUTER] table [ [ALIAS] alias]}

                        [ where_clause ]

                        [ GROUP BY attr {, attr} ]

                        [ having_clause ]
  2.         TABLE table

注意

1. `DISTINCT`オプションは、出力から重複レコードを除外します。 (`UNIQUE`と`DISTINCT`は同義語)`ALL`は省略しても有効で あり、重複値を含んで出力するオプションです。`SELECT`文では `DISTINCT`を何度も使用できることに注意する必要があります。 集計関数以外で使用する場合には、処理される全フィールドを`GROUP BY`句で 指定する必要があります。
2. `BYPASS_LOCK`オプションは、データベースからロックの有無に関係なく データを読み込むことを可能にしています。ダーティリード機能は特権を無視しません。 詳細はEmpress: Database Administrator's Guideを参照してください。
3. アスタリスク(*)を指定すると、全フィールドが選択されます。フィールドの リストが指定された場合には、指定フィールドがカラムを構成します。フィールド名に テーブルの指定がなく、複数テーブルからの検索の場合、最初に指定されている テーブルからフィールドは選択されます。
4. `print_clause`句において、`header`文字列にコロン、 セミコロン、ピリオド、スラッシュ、ブランク、改行コードを使用する場合には、 文字列を引用符で囲む必要があります。ボックス、行、カラムと見出しの間の罫線、 カラム幅を設定するためにEmpressの変数が提供されます。
5. `table [ALIAS] aliasname`と指定すると、データの検索 テーブルを別名付きで指定できます。`aliasname`を指定した場合、 コマンド中のテーブル名の指定にエリアス名を使用することができます。
6. キーワード`OUTER`は`SELECT`文の中でテーブルの外部結合に使用 します。外部結合はシンプルなジョインと内部結合でないレコードを出力します。
7. `LIST`オプションは1行あたり1フィールド値を出力します。フィールド名 （またはヘッダー)、コロン、スペースが行の先頭でフィールド値の前に出力され、 ブランク行でレコードを分離します。
8. `REPORT`オプションは、`DUMP`オプションと併用して使用します。 これによって`DUMP`の出力の前にフィールド名とデータタイプが出力されます。
9. `DUMP`オプションはフィールド名の出力を抑制し、値だけを出力します。 この値はEmpressの変数に設定されているセパレータ（変数`MSVALSEP` で初期値は<CTRL+V>)によって分離されます。 `LIST`オプションが同時に指定された場合には、フィールド値は1行に1つずつ 出力されフィールド名は出力されません。
10. コマンドの出力は、`INTO`または`ONTO`とファイル名の指定により 端末だけでなく、ファイルへ転送することができます。この場合、`INTO`は 上書きし`ONTO`は追記します。ファイルが存在しない場合は作成します。
11. `where_clause`は、検索に条件を与え満たすレコードのみを検索 します。`GROUP BY`句はフィールド値が同一であるレコードをグループ化 します。この処理はフィールドに基づくソートでもあります。 `HAVING`句は、条件を満たすグループのみを出力します。`HAVING`句を 使用できるのは、選択した各項目がグループ化した関数、または定数である場合だけと なります。
12. `sort_clause`は指定されたフィールド名、フィールド番号あるい は出力カラム番号により出力をソートします。グループがコマンドの中で形成される 場合、ソートはグループ内で行なわれます。

    フィールド名の変わりに番号が指定された場合、出力カラムの指定がある場合 には、その順番によりソートし、それ以外データディクショナリーで指定されている フィールド番号によりソートします。

    表現式からソートする場合などは、`column_num`でのソート指定は 有効となります。例えば以下のような場合。

           SELECT a * b, c, d, e * d FROM T1, ORDER BY 1;

    出力は`a * b`の結果によってソートされます。

13. サブシーケンスおよびネストされた`SELECT`文のシンタックスは、 マニュアルEmpress SQL: User's Guideの サブシーケンスで解説します。
14. `COUNT`機能は、検索されたレコード数を表示します。アスタリスク(*)は 検索されたレコードをすべて数えるために使用されます。`DISTINCT`が指定 された場合、同一値でないレコードを検索し数えられます。選択された項目のリスト には、DISTINCTが一度しか使用できないことに注意してください。
15. `INSERT INTO table`が`SELECT`コマンドと共に指定された 場合、端末の変わりにテーブルまたはファイルへ`SELECT`の出力を行います。 テーブルが存在しない場合には検索元のテーブルと同一の構造をもったテーブルが 作成されます。

    `INSERT INTO table` が`SELECT`文の前に指定される場合も あります(`INSERT INTO table SELECT FROM table...`)。

    フィールドがそのとき既存のテーブルに挿入される場合、既存テーブルから 選ばれたフィールドは対応するリスト中で`attrs`を指定することに より、新しいテーブル中で改名することができます。これは、少数のフィールド値を 備えたレコードが既存のテーブルに加えられることを可能にします。 さらに、作成される新しいテーブル中のフィールド名およびオーダーを変更する メカニズムを提供します。

    `select_item`が`header`(文字列、ブランクを 含んでいる場合には引用符で囲む)を含んでいる場合、新しいテーブル中の対応する フィールドは既存のテーブル中の名前ではなく`header`によって与え られた名前になります。これは既存のテーブルのフィールド名には影響しません。 `header`および`attr`の両方が指定される場合、 `attr`は、新しく作成されたフィールド名としてヘッダーより優先 します。

    `GROUP BY`句が使用される場合、出力はレコードからのみになります。 関数結果が各グループの下で表示される出力はエラーとなります。`GROUP BY`句 の使用はGROUP BY句で解説します。

    検索されたテーブルにデータを挿入することができないことに注意してください。

16. Syntax 4は、以下のコマンドと同一です。

            SELECT * FROM table

            [ sort_clause ]

            [ |LIST  | ] [DUMP] [ |INTO| file ];
              |REPORT|            |ONTO|

必要な特権

- 該当テーブルに`SELECT`特権が必要です。
- `INSERT INTO table`を行なう場合、テーブルを作成する必要が あれば`sys_tables`に`INSERT`特権が必要です。
- ダーティリードするテーブルには`BYPASS_LOCK`特権が必要です。

例

シンプルな検索

1. `loans`テーブルの検索

          SELECT * FROM loans;

   以下の表示を行います。

          number     name            date                    amount

           5          Mosca           2 February 1990        $150.00
           3          Jones           7 February 1990         $33.95
          10          Kilroy         16 February 1990        $250.00
          17          Wladislaw      27 February 1990         $55.00
           3          Jones           3 April 1990            $25.00
           5          Mosca           4 May 1990             $200.00
          17          Wladislaw      12 May 1990              $25.00
           8          Peterson        6 June 1990             $50.00
          17          Wladislaw      25 June 1990             $75.00
           3          Jones          12 August 1990          $300.00
           4          Scarlatti       9 September 1990       $150.00
           4          Scarlatti      14 October 1990         $125.00

   以下のコマンドでも同一の結果が得られます。

          SELECT FROM loans;

2. シンプルな条件検索

   1990年6月以降のローンの検索

          SELECT * FROM loans WHERE date > "31 May 1990";

   以下のように表示します。

          number      name          date                  amount

           8          Peterson       6 June 1990           $50.00
          17          Wladislaw     25 June 1990           $75.00
           3          Jones         12 August 1990        $300.00
          10          Kilroy        27 June 1990          $100.00
           4          Scarlatti      9 September 1990     $150.00
           4          Scarlatti     14 October 1990       $125.00

3. 複数の条件検索

   customersテーブルからLucas、Wilson、Marshallを検索します。

          SELECT * FROM customers WHERE name MATCH "*Lucas*"
             OR name MATCH "*Wilson*"
             OR name MATCH "*Marshall*";

   以下のように表示します。

          name             address                comments

          Mr. R. Lucas     1423 Beach Drive,      Can always be sold
                           Bayville, CA 92308     something new and
                                                  flashy - likes chrome
                                                  and colored stuff, also
                                                  little gadgets.

          Mr. B. Wilson    14 Valley View Drive,  Good customer - give
                           Bayville, CA 92308     credit if he asks for it

          Ms. C. Marshall  12 Berkeley St.        Suggest vacuum &
                           Gull Point, CA 92309   wash, she keeps 3
                                                  dogs. Look for dog hair
                                                  collecting in engine.

4. 1つのフィールドを検索します。

   特定フィールドを指定して検索できます。

          SELECT name FROM personnel;

   以下のように表示します。

          name

          Kilroy
          Mosca
          Wladislaw
          Jones
          Peterson
          Scarlatti
          Jordan

5. 複数のフィールドを指定したシンプルな条件検索。

   `personnel`テーブルから`credit_limit`フィールド値が$250.00 より多い、`name`フィールドと、`number`フィールドを表示します。

          SELECT name, number
             FROM personnel WHERE credit_limit > 250.00;

   以下のように表示します。

          name       number

          Kilroy     10
          Mosca       5
          Jones       3

6. 異なるオーダーのフィールドを検索します。

   テーブル作成時の指定フィールド順と違う順番で、表示します。

          SELECT amount, name, date FROM loans;

   以下のように表示します。

          amount      name          date

          $150.00     Mosca          2 February 1990
           $33.95     Jones          7 February 1990
          $250.00     Kilroy        16 February 1990
           $55.00     Wladislaw     27 February 1990
           $25.00     Jones          3 April 1990
          $200.00     Mosca          4 May 1990
           $25.00     Wladislaw     12 May 1990
           $50.00     Peterson       6 June 1990
           $75.00     Wladislaw     25 June 1990
          $300.00     Jones         12 August 1990
          $150.00     Scarlatti      9 September 1990
          $125.00     Scarlatti     14 October 1990

7. フィールドにヘッダーを付けて検索します。

   `PRINT`句を指定しフィールドにヘッダーを付加します。文字列にブランク、 ピリオド、スラッシュ、コロン、セミコロン、タブ、改行コードが含まれる場合には 引用符で囲む必要があります。

   コマンド

          SELECT name PRINT Employee,
             amount PRINT "Loan Amount" FROM loans;

   以下のように表示します。

          Employee      Loan Amount

          Mosca         $150.00
          Jones          $33.95
          Kilroy        $250.00
          Wladislaw      $55.00
          Jones          $25.00
          Mosca         $200.00
          Wladislaw      $25.00
          Peterson       $50.00
          Wladislaw      $75.00
          Jones         $300.00
          Kilroy        $100.00
          Scarlatti     $150.00
          Scarlatti     $125.00

   `PRINT`の変わりに`AS`を指定しても同一の結果となります。

          SELECT name AS Employee,
             amount AS "Loan Amount" FROM loans;

   Empressの変数`MSQLSELHEAD`がアンセットされた場合、ヘッダーの 出力は抑制されます。

8. 計算式を含んで検索します。

   計算は検索されたフィールド値に対して行なわれ、単純な表現式や複雑な表現式かもしれません。

   - amount * 2
   - (credit_limit - (amount * 1.02))/credit_limit * 100

   `loans`テーブルに対して`amount`と`amount`の2%と `amount`の2%増量を表示します。

          SELECT name, amount, amount * 0.02 PRINT 'interest',
             amount * 1.02 PRINT 'new balance'
             FROM loans;

   以下のように表示します。

          name            amount           interest    new balance

          Mosca           $150.00          3.00        153.00
          Jones            $33.95          0.67         34.62
          Kilroy          $250.00          5.00        255.00
          Wladislaw        $55.00          1.10         56.10
          Jones            $25.00          0.50         25.50
          Mosca           $200.00          4.00        204.00
          Wladislaw        $25.00          0.50         25.50
          Peterson         $50.00          1.00         51.00
          Wladislaw        $75.00          1.50         76.50
          Jones           $300.00          6.00        306.00
          Scarlatti       $150.00          3.00        153.00
          Scarlatti       $125.00          2.50        127.50

   ドル記号付きで`interest`、`new balance`というヘッダーで表示 します。

          SELECT name, amount,
             amount * 0.02 CONVERT DOLLAR PRINT 'interest',
             amount * 1.02 CONVERT DOLLAR PRINT 'new balance'
             FROM loan;

   以下のように表示します。

          name            amount           interest     new balance

          Mosca           $150.00          $3.00        $153.00
          Jones            $33.95          $0.67         $34.62
          Kilroy          $250.00          $5.00        $255.00
          Wladislaw        $55.00          $1.10         $56.10
          Jones            $25.00          $0.50         $25.50
          Mosca           $200.00          $4.00        $204.00
          Wladislaw        $25.00          $0.50         $25.50
          Peterson         $50.00          $1.00         $51.00
          Wladislaw        $75.00          $1.50         $76.50
          Jones           $300.00          $6.00        $306.00
          Scarlatti       $150.00          $3.00        $153.00
          Scarlatti       $125.00          $2.50        $127.50

9. 複数テーブルから検索し、結果をテーブルに格納します。

   `loans`テーブル、`personnel`テーブルから検索し、 `loanslist`というテーブル名のテーブルを作成し結果を格納します。

          SELECT name PRINT Employee, credit_limit, date, amount
             FROM loans, personnel
             INSERT INTO loanlist
             WHERE loans.name = personnel.name;

   データベース内を参照すると。

          *** repairs ***

          auto parts
          customers
          loanlist
          loans
          personnel

   以下のコマンドを実行すると。

          SELECT * FROM loanlist;

   以下のように表示されます。

          Employee     credit_limit     date                 amount

          Mosca        $750.00           2 February 1990     $150.00
          Jones        $500.00           7 February 1990      $33.95
          Kilroy       $500.00          16 February 1990     $250.00
          Wladislaw     $50.00          27 February 1990      $55.00
          Jones        $500.00           3 April 1990         $25.00
          Mosca        $750.00           4 May 1990          $200.00
          Wladislaw     $50.00          12 May 1990           $25.00
          Peterson     $250.00           6 June 1990          $50.00
          Wladislaw     $50.00          25 June 1990          $75.00
          Jones        $500.00          12 August 1990       $300.00
          Scarlatti    $100.00           9 September 1990    $150.00
          Scarlatti    $100.00          14 October 1990      $125.00

   この新しく作成されたテーブルは、他のテーブル同様に使用できます。

10. UNIONを使用した検索

    2つのテーブル、`loans`と`loanlist`の連携を取得します。

           SELECT name, amount FROM loans
           UNION
           SELECT Employee, amount FROM loanlist;

    UNIONオペレーションのオペランドが同一なくてはなりません。それは、UNION オペレーションの2つのフィールドセットが同数のフィールドを持っていることを 意味します。また対応するフィールドは同じデータタイプでなくてはなりません。

11. 同一のテーブル構造を持つテーブルに対するUNIONを使用した検索。

    `loan`テーブルと`loanlist`テーブルが同一構造であり、2つの テーブルのすべての内容の結合を得たい場合、次の指定をします。

           TABLE loan UNION TABLE loanlist;

## 5.4 UPDATE

`UPDATE`コマンドは、テーブル中にある一つ以上のレコードのフィールド値 を変更します。 Syntax command changes attribute values in one or more existing records in a table.

Syntax

  Syntax 1:

  |  |  | `UPDATE table SET attr` | `|TO |=` | `| |` | `attr_value {, attr` | `|TO |=` | `| |` | `attr_value}`

            [where_clause];

  Syntax 2:

  |  |  | `UPDATE table [` | `|(*) |(attr {, attr})` | `|] |`

  |  |  |  |  |  | `|VALUES [(] attr_value {, attr_value} [)] |attr_value {, attr_value} [END] |SET TO attr_value {, attr_value} |FROM data_source` | `|; | | |`

            [where_clause];

  Syntax 3:

  |  |  | `UPDATE table SET` | `| * | attr {, attr}` | `| |`

  |  |  |  |  |  | `|VALUES [(] attr_value {, attr_value} [)] |attr_value {, attr_value} [END] |FROM data_source` | `|; | |`

            [where_clause];

  説明

  `attr_value` |
  いずれか１つ。 | `|expr |NULL |DIRECT_FROM data_source` | `| | |`
  expr | フィールドに与えられた適した値。詳細は Expressionsを参照してください。
  data_source |
  いずれか１つ。 | `|file |!os_command` | `| |`
  os_command | システムコマンドの出力が、直接テーブルに挿入されます。 この機能はUnixのみ有効です。
  `where_clause` | シンタックスはWHERE句 を参照してください。

注意

1. データ値は、それらに対応するフィールドと同じ順番で指定されます。フィールド がコマンドライン上で指定されている場合には、データもその順番で指定します。 指定されないフィールドは変更されません。
2. 更新するレコードを限定する場合には、`WHERE`句を指定し限定条件を 与えます。
3. テーブルはファイルから更新される場合もあります。ファイル中のデータは1行 当たり1つのフィールド値、あるいは、`MSVALSEP`(初期値は<Ctrl+V>)に よって指定された文字によって分離されたフィールド値を備えた1行当たり1つの レコードです。この場合レコードは新しい行によって分離されます。 新しい行が、`MSLINECONT`によって指定されたライン継続文字で繋がれている 場合、データ行は1行以上の行で分離している場合があります。`MSLINECONT`の 初期値はバックスラッシュ(\)です。
4. 対話型インターフェースの`UPDATE`コマンドを使用して、画面上で対話 形式に1レコードずつ更新していく方法もあります。詳しくは 対話型インターフェースの章を 参照してください。

必要な特権

  `UPDATE`特権

例

1. シンプルな更新

   `loans`テーブル内の全てのレコードに対して日付を、`1990年1月1日` にします。

          UPDATE loans
            SET date = '1 Jan 1990';

2. 特定レコードの更新

   `loans`テーブル中の`name`フィールド`Mosca`を `Kilroy`に変更します。

          UPDATE loans
             SET name TO 'Kilroy'
             WHERE name = 'Mosca';

   この更新では、2レコードしか更新しません。

3. AND結合した条件で更新すいます。

   `loans`テーブル中の日付が`1990年2月2日`で`name` フィールドが`Mosca`のレコードの`name`フィールドを`Kilroy` に変更します。

          UPDATE loans
             SET name TO 'Kilroy'
             WHERE name = 'Mosca'
             AND date = '2 February 1990';

4. OR結合された条件で更新します。

   `loans`テーブルの`name`フィールドが`Mosca`と `Jones`のレコードの、`name`フィールドを`Kilroy`に変更 します。

          UPDATE loans
             SET name TO 'Kilroy'
             WHERE name = 'Mosca'
             OR name = 'Jones';

   `Mosca`と`Jones`を表す場合に、英語での記述は `Mosca and Jones`となりますが、SQLの`WHERE`句での指定は `Mosca or Jones`と指定するということに注意してください。 `WHERE`句で`AND`結合した記述`Mosca and Jones`は レコードを限定できません。

5. いろいろな`UPDATE`コマンドのシンタックス例

   Moscaの電話番号を`928-1796`に、クレジットリミットを`$250.00` に変更するには以下のコマンドを使用します。

          UPDATE personnel
             SET phone TO '923-1796',
             credit_limit TO 250
             WHERE name = 'Mosca';

          UPDATE personnel
             (phone, credit_limit)
             SET TO '923-1796', 250
             WHERE name = 'Mosca';

          UPDATE personnel
             (phone, credit_limit)
             '923-1796', 250 END
             WHERE name = 'Mosca';

          UPDATE personnel
             (phone, credit_limit)
             VALUES '923-1796', 250
             WHERE name = 'Mosca';

          UPDATE personnel
             VALUES 5, 'Mosca', '923-1796', 250
             WHERE name = 'Mosca';

6. 計算して更新します。

   `loans`テーブルの`amount`フィールド値を2%高くして更新します。

       UPDATE loans
            SET amount TO amount * 1.02;

7. ファイルから更新します。

   下に示すデータを含んでいるファイル名を`newlimits`とします。データは 1行ごとか、Empress変数`MSVALSEP`に設定された文字列で分離されて いる必要があります。

          600
          500
          250
          750
          500
          250

   以下のコマンドを使用します。

          UPDATE personnel
             SET credit_limit
             FROM newlimits;

   `SELECT` from `personnel`コマンドは、以下のような表示をします。

          number     name           phone             credit_limit

          10         Kilroy         426-9681          $600.00
           5         Mosca          544-2243          $500.00
          17         Wladislaw      723-6073          $250.00
           3         Jones          667-2951          $750.00
           8         Peterson       978-6060          $500.00
           4         Scarlatti      961-7363          $250.00

## 5.5 DELETE

`DELETE`コマンドは、テーブルから1つ以上のレコードを削除します。

Syntax

      DELETE [FROM] table [where_clause];

  説明

  `where_clause` | シンタックスはWHERE句 を参照してください。

注意

1. `WHERE`条件を満たしたレコードをすべて削除します。

   よって削除対象を指定する条件を設定する際には、十分注意する必要があります。

2. `WHERE`句を指定しない場合、テーブル中の全レコードが削除されてしまい ます。参照制約として削除制約が設定されている場合には、その制約条件を満たす レコードだけが削除されます。尚、`EMPTY`コマンドは削除制約に関係なく テーブル中の全レコードを削除しますので注意してください。
3. 対話型インタフェースの`UPDATE`コマンドにより、1レコードごと に削除することができます。詳細はこのマニュアルの 対話型インタフェースを参照してください。レコード削除には 対話型インタフェースを利用したほうが無難です。

必要な特権

  `DELETE`特権

例

1. シンプルな削除

   `loans`テーブルの`name`フィールドがJonesのレコードを全て削除 します。

          DELETE FROM loans
             WHERE name = 'Jones';

   `Jones`という名前のレコードを全て削除します。

2. `AND`結合した条件で削除します。

   `WHERE`句にレコードを特定するための条件を与えて削除します。 `loans`テーブルの`name`フィールドがJonesで、 `date`フィールドが1990年8月12日のレコードを削除します。

          DELETE FROM loans
             WHERE name = 'Jones'
             AND date = '12 August 1990';

   最も安全な方法は`WHERE`句の中で全フィールドを指定することです。

## 5.6 EMPTY TABLE

`EMPTY`コマンドは指定されたテーブル中の、全レコードを削除します。

Syntax

      EMPTY table;

注意

1. 全レコードが削除されますが、テーブル自体は削除されません。この点で レコードとテーブルを削除してしまう`DROP TABLE`コマンドと違います。
2. `EMPTY`コマンドの使用は、うっかり削除してしまわないように、細心の 注意が必要となります。
3. 回復したスペースは、自動的にオペレーティングシステムに割り当てられます。
4. `EMPTY`コマンドは、削除制約の影響を受けません。
5. `EMPTY`コマンドは古いテーブルファイルを削除する前に、データベース ディレクトリ内に新しいテーブルファイル(`.rel`ファイル)を作成します。 `umask`の設定が変更された場合や、所有者IDが変更された場合には新しい テーブルファイル中のUNIX許可は古いテーブルファイルとは異なる場合があります。

必要な特権

  `EMPTY`特権

例

  `loans`テーブル内の全レコードを削除します。

         EMPTY loans;

## 5.7 CALL

`CALL`コマンドは、表現式を評価したり、ストアドプロシージャを呼び出し ます。

Syntax

  `CALL` | `|expr |procedure_name [([expr {,expr}])]` | `| [ |` | `|INTO |ONTO` | `| filename ]; |`

注意

1. `CALL`コマンドでの表現式には、テーブル名、フィールド名は指定 できません。

2. 対話型SQLでは`CALL`コマンドによるデータタイプの変換はでき ません。

3. プロシージャまたはファンクションのみ呼び出すことができます。集計関数や オペレータが呼び出された場合には、エラーメッセージを出力します。

必要な特権

  なし

例

1. ストアドプロシージャ`log_event`を呼び出します。

          CALL log_event;

2. 本日から32日後の日付を取得します。

          CALL TODAY + 32 DAYS;

3. いくつかの数学関数を呼び出します。

          CALL sin(30);
          CALL cos(60);

## 5.8 LOCK TABLE

しばしば、ある期間内のデータ（テーブルからの読込みまたは更新）について保証 しなくてはならない場合があります。これは、トランザクションの間に `LOCK TABLE`コマンドを使用して、他からのテーブルアクセスを制限すること により行うことができます。`LOCK TABLE`コマンドを発行することにより直ち に機能します。

Syntax

  `LOCK table [IN]` | `|EXCLUSIVE |EXCL |SHARE` | `| [MODE]; | |`

注意

1. テーブルには`排他`モードと`共有`モードでロックすることが できます。`排他`モードのロックは、テーブルへのアクセスを占有します。 `排他`モードでは他のプロセスはテーブルの検索も更新もできなくなります。 またテーブルへのロックの設定もできなくなります。`共有`モードでは、 他のプロセスの検索は可能ですが、更新はできません。

2. 同時に複数のユーザから、`共有`モードのロックが設定される場合には このテーブルは更新できません。1つの`共有`モードしか設定されていない場合 には、設定したユーザのみ更新することができます。トランザクションが終了するまで、 他のプロセスはこの更新されたレコードにアクセスできません。

3. `LOCK TABLE`コマンドでロックレベルを設定してある場合のみ、 `LOCK TABLE`コマンドは有効となります。ロックレベルがnullに設定されて いる場合は、`LOCK TABLE`コマンドは無効となり、null以外であれば設定 レベルに関係なく`LOCK TABLE`コマンドはTABLEレベルのロックを設定します。

4. `排他`モードの`LOCK TABLE`コマンドは、他のプロセスがテーブル のレコードにアクセス（参照または更新）している場合はエラーとなります。 `共有`モードの`LOCK TABLE`コマンドは、他のプロセスがテーブルに 対して更新している場合にはエラーをなります。

必要な特権

  `共有`モードでは、`SELECT`特権と`UPDATE`特権が必要 です。

  `排他`モードでは、`UPDATE`特権、`INSERT`特権、 `DELETE`特権が必要です。

例

  トランザクションが既に開始されていて、トランザクション中は`排他` モードで`loans`テーブルをロックする場合。

         LOCK loans EXCLUSIVE;

  他のプロセスが`loans`テーブルにアクセス中であった場合、以下の メッセージが表示されます。

         *** Lock Busy *** table 'loans' lock busy

## 5.9 SORT

`SORT`または`ORDER`コマンドは、テーブルのデータを並べ替え ます。この並べ替えは１つのフィールドでも複数のフィールドでも行なえ、フィールド ごとに昇順または降順の指定ができます。省略時は昇順です。

Syntax

  `|SORT |ORDER` | `| table [ |` | `|BY |ON` | `|] attr [` | `|ASCENDING |ASC |DESCENDING |DESC` | `|] {, attr [ | | |` | `|ASCENDING |ASC |DESCENDING |DESC` | `|]}; | | |`

注意

1. `SORT`と`ORDER`は同義語です。キーワード`ASC`と `ASCENDING`、`DESC`と`DESCENDING`は同義語です。

2. このマニュアルの`SELECT`の章で解説 するように、`SELECT`コマンドの出力は動的にソートできます。 一般的に変更があまりないテーブルからデータを検索する場合、テーブル中にソート して格納したしたほうが効率的です。変更の頻度が高い場合には、`SELECT` コマンド実行時にソートしたほうが便利です。 しかし、ソートには検索の処理時間に多くの負担をもたらします。

3. システム変数`MSSORTSPACE`は、Empressのメモリスペースを制限 するために使用することができます。詳細は Empress: Database Administra tor's Guideを参照してください。

4. システム変数`MSSORTBYPASS`を指定した場合（初期値では指定されて います）、ロックされたレコードはソートから除外され警告メッセージを出力します。 この変数を指定しない場合には、ロックレコードによりソート処理がエラーとなり、 `lock busy`のメッセージが出力されます。

5. `SORT`コマンドは古いテーブルファイルを削除する前に、データベース ディレクトリ内に新しいテーブルファイル(`.rel`ファイル)を作成します。 このコマンドによって要求されたディスクスペースは少なくとも2倍のテーブルサイズ です。処理が完了し古いテーブルファイルが削除されれば、オリジナルのテーブルに 関連したスペースはオペレーティングシステムによって回復されます。

6. メモリ内でソート処理ができない場合、Empressは`MSTMPDIR` ディレクトリ内のテンポラリファイルを使用します。`SORT`コマンドが完了 した時点でテンポラリファイルは削除されます。

7. `SORT`コマンドは新しいテーブルファイルを作成しますが、そのファイル のUNIX許可および所有者IDは`umask`設定や所有者IDに依存して変更される場合 があります。

8. いかなる状況であっても、データディクショナリーには`SORT`コマンドを 実行してはいけません。

必要な特権

  `SORT`特権

例

  `personnel`テーブルを`number`フィールドの昇順にソートします。

         SORT personnel BY number;

         ORDER personnel BY number;

  ソート後のテーブルを検索します。

         SELECT FROM personnel;

  以下のように表示されます。

         number     name          phone             credit_limit

         3          Jones         667-2951          $500.00
         4          Scarlatti     961-7363          $100.00
         5          Mosca         544-2243          $750.00
         8          Peterson      978-6060          $250.00
         9          Jordan        964-3335          $250.00
         10         Kilroy        426-9681          $500.00
         17         Wladislaw     723-6073           $50.00