插入查询

Tho*_*ner 7 sql oracle insert

在查看Oracle的INSERT语法时,我注意到您可以插入查询,例如

insert into (select * from dept) (deptno, dname) values (99, 'new department');
Run Code Online (Sandbox Code Playgroud)

任何人都可以了解这是什么意思吗?插入到我不能直接插入表中的查询中可以实现什么?

更新:到目前为止,这似乎只是一种替代语法,所以我可以写

insert into (select deptno, dname from dept) values (99, 'new department');
Run Code Online (Sandbox Code Playgroud)

代替

insert into dept (deptno, dname) values (99, 'new department');
Run Code Online (Sandbox Code Playgroud)

同样的事情,相同的执行计划.查询是否返回记录无关紧要.这个:

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

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

insert into (select deptno, dname from dept cross join some_table)
values (99, 'new department');
Run Code Online (Sandbox Code Playgroud)

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

我的印象是Oracle决定允许插入查询,因为它们允许插入视图,还有什么是子查询,然后是临时视图?因此,当你可以插入到一个视图中时,他们肯定会让你插入到一个特殊的视图中,但是正确的心灵中的任何人都不会使用这种语法,当然:-)

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

Jon*_*ler 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.
Run Code Online (Sandbox Code Playgroud)

但如果插入该错误值,则会抛出错误:

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
Run Code Online (Sandbox Code Playgroud)

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

您必须深入了解语法图以查看此功能:insert - > single_table_insert - > subquery - > query_block - > table_reference - > query_table_expression - > subquery_restriction_clause.


col*_*sar 0

子查询定义要插入行的表的列。正如Oracle 的文档 (12c)所说:

指定子查询返回的 [...] 列的名称,行将插入其中。如果指定视图或对象视图,则数据库会将行插入到视图的基表中。

例子

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;
Run Code Online (Sandbox Code Playgroud)