一般に、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のように桁数が異なっていれば、やはり値は切り捨てられます。異なるフィールド構成のレコードセットを追加する場合は、桁数に注意しましょう。
|
|
|