INSERT ステートメントは、表または視点に行を挿入します。 行を視点に挿入することは、その行をその視点の基礎表に挿入することでもあります。
呼び出し
このステートメントは、アプリケーション・プログラムに組み込むか、 または動的 SQL ステートメントを使用して発行することができます。 このステートメントは、動的に準備可能な実行可能ステートメントです。
許可
このステートメントを実行するには、ステートメントの許可 ID に、 以下の特権の少なくとも 1 つが含まれている必要があります。
さらに、ステートメントの許可 ID には、 INSERT ステートメントで使用する全選択で参照される表または視点のそれぞれに対して、 以下の特権の少なくとも 1 つが含まれている必要があります。
静的 INSERT ステートメントの場合、GROUP 特権は検査されません。
構文
>>-INSERT INTO----+-table-name-+--------------------------------> '-view-name--' >-----+----------------------------+----------------------------> | .-,--------------. | | V | | '-(-----column-name---+---)--' .-,------------------------------------. V | >-----+-VALUES------+-+-expression-+----------------+--+--------+->< | | +-NULL-------+ | | | | '-DEFAULT----' | | | | .-,-----------------. | | | | V | | | | '-(------+-expression-+--+---)--' | | +-NULL-------+ | | '-DEFAULT----' | '-+---------------------------------------+---fullselect--' | .-,--------------------------. | | V | | '-WITH-----common-table-expression---+--'
注: | common-table-expression (共通表式) と fullselect (全選択) の構文については、 照会 を参照してください。 |
説明
視点の以下のような列には、値を挿入することはできません。
挿入操作の対象となる視点にこのような列がある場合は、 列名のリストを指定する必要があり、そのリストにそれらの列を指定してはなりません。
列のリストを省略すると、 その表または視点のすべての列を左から右に指定したリストが暗黙に指定されます。 このリストはステートメントが準備される時点で確立され、 したがって、ステートメントの準備後に表に追加された列は含まれません。
暗黙の列リストは、準備時に確立されます。 したがって、アプリケーション・プログラムに組み込んだ INSERT ステートメントでは、 準備後に表または視点に追加された列は使用されません。
ホスト変数を指定する場合、それらのホスト変数は、 ホスト変数の宣言規則に従ってそのプログラムで記述されていなければなりません。
各行ごとの値の数は、列リストの名前の数と同じでなければなりません。 最初の値はリストの最初の列に挿入され、2 番目の値は 2 番目の列に挿入されます。 以下同様です。
INSERT の基本オブジェクトおよび全選択の基本オブジェクトまたは全選択の副照会のいずれかが同一の表である場合、 行挿入の前に、全選択が完全に評価されます。
結果表の列の数は、列リストの名前の数と同じでなければなりません。 結果の最初の列の値はリストの最初の列に挿入され、 2 番目の値は 2 番目の列に挿入されます。 以下同様です。
注
この方法は、INSERT のパフォーマンスを大幅に向上させる可能性を持っていますが、 エラー処理が非同期であるために、クリーン・データに対して使用するのが最適です。 詳細については、アプリケーション開発の手引き のバッファー挿入の項を参照してください。
たとえば、EMPID という列が GENERATED ALWAYS 識別列として定義されているとします。 そこで、次のコマンドを入力します。
INSERT INTO T2 (EMPID, EMPNAME, EMPADDR) VALUES (:hv_valid_emp_id, :hv_name, :hv_addr)
すると、エラーが戻されます。
列のリストを指定せずに、GENERATED BY DEFAULT 識別列のある表に挿入するときは、 識別列の値を表す DEFAULT キーワードを VALUES 文節で指定することができます。 DB2 は、指定された値を識別列に生成します。
INSERT INTO T2 (EMPID, EMPNAME, EMPADDR) VALUES (DEFAULT, :hv_name, :hv_addr)
この例では、EMPID が識別列として定義され、この列に挿入される値は DB2 によって生成されます。
たとえば、同じ定義を持つ、T1 と T2 という 2 つの表があるとします。 これらの表にはいずれも列 intcol1 および identcol2 (これらはどちらもタイプ INTEGER の列で、 2 番目の列には識別属性がある) が含まれています。 次のような挿入について考慮します。
INSERT INTO T2 SELECT * FROM T1
この例は、論理的には以下と同じ意味になります。
INSERT INTO T2 (intcol1,identcol2) SELECT intcol1, identcol2 FROM T1
このどちらの場合においても、 INSERT ステートメントには T2 の識別列を表す明示的な値が指定されています。 このように明示的な値を指定した場合は、識別列の値を指定することができます。 しかしこれは、T2 の識別列が GENERATED BY DEFAULT として定義されている場合に限られます。 それ以外の場合は、識別列に値を指定するとエラーが戻されます (SQLSTATE 428C9)。
表に GENERATED ALWAYS 識別列として定義された列がある場合でも、 同じ定義を持つ表から、他のすべての列に伝搬することができます。 たとえば、先に取り上げた例の表 T1 と T2 であれば、 T1 と T2 に含まれている intcol1 の値を以下の SQL で伝搬することができます。
INSERT INTO T2 (intcol1) SELECT intcol1 FROM T1
なお、identcol2 は列のリストで指定されていないため、 この列にはデフォルトの (生成) 値が使用されます。
INSERT INTO IDTABLE VALUES(DEFAULT)識別属性をもつ列が含まれているこの同じ単一列の表に、 1 つの INSERT ステートメントを使用して複数の行を挿入するとします。 その場合は、次のような INSERT ステートメントを使用できます。
INSERT INTO IDTABLE VALUES (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT)
たとえば、識別列に固有の索引が作成されていると想定します。 識別列に対する値の生成で重複キーの違反が検出されると、エラーが戻され (SQLSTATE 23505)、 その識別列に対して生成される値は破棄されることになります。 このエラーが生じる可能性があるのは、識別列が GENERATED BY DEFAULT として定義されており、 システムが新しい値を生成しようとしたものの、 ユーザーが以前の INSERT ステートメントで識別列に明示的な値を指定していた場合です。 このような場合は、同じ INSERT ステートメントをもう一度発行すればうまくいきます。 DB2 は識別列に対して次の値を生成します。 次に生成された値が重複していなければ、INSERT ステートメントは正常に完了します。
たとえば、データ・タイプ SMALLINT で定義されている識別列があり、 この列で割り当てられる値を使い切ってしまったとします。 識別の列を INTEGER として再定義するには、データをアンロードし、表を除去し、 新しい定義の列で表を再作成して、それからデータを再ロードしなければなりません。 そして、表を再定義する際は、DB2 によって生成される次の値が、 元の順序で次の値になるように、START WITH の値を指定しなければなりません。 最後の値を確認するには、データをアンロードする前に、 識別列の MAX (昇順で値を生成している場合) または MIN (降順で値を生成している場合) を使用して照会を実行します。
例
例 1: DEPARTMENT 表に、以下の新しい部門を挿入します。
INSERT INTO DEPARTMENT VALUES ('E31', 'ARCHITECTURE', '00390', 'E01')
例 2: 例 1 と同様に DEPARTMENT 表に新しい部門を挿入しますが、 新しい部門に管理者は割り当てません。
INSERT INTO DEPARTMENT (DEPTNO, DEPTNAME, ADMRDEPT) VALUES ('E31', 'ARCHITECTURE', 'E01')
例 3: 例 2 と同様の DEPARTMENT 表に 2 つの新しい部門を 1 つのステートメントを使用して挿入しますが、 新しい部門に管理者は割り当てません。
INSERT INTO DEPARTMENT (DEPTNO, DEPTNAME, ADMRDEPT) VALUES ('B11', 'PURCHASING', 'B01'), ('E41', 'DATABASE ADMINISTRATION', 'E01')
例 4: EMP_ACT 表と同じ列を持つ一時表 MA_EMP_ACT を作成します。 EMP_ACT 表から、 'MA' で始まるプロジェクト番号 (PROJNO) を持つ行を MA_EMP_ACT 表にロードします。
CREATE TABLE MA_EMP_ACT ( EMPNO CHAR(6) NOT NULL, PROJNO CHAR(6) NOT NULL, ACTNO SMALLINT NOT NULL, EMPTIME DEC(5,2), EMSTDATE DATE, EMENDATE DATE ) INSERT INTO MA_EMP_ACT SELECT * FROM EMP_ACT WHERE SUBSTR(PROJNO, 1, 2) = 'MA'
例 5: C プログラムのステートメントを使用して、 PROJECT 表に骨組みとなるプロジェクトを追加します。 プロジェクト番号 (PROJNO)、プロジェクト名 (PROJNAME)、 部門番号 (DEPTNO)、および責任者 (RESPEMP) は、ホスト変数から入手します。 プロジェクトの開始日 (PRSTDATE) として、現在の日付を使用します。 表のその他の列には、NULL (ヌル) 値を割り当てます。
EXEC SQL INSERT INTO PROJECT (PROJNO, PROJNAME, DEPTNO, RESPEMP, PRSTDATE) VALUES (:PRJNO, :PRJNM, :DPTNO, :REMP, CURRENT DATE);