S-JIS[2009-12-24/2010-07-24] 変更履歴

INSERT文

OracleSQLのINSERT文のメモ。


デフォルト値を指定する例

「default」というキーワードでその項目のデフォルト値をセットできる。

insert into テーブル values(…, default, …);

update文のdefaultキーワード


別テーブルからのデータを挿入する例

別のテーブルからselectによって挿入したいデータを持ってくることが出来る。[2010-02-19]

insert into テーブル
select * from 元テーブル
;
insert into テーブル
select 項目名, … from 元テーブル
where 条件
;

ちなみに、select部でorder byを指定することが出来るが、新しいテーブルからデータを取ってくる際の並び順を指定したいという目的なら、意味が無い。
というのは、結局新しいテーブルからselectする際にorder byを指定しない限り、取得できる並び順は不定になるのが仕様だから。
(が、テーブルのデータの物理的な配置の面では、意味がある…のかなあ?)

insert〜select文の生成を支援するExcelマクロ
create〜selectによるテーブル定義のコピー


インサートする件数の制限

insertでもROWNUM擬似列を使うことが出来る。以下の例では、最大100件挿入される。

insert into テーブル
select * from 元テーブル
where ROWNUM <= 100
;

以下の様にINSERTされた件数を元にプログラムで繰り返せば、n件ずつ分割コミットすることが出来そう。
(ソート処理が入っているからあんまり効率良くなさそうだけど…プライマリキーならソートされている(インデックスが使われる)から大丈夫か?)

while(true) { //無限ループ
1.INSERT文を実行
	insert into テーブル
	select * from (
		select * from 元テーブル
		where キー > 前回最後に処理したキー値
		order by キー
	)
	where ROWNUM <= 100
	;

2.コミット

3.insertの処理件数が100件より小さいなら、ループ終了

4.insertした結果の最大キー値を取得する
	select max(キー) from テーブル;

5.取得した最大キー値を「前回最後に処理したキー値」として、ループの先頭に戻る 
}

存在しないデータだけコピーするINESRT文

insert into テーブル
select * from 元テーブル f
where not exists(
  select * from テーブル t where t.キー = f.キー
);

挿入した値の取得(returning)

returning句を使うと、INSERTした際の値をバインド変数に取り込むことが出来る。[2010-07-24]

insert into テーブル
(項目名…)
values (値…)
returning 項目名… into :バインド変数名…
;

insert-selectの構文では、returningは使うことが出来ない。

JDBCでreturningを使う例


バインド変数はPL/SQLで使う他に、SQL*Plusでも定義することが出来る。

SQL> var v1 number

SQL> insert into EMP (EMPNO) values(9999) returning EMPNO into :v1;
1行が作成されました。

SQL> print v1
        V1
----------
      9999
SQL> var v1 number
SQL> var v2 varchar2(10)

SQL> insert into EMP (EMPNO,ENAME,JOB) values(9874,'zzz','job') returning EMPNO,ENAME into :v1,:v2 ;
1行が作成されました。

SQL> print
        V1
----------
      9874

V2
--------------------------------
zzz

シーケンスを使って値を採番した時に、その値を取得することが出来て便利。

SQL> insert into EMP (EMPNO,ENAME) values(test_seq.nextval,'zzz') returning EMPNO into :v1;
1行が作成されました。

SQL> print v1
        V1
----------
         1

インデックス・制約の無効化

大量にインサートする場合、インサート先のテーブルのインデックス制約を無効 にし、インサートし終わった後で有効化すると効率が良いらしい。
(有効にした時点で、まとめてインデックスの再作成や制約のチェックが行われる)

ただし、INSERT〜SELECTのWHERE条件でそのインデックスを使用できる場合は、インデックスを無効にすると逆に効率が悪くなる可能性がある。


SQLメモへ戻る / Oracle目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま