在查看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决定允许插入查询,因为它们允许插入视图,还有什么是子查询,然后是临时视图?因此,当你可以插入到一个视图中时,他们肯定会让你插入到一个特殊的视图中,但是正确的心灵中的任何人都不会使用这种语法,当然:-)
但也许我错了?也许这种语法确实提供了一些我还没有意识到的东西?如果是这样告诉我:-)
插入子查询允许使用限制结果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.
子查询定义要插入行的表的列。正如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)
| 归档时间: |
|
| 查看次数: |
692 次 |
| 最近记录: |