2016-04-28 17 views
7

OracleのINSERT構文を調べるだけで、クエリに挿入することができます。クエリに挿入

insert into (select * from dept) (deptno, dname) values (99, 'new department'); 

これは何を意味するのですか?私はテーブルに直接挿入することができないクエリに挿入することで何を達成できますか?

UPDATE:はこれまでのところ、単なる代替構文であると思われるので、私は

insert into (select deptno, dname from dept) values (99, 'new department'); 

代わりの

insert into dept (deptno, dname) values (99, 'new department'); 

同じこと、同じ実行計画を作成することができます。クエリがレコードを返すかどうかは関係ありません。これは:

insert into (select deptno, dname from dept where 1 = 0) values (99, 'new department'); 

が同じ実行計画に再びつながります。したがって、1つのテーブルから列を選択するだけでは、サブクエリがどのように見えるかは実際には関係ありません。しかし、いいえ。この:か:「非キー保存表にマップする列変更することはできませんORA-01779」、「ORA-01732を:このビューのデータ操作操作は有効ではありません」

insert into (select deptno, dname from dept cross join some_table) 
values (99, 'new department'); 

がにつながります。

Oracleは、ビューに挿入できるようにするために、問合せに挿入することを決定したという印象を持っています。それ以外のサブクエリは、次にアドホック・ビューですか?だから、あなたがビューに挿入することができれば、確かにあなたはアドホックなビューにも挿入できるようになりますが、正しい考え方の誰もこの構文を使用することはありません:-)

多分私は間違っていますか?たぶん、この構文は私がまだ認識していない何かを提供しているのでしょうか?その場合は:-)

答えて

0

サブクエリは、行が挿入されるテーブルの列を定義します。 oracle's doc (12c)が言うように:

Specify the name of the [...] column or columns returned by a subquery, into which rows are to be inserted. If you specify a view or object view, then the database inserts rows into the base table of the view.

create table test_isq (
    pk integer not null primary key, data_1 varchar2(40), data_2 varchar2(40), data_3 varchar2(40) 
); 

-- ok 
insert into (select pk, data_2, data_3 from test_isq) (pk, data_2) values (1, 'Test'); 
insert into (select pk, data_2, data_3 from test_isq) values (2, 'Another', 'Test'); 

-- fail 
insert into (select data_1 from test_isq) values ('This', 'one', 'fails'); 
insert into (select data_1 from test_isq) (pk, data_1) values (42, 'Nope'); 

drop table test_isq; 
+0

ああ、これは単なる代替構文だと言っていますか?私は 'dept(deptno、dname)の値(...)'または '(deptno、deptからの名前の選択)値(...)'に挿入することができます。それは同じことを書いているもう一つの方法であり、他のものよりも利点がありません。 –

+0

基本的にはい - 私は可能性のある分派を研究していませんが。ドキュメントに基づいて私はそれらを期待していなかったでしょう、あなたが 'insert'特権を持ち、それぞれのテーブルで' select'を持っていない限り。 – collapsar

-1

SELECTステートメントへのINSERTは、1つのテーブルからデータを選択し、それを既存のテーブルに挿入するためです。 ターゲット表の既存の行は影響を受けません。

+1

これを挿入と混同していると思います。 'insert into dept(deptno、dname)select deptnumber、deptname from new_departments'です。 –

+0

ありあり... (select *)へのInsertのような副問合せを使用する理由は、oracleであるため、副問合せに含まれていない行が生成されるような変更は許可されません。 –

+0

私は既にそこにあるものだけを挿入することができましたか?それは意味をなさない。とにかく、私はサブクエリで 'where 1 = 0'を試しましたが、挿入には何の影響もありません。サブクエリが行を返すかどうかはまったく問題ではないようです。 –

-1

基本的にはselect * from deptクエリは、テーブルの列名ではない戻り値です。また、列名を指定するためにを挿入してください。

dept(deptno、dname)に挿入するdeptnumber、deptnameをnew_departmentsから選択するその時刻を選択するクエリはデータを返すため、値が挿入されます。

+0

申し訳ありませんが、私はこの答えを理解していません。私は 'dept(...)values(...)'に挿入することができ、 '(select * from dept)(...)values(...)'を挿入することができます。 2番目のステートメントのようにクエリを使用すると、最初のクエリのようにテーブルの名前を直接指定することよりも利点があります。 –

5

サブクエリに挿入するWITH CHECK OPTIONを使用して結果を制限することができます。

たとえば、「新しい部門」の以外の部門名を許可したいとします。

SQL> insert into 
    2 (select deptno, dname from dept where dname <> 'new department' WITH CHECK OPTION) 
    3 values (98, 'old department'); 

1 row created. 

をしかし、その不正な値が挿入されている場合は、エラーがスローされます:別の値を使用して、この例では、正常に動作します

SQL> insert into 
    2 (select deptno, dname from dept where dname <> 'new department' WITH CHECK OPTION) 
    3 values (99, 'new department'); 
(select deptno, dname from dept where dname <> 'new department' WITH CHECK OPTION) 
          * 
ERROR at line 2: 
ORA-01402: view WITH CHECK OPTION where-clause violation 

私は野生で使用されるこの機能を見たことがありません。ビューにはこのオプションがありますので、サブクエリで同じことを実行できるはずです。なぜ誰かがこれをやりたがっているのか分かりません。INSERTにフィードするSELECT文に制限を入れるのと同じくらい簡単です。また、INSERTがVALUESを使用する場合は、SELECT文に変換するのは簡単です。

​​- > single_table_insert - > subquery - > query_block - > table_reference - > query_table_expression - > subquery_restriction_clauseを参照するには、構文図を実際に調べる必要があります。