关于程序,哪两项陈述是正确的?

Posted

技术标签:

【中文标题】关于程序,哪两项陈述是正确的?【英文标题】:Which two statements are true regarding procedures? 【发布时间】:2013-03-31 07:44:17 【问题描述】:

过程 PROCESS_EMP 引用表 EMP。过程 UPDATE_EMP 通过过程 PROCESS_EMP 更新表 EMP 的行。有一个远程过程 QUERY_EMP 通过本地过程 PROCESS_EMP 查询 EMP 表。在此会话中,依赖模式设置为 TIMESTAMP。哪两种说法是正确的?

1) 如果PROCESS_EMP过程的签名被修改并成功重新编译,则EMP表无效。

2) 如果PROCESS_EMP过程的内部逻辑被修改并成功重新编译,则UPDATE_EMP失效并在第一次调用时重新编译。

3) 如果PROCESS_EMP过程的签名被修改并成功重新编译,则UPDATE_EMP失效并在第一次调用时重新编译。

4) 如果PROCESS_EMP过程的内部逻辑被修改并成功重新编译,QUERY_EMP将失效,并在第一次调用时重新编译。

5) 如果PROCESS_EMP过程的内部逻辑被修改并成功重新编译,则QUERY_EMP失效,并在第二次调用时重新编译。

据我所知,签名是返回类型和参数列表的组合。

1) 如果 PROCESS_EMP 的签名发生变化,则与 EMP 表无关,因为它本身正在引用 EMP。

2) 这是正确的选项。 UPDATE_EMP 使用 PROCESS_EMP 更新 EMP 表。如果 PROCESS_EMP 的内部逻辑发生变化,那么它如何影响 UPDATE_EMP ?如果 UPDATE_EMP 正在使用 PROCESS_EMP,那么它应该调用它。内部逻辑的变化包含在 PROCESS_EMP 中的 body 中,而不是 UPDATE_EMP 中。

3) 我认为这一定是正确的。但这是错误的。如果在 PROCESS_EMP 中更改了签名。就像如果返回类型或参数数量或两者都被修改,那么调用方式会受到影响。因此,UPDATE_EMP 应该受到影响。为什么是假的?

4) 和 5) 4 点不正确。我没有得到这个“第一次”和“第二次”。为什么是第二次?为什么不是第一次? 5分是正确的。*

【问题讨论】:

根据我对 Oracle 重新编译逻辑的最少了解,我对上述问题的回答是 1) 错误,2) 取决于如何调用 UPDATE_EMP,3) 与 (2) 相同,4) 错误, 5) 错误。有没有哪位 DBA 对这个有更好的了解? 【参考方案1】:

3 和 5。

但不要相信我的话,让我们测试一下。

创建测试对象

--Remote dependency mode
alter session set remote_dependencies_mode = timestamp;

--Table
drop table emp purge;
create table emp(id number, name varchar2(100));
insert into emp values(1, 'asdf');
commit;

--Database link - you don't need two databases, you can link to yourself
drop database link myself;
create database link myself connect to <user> identified by <password> using '<database>';
select * from dual@myself;

--Procedures
create or replace procedure process_emp(action_type in varchar2) is
    v_count number;
begin
    if action_type = 'U' then
        update emp set name = upper(name);
    elsif action_type = 'Q' then
        select count(*) into v_count from emp;
    end if;
end;
/

create or replace procedure update_emp is
begin
    process_emp('U');
end;
/

create or replace procedure query_emp is
begin
    process_emp@myself('Q');
end;
/

--Initial object times
select object_name, last_ddl_time, status
from user_objects
where object_name in ('PROCESS_EMP', 'UPDATE_EMP', 'QUERY_EMP')
order by last_ddl_time;

PROCESS_EMP 2013-04-02 00:25:47 VALID
UPDATE_EMP  2013-04-02 00:25:48 VALID
QUERY_EMP   2013-04-02 00:25:49 VALID

测试

1) 如果PROCESS_EMP过程的签名被修改并成功重新编译,则EMP表无效。

False - 没有什么可以测试的。没有无效表之类的东西。 (可能对象关系表除外,但我认为这不适用于这里。)

2) 如果PROCESS_EMP过程的内部逻辑被修改并成功重新编译,则UPDATE_EMP失效并在第一次调用时重新编译。

False - UPDATE_EMP 仍然有效,并且不会重新编译。 LAST_DDL_TIME 不会改变。通常,一个过程仅通过它的签名知道——如果它没有改变,那么就没有必要改变其他任何东西。

create or replace procedure process_emp(action_type in varchar2) is
    v_count number;
begin
    if action_type = 'U' then
        update emp set name = upper(name);
    elsif action_type = 'Q' then
        select count(*)+1 into v_count from emp;
    end if;
end;
/

select object_name, last_ddl_time, status
from user_objects
where object_name in ('PROCESS_EMP', 'UPDATE_EMP', 'QUERY_EMP')
order by last_ddl_time;

UPDATE_EMP  2013-04-02 00:25:48 VALID
QUERY_EMP   2013-04-02 00:25:49 VALID
PROCESS_EMP 2013-04-02 00:29:20 VALID

3) 如果PROCESS_EMP过程的签名被修改并成功重新编译,则UPDATE_EMP失效并在第一次调用时重新编译。

True - 更改参数可能会改变调用过程的方式。大多数更改都会导致失败,但在很多情况下 依赖程序将重新编译,一切都会好起来的。例如,如果您添加一个默认参数:

create or replace procedure process_emp(action_type in varchar2, new_param in varchar2 default null) is
    v_count number;
begin
    if action_type = 'U' then
        update emp set name = upper(name);
    elsif action_type = 'Q' then
        select count(*)+1 into v_count from emp;
    end if;
end;
/

--Now the object is invalid:
select status from user_objects where object_name in ('UPDATE_EMP');
INVALID

--But no need to worry, just run it and it will automatically recompile and work correctly:
begin
    update_emp;
end;
/

select status from user_objects where object_name in ('UPDATE_EMP');
VALID

4) 如果PROCESS_EMP过程的内部逻辑被修改并成功重新编译,QUERY_EMP将失效,并在第一次调用时重新编译。

False - QUERY_EMP 仍然有效,但在第一次调用时会失败,并且不会重新编译。事实上,即使像我们上面所做的那样更改参数也不会使这一点失效。

select object_name, last_ddl_time, status
from user_objects
where object_name in ('QUERY_EMP')
order by last_ddl_time;

QUERY_EMP   2013-04-02 00:25:49 VALID

begin
    query_emp@myself;
end;
/

ORA-04062: timestamp of procedure "JHELLER.PROCESS_EMP" has been changed
ORA-06512: at "JHELLER.QUERY_EMP", line 3
ORA-06512: at line 2

View program sources of error stack?

5) 如果PROCESS_EMP过程的内部逻辑被修改并成功重新编译,则QUERY_EMP失效,并在第二次调用时重新编译。

True - QUERY_EMP 将失效(尽管直到第一次之后),然后第二次正确重新编译。查询运行,LAST_DDL_TIME 现已更新。

begin
    query_emp@myself;
end;
/

select object_name, last_ddl_time, status
from user_objects
where object_name in ('QUERY_EMP')
order by last_ddl_time;

QUERY_EMP   2013-04-02 00:37:01 VALID

【讨论】:

【参考方案2】:

第 3 点和第 5 点是对的。

你有第三点的理由。

第 5 点成立的原因:

依赖模式设置为TIMESTAMP

当过程PROCESS_EMP的内部逻辑被修改并成功重新编译时,其TIMESTAMP发生变化。您可以通过查询USER_OBJECTS 视图来检查。

所有依赖于PROCESS_EMP 的过程都会立即失效。您也可以通过查询USER_OBJECTS 视图来检查这一点。因此,当这些过程(如UPDATE_EMP)在第一次调用时被重新编译。

但是任何依赖于PROCESS_EMP 的远程过程,例如QUERY_EMP,都不会立即失效。在重新编译依赖过程后第一次调用它们后,它们将失效。因此QUERY_EMP 在第一次调用时不会重新编译。您可以通过在调用QUERY_EMP 之前和之后查询远程数据库上的USER_OBJECTS 视图来检查这一点。

第二次调用QUERY_EMP时,由于状态无效,需要重新编译,PROCESS_EMP的签名没有变化,重新编译成功并执行。

有关更多信息,请阅读 Oracle 文档 here 和 here。

【讨论】:

我们不同意#3,但这可能只是因为版本不同。我的例子是 11g,它使用fine-grained invalidation。 好的...我看到标签是oracle10g,这就是原因。 @jonearles:在#3 中,“所有程序”是指同一数据库中的所有程序。据我所知,远程数据库中的过程不会立即失效。 :) 糟糕,我错过了 10g 标签!谷歌搜索这个问题后,我看到它是为 10g 创建的。不过,我相信现在相关的考试只针对11g。 OCP,即 1z0-146 适用于 11g。如果提问者尝试 OCA,则有两个 11g 的 1z0-144 和 10g 的 1z0-147。视情况而定。

以上是关于关于程序,哪两项陈述是正确的?的主要内容,如果未能解决你的问题,请参考以下文章

oracle数据库开哪两项服务就可以了?

关于Java中异常的叙述正确的是:( ) A.异常是程序编写过程中代码的语法错误

OCP 071中文考试题库(cuug整理)第45题

多态分为哪两中

关于 ALSA 驱动程序:如何正确处理音频设备

关于C# MVC 试图加载格式不正确的程序 的问题。