首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有关联查询的oracle更新

具有关联查询的oracle更新
EN

Stack Overflow用户
提问于 2020-02-16 20:09:27
回答 2查看 1.1K关注 0票数 3

正确的答案是什么?选两个。

检查此SQL语句:

代码语言:javascript
复制
UPDATE orders o
SET customer_name = (
    SELECT cust_last_name FROM customers  WHERE customer_id=o.customer_id
);

哪两个是真的?

  • 子查询在UPDATE语句执行之前执行。
  • B.对ORDERS表中的所有现有行进行更新。
  • 子查询对ORDERS表中的每个更新行执行。
  • D.即使子查询选择多行,UPDATE语句也会成功执行。
  • 子查询不是关联子查询。

我知道B是对的,但我认为其他的选择都是错误的。

  • 子查询对外部查询返回的每一行执行,因此它应该在外部查询之后执行。
  • 外部查询返回的不是每个更新的行,而是每一行。
  • 我试过了。它会导致错误ORA-01427:单行子查询返回多行。
  • 它是一个相关的子查询。
EN

回答 2

Stack Overflow用户

发布于 2020-02-16 20:17:14

考虑备选案文C:

子查询对ORDERS表中的每个更新行执行。

你说过:

外部查询返回的不是每一行更新的行,而是每一行。

是。子查询确实是针对外部查询中的每一行执行的(将数据库应用的可能优化分开)。外部查询中的每一行都会被更新--正如您所发现的那样,因为您已经正确地选择了选项B: ORDERS表中的所有现有行都将被更新。

注:您反对选项A、D和3的论点是有效的。

票数 1
EN

Stack Overflow用户

发布于 2020-02-16 20:23:30

第二个正确答案是

这是一种错误的设计,在CUSTOMER_NAME表中对orders进行反错,并与正常形式相冲突。

在甲骨文8时代(即20年前),的答案C可能是对的,但现在绝对错了!

Oracle引入标量子查询缓存事件是为了限制子查询的执行次数。

这里是一个简单的演示

此设置在Oracle 19.2中有10K订单和1K客户。

代码语言:javascript
复制
create table customers as
select rownum customer_id, 'cust_'||rownum customer_name from dual connect by level <= 1000;

create index customers_idx1 on customers (customer_id);

create table orders as
select rownum order_id, trunc(rownum/10)+1 customer_id, cast (null as varchar2(100)) customer_name
from dual connect by level <= 10000;

更新将按预期对100 K行执行。

代码语言:javascript
复制
UPDATE /*+ gather_plan_statistics */ orders o
SET customer_name = (
    SELECT customer_name FROM customers  WHERE customer_id=o.customer_id
);

提示gather_plan_statistics收集执行统计信息,我们将检查这些统计信息。

代码语言:javascript
复制
SQL_ID  8r610vz9fknr6, child number 0
-------------------------------------
UPDATE /*+ gather_plan_statistics */ orders o SET customer_name = (     
SELECT customer_name FROM customers  WHERE customer_id=o.customer_id )

Plan hash value: 3416863305

--------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
--------------------------------------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT                     |                |      1 |        |      0 |00:00:00.18 |   60863 |     21 |
|   1 |  UPDATE                              | ORDERS         |      1 |        |      0 |00:00:00.18 |   60863 |     21 |
|   2 |   TABLE ACCESS FULL                  | ORDERS         |      1 |  10000 |  10000 |00:00:00.01 |      21 |     18 |
|   3 |   TABLE ACCESS BY INDEX ROWID BATCHED| CUSTOMERS      |   1001 |      1 |   1000 |00:00:00.01 |    2020 |      3 |
|*  4 |    INDEX RANGE SCAN                  | CUSTOMERS_IDX1 |   1001 |      1 |   1000 |00:00:00.01 |    1020 |      3 |
--------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("CUSTOMER_ID"=:B1)

重要信息在列Start中,我们看到表customers仅被访问了1001次,即几乎每个客户只访问一次,而不是每个订单访问一次。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60252753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档