Oracle数据库考试题(一)update更改多行计算
原创前言:
在采访中,我遇到了这样一个问题:目前有两种形式。A表和B表,A表有字段ID,NAME,B该表也包含字段ID,NAME()字段ID和A表的ID一样的,但田野NAME和A表中的NAME不完全相同),使用B表中的NAME更新A表的NAME。
我立刻想到就这么简单,update阿。但再想一想是不可能的。下面将详细描述更改多行数据的四种方法。
1.传统方法--update:(可能是最慢的方法)
--在SQL Server(这是我的回答,面试官很困惑。长期使用SQL server):
update a set a.NAME=b.NAME from A a,B b where a.ID=b.ID --这种效率将会非常快。
在Oracle它只能写成这样:
update A a set a.NAME=(select b.NAME from B b where a.ID=b.ID)
----或者:使用exists限制它。
update A a set a.NAME=(select b.NAME from B b where a.ID=b.ID)
where exists(select 1 from B b where a.ID=b.ID)
使用Oracle中员工表emp做例子:
可以直接在Oracle在数据库中执行,test_emp是emp相同的表结构,复制。
update TEST_EMP a
set a.sal =
(select b.sal from emp b where a.empno = b.empno)
where exists (select 1 from emp b where a.empno = b.empno);
在这种情况下,如果A,B两者各有各的特点10000数据,那么它必须扫描整个表。10000*10000时不我待,就会出现性能问题。所以在oracle有没有其他方法可以改善它?
二、inline view嵌入视图:(关联主键字段,速度更快)
方案:
更新临时创建的视图。要求B表的主键字段必须在where条件,并且是=要关联更新表的编号,否则可能会报告错误:ORA-01779:非键值保存表对应的列不能修改。什么时候B当表主键字段与多个列组合时也可能发生此错误。
update
(
select a.sal as asal, b.sal as bsal
from emp a, test_emp b
where a.empno = b.empno
)
set asal = bsal;
嵌入式视图和子查询之间的区别:(我一直认为它是相同的,但它似乎仍然是不同的。)
子查询是一个完整的查询语句。子查询首先生成结果集并将结果集应用于条件语句。子查询不同于嵌入式视图。嵌入的视图也可以被视为临时查询结果,但嵌入的视图显示在中。from子句,并与其他数据源(数据表、视图等)形成笛卡尔乘积运算。另一方面,子查询单独操作,不对其他数据源执行笛卡尔乘积操作。
三、merge into更新方法:(当关联的字段不是主键时速度更快)
方案:
在alias2中select在数据中,每个都是。alias1进行ON (join condition)比较、如果匹配、更新操作、不匹配、插入操作。
merge不会返回受影响的行数,最多只能关联两个表,适用于连接条件不是主键的字段。
语法:(详细)merge into我又写了一篇文章来解释:先留空)
merge into table_name alias1 --须操作的桌子 可以使用别名
using (table|view|sub_query) alias2 --数据来源 可以是表、视图或子查询。
on (join condition) --关联条件
when matched then --当关联条件成立时 更新、删除、插入where部分可选
--更新
update table_name set col1=colvalue where……
--删除
delete from table_name where col2=colvalue where……
--只能更新,不能删除 您也可以只删除而不更新。
--如果更新和删除同时存在,则删除条件必须在更新条件内,否则不能删除数据。
when not matched then --当关联条件不成立时 插入
insert (col3) values (col3values) where……;
--例如:
merge into test_emp a --须操作的桌子 可以使用别名
using emp b --源表
on (a.EMPNO = b.EMPNO) --目标表和源表之间的相关性。
when matched then --当关联条件成立时 更新、删除、插入where部分可选
update set a.sal= b.sal where a.empno = 7566
when not matched then
insert (a.empno, a.ename, a.job, a.mgr, a.hiredate, a.sal, a.comm, a.deptno)
values (b.empno, b.ename, b.job, b.mgr, b.hiredate, b.sal, b.comm, b.deptno);
4.快速游标更新方法:(逻辑复杂时高效)
方案:
配合oracle独一无二的内置ROWID物理字段,使用快速游标,不需要定义,直接编写游标for循环,快速定位并执行更新。它可以支持复杂的逻辑查询语句,更新准确,无论多少数据,更新效率仍然很高。但是,在执行后不返回受影响的行数。
语法:
begin
for cr in (查询语句) loop --循环
update table_name set ... --UPDATE语句(基于查询的结果集)
end loop; --结束循环
end;
例如:
begin
for emp_cursor in (select a.rowid, b.sal sal from test_emp a, emp b where a.empno = b.empno)
loop
update test_emp set sal = emp_cursor.sal
where rowid = emp_cursor.rowid;
end loop;
end;
5.四种方法的比较:
方法描述
适用范围
运行效率
传统方案
一般情况也适用。
单表更新高效稳定,多表更新速度较慢。
inline view更新法
关联的字段是主键。
速度较快
merge更新法
关联字段不是主键,适用于两个表的关联。
非主键关联表更新,速度更快
一种快速更新光标的方法
逻辑上复杂的情况
复杂的逻辑是非常有效的。
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除