データベース千夜一夜第7回

データの加工命令(1)~レコードの追加とテーブルの作成 長谷川裕行
有限会社 手國堂

SELECTとINSERTの組み合わせ

一般に、INSERT命令はSELECT命令と組み合わせて、「既存テーブルから抽出したレコードを追加する」処理に用います。


- SELECT命令で元データを抽出する -

新たに作ったテーブル「商品在庫減少」に、既存のテーブル「商品_mr」から「在庫数が10未満のレコード」を抽出して追加します。レコードの抽出には、既に説明してきたようにSELECT命令を用います。

ここで、新規テーブル「商品在庫減少」のフィールド構成が、「商品_mr」とは異なることに注意してください。「商品在庫減少」は「商品ID、品名、在庫」の3つのフィールドだけで構成されています。

そのためSELECT命令では、「商品_mr」からこれら3つのフィールドだけを抜き出します。そして「在庫数10未満のレコード」は、WHERE句で条件式を設定して抽出します。SQLは以下のようになります。

  SELECT 商品ID, 品名, 在庫 FROM 商品_mr WHERE 在庫 <10

試しに、この命令文だけを実行してみましょう。この段階では、単にレコードセットに7件のレコードが抽出されただけで、データベースそのものには何の変化もありません。


- 抽出したレコードを追加する -

こうしてSELECT命令で抽出したレコード群の行き先を決めるのが、INSERT命令です。

先に説明した方法では、追加先のテーブルとフィールドリストに続けて、フィールドに設定する値を「,」で区切った値リストを指定しました。SELECT命令で抽出したレコードを追加する場合は、レコードセットに既に値を持つレコード群が保持されているので、値リストの代わりにレコードセットを指定します。

SELECT命令を他の命令と組み合わせると、SELECT命令で生成されたレコードセットを他の命令中にそのまま利用できます。INSERT命令なら、以下のような書式となります。

  INSERT INTO <追加先テーブル> [(<フィールドリスト>)] (1)
  SELECT <フィールドリスト> FROM <追加元テーブル> [WHERE <条件式>] (2)

(1)が追加先のテーブルにレコードを追加する部分ですが、先ほどと違って「値リスト」がありません。その代わりに(2)でSELECT命令を使ってレコードセットを生成させます。(2)の結果が、そのまま(1)のフィールドリストに対応する値リストとなり、値を持ったレコードが<追加先テーブル>に追加されます。

このように、他の命令の補助としてレコードセットを生成するために用いるSELECT文を「サブクエリ」と呼びます。サブクエリは他にも様々な使い方と規則があるため、INSERT、DELETEなどのデータ加工命令の説明が終わってから、改めて詳しく説明します。


- 抽出と追加を1つの文にする -

さて、これで

  「商品在庫減少」に
  既存のテーブル「商品_mr」から
  「在庫数が10未満のレコード」を抽出して追加する

処理の準備は整いました。これを実現するには、以下のようなSQLを記述します。

  INSERT INTO 商品在庫減少 (3)
  SELECT 商品ID, 品名, 在庫 FROM 商品_mr WHERE 在庫 <10 (4)

(3)ではフィールドリストを指定する必要はありません。(4)のSELECT命令で指定しているフィールド構成が、(3)追加先テーブルにそのまま反映されます。そのためSELECT命令で抽出するレコードセットのフィールド構成が、追加先テーブルのフィールド構成と同じでなければなりません。


- フィールドリストの指定 -

フィールドリストを指定して以下のように記述してもエラーにはならず、命令は正しく処理されます。

  INSERT INTO 商品在庫減少 (商品ID, 品名, 在庫)
  SELECT 商品ID, 品名, 在庫 FROM 商品_mr WHERE 在庫 <10

但しこの方法は無駄が多く、間違いの元になります。フィールドリストを指定するのは、SELECT命令で抽出したレコードのフィールド数が、追加先テーブルのフィールド数より少ない場合です。

  INSERT INTO 商品在庫減少 (商品ID, 在庫)
  SELECT 商品ID, 在庫 FROM 商品_mr WHERE 在庫 <10

上のようにすると、「商品在庫減少」の「品名」フィールドにはNULLが設定されます。このように追加先テーブルのフィールド構成と異なるフィールドのレコードセットを用いて追加する場合は、必ずフィールドリストを指定します。この場合にフィールドリストを省略すると、以下のようなエラーメッセージが返されます。

  挿入エラー : 列名または列数の値がテーブルの定義と不一致です。


- フィールド名が異なる場合の対処 -

処理によっては、SELECT命令の対象となる追加元テーブルのフィールド名が、追加先のフィールド名と異なる場合もあるでしょう。そのような場合にはSELECT文の側でAS句を使い、追加元テーブルのフィールドに追加先テーブルと同じ名前の“別名(エイリアス)”を付けます。

例えばテーブル「商品在庫減少」のフィールド構成が

  商品番号、製品名、在庫数量

となっていた場合、以下のようなSQLを記述します。

  INSERT INTO 商品在庫減少
  SELECT 商品ID AS 商品番号, 品名 AS 製品名, 在庫 AS 在庫数量
  FROM 商品_mr WHERE 在庫 <10

AS句による別名指定と先に紹介した「フィールドリストを用いて一部のフィールドだけに値を設定する方法」とを組み合わせれば、まったく異なるフィールド構成のテーブルから必要なフィールドだけを抜き出してレコードを追加できます。



- データ型の対応に注意 -

追加先のフィールドと、それに対応するとSELECT命令で抽出するフィールドのデータ型とは、基本的に同じでなければなりません。

但し、整数型同士なら異なっていてもエラーにはなりません。

追加元が文字列型で追加先が数値型のような場合はエラーになります。追加先が文字列型なら、追加元が数値型の場合は文字列に変換されます。

文字列型同士の場合はエラーにはなりませんが、追加先の方が桁数が少ない場合、値の後部が切り捨てられる場合があります。

数値型でも追加先がintで追加元がlongのように桁数が異なっていれば、やはり値は切り捨てられます。異なるフィールド構成のレコードセットを追加する場合は、桁数に注意しましょう。



トップページ
データを加工する
レコードの追加~INSERT命令
テーブルを作成する命令~CREATE TABLE
SELECTとINSERTの組み合わせ
SELECT命令で元データを抽出する
抽出したレコードを追加する
抽出と追加を1つの文にする
フィールドリストの指定
フィールド名が異なる場合の対処
データ型の対応に注意
テーブルを作るもう一つの方法~INTO句
あとがき
Copyright © MESCIUS inc. All rights reserved.