插入查询

时间:2016-04-28 06:48:37

标签: sql oracle insert

当查看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');

再次引导相同的执行计划。因此,只要我们只选择一个表中的列,我们就可以假设子查询的内容并不重要。但不是。这样:

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

导致" ORA-01779:无法修改映射到非密钥保留表的列"或" ORA-01732:数据操作操作在此视图上不合法"。

我的印象是Oracle决定允许插入查询,因为它们允许插入视图,还有什么是子查询,然后是临时视图?因此,当您可以插入到视图中时,它们肯定会让您插入到即席视图中,但是正确思想中的任何人都不会使用此语法,当然: - )

但也许我错了?也许这种语法确实提供了一些我还没有意识到的东西?如果是这样,请告诉我: - )

3 个答案:

答案 0 :(得分:5)

插入子查询允许使用WITH CHECK OPTION限制结果。

例如,假设您要为“新部门”允许除之外的任何部门名称​​。使用不同值的此示例可以正常工作:

R.utils::gunzip

但如果插入了这个错误值,则会抛出错误:

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

1 row created.

我从来没有见过野外使用的这个功能。视图具有此选项,因此您应该能够使用子查询执行相同的操作。我不确定为什么有人会想要这样做,将限制放在提供INSERT的SELECT语句上同样容易。如果INSERT使用VALUES,将它转换为SELECT语句是很简单的。

您必须深入了解语法图才能看到此功能:insert - &gt; single_table_insert - &gt;子查询 - &gt; query_block - &gt; table_reference - &gt; query_table_expression - &gt; subquery_restriction_clause。

答案 1 :(得分:0)

子查询定义要插入行的表的列。正如oracle's doc (12c)所说:

  

指定a返回的一列或多列的名称   子查询,要插入哪些行。如果指定视图或对象   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;

答案 2 :(得分:-1)

那是因为 INSERT into SELECT语句从一个表中选择数据并将其插入现有表中。 目标表中的任何现有行都不受影响。