在 Oracle 11gR2 中使用条件进行多次更新

Posted

技术标签:

【中文标题】在 Oracle 11gR2 中使用条件进行多次更新【英文标题】:Multiple update using a condition in Oracle 11gR2 【发布时间】:2015-12-02 06:06:27 【问题描述】:

我一直在尝试在 Oracle 11gR2 中创建过程,所做的是根据输入动态执行对特定表的更新。用户可以更新表格的四个属性中的任何一个或全部。以下代码成功实现了需求。

SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE eis_mod_user_emp_dets_proc
(p_pres_add         eis_employees_tb.emp_present_add%TYPE     DEFAULT NULL
,p_marital_stat     eis_employees_tb.emp_marital_status%TYPE  DEFAULT NULL
,p_cont_ll          eis_employees_tb.emp_contact_ll%TYPE      DEFAULT NULL
,p_cont_mob         eis_employees_tb.emp_contact_mob%TYPE     DEFAULT NULL)
IS
BEGIN
IF  p_pres_add IS NOT NULL THEN
    UPDATE      eis_employees_tb
    SET         emp_present_add=p_pres_add
    WHERE       emp_id = sess.g_var_uid;
    dbms_output.put_line('Present Address updated Successfully');
END IF;

IF  p_marital_stat IS NOT NULL THEN
    UPDATE      eis_employees_tb
    SET         emp_marital_status=p_marital_stat
    WHERE       emp_id = sess.g_var_uid;
    dbms_output.put_line('Present Marital Status updated Successfully');
END IF;

IF  p_cont_ll IS NOT NULL THEN
    UPDATE      eis_employees_tb
    SET         emp_contact_ll=p_cont_ll
    WHERE       emp_id = sess.g_var_uid;
    dbms_output.put_line('Present Landline Number updated Successfully');
END IF;

IF  p_cont_mob IS NOT NULL THEN
    UPDATE      eis_employees_tb
    SET         emp_contact_mob=p_cont_mob 
    WHERE       emp_id = sess.g_var_uid;
    dbms_output.put_line('Present Mobile Number updated Successfully');
END IF;

END eis_mod_user_emp_dets_proc;
/
SHOW ERROR;`

程序编译后的输出

PROCEDURE eis_mod_user_emp_dets_proc Compiled. No Errors.

该过程的示例执行是: EXEC global_procs_pkg.login_proc('bh104','bh104'); EXEC eis_mod_user_emp_dets_proc(p_pres_add=>'Bundelkhand');

样本输出:

anonymous block completed
Welcome to the system bh104

anonymous block completed
Present Address updated Successfully
Present Marital Status updated Successfully

有没有更好的方法来优化这个过程? 我想尽可能优化这个过程,尽可能减少比较次数,减少更新语句的数量,从而提高性能。所以我需要改进这段代码的建议。

【问题讨论】:

如果逻辑比示例复杂,也可以根据输入参数编写动态sql并在单个sql语句中执行。 【参考方案1】:

试试这个。您的方法效率不高,如果它们都不为空,那么您将触发 4 个更新语句。它还必须在 sql 引擎和 pl/sql 引擎之间执行 4 次上下文切换。您可以使用通用 dbms_output 语句来表示更新成功。但是将 dbms_output 作为包的一部分并不是一个好习惯。

IF  p_pres_add IS NOT NULL OR p_marital_stat IS NOT NULL OR p_cont_ll IS NOT NULL OR p_cont_mob IS NOT NULL
THEN 
  UPDATE      eis_employees_tb
    SET         emp_present_add=nvl(p_pres_add, emp_present_add),
                emp_marital_status=nvl(p_marital_stat, emp_marital_status),
                emp_contact_ll=nvl(p_cont_ll, emp_contact_ll),
                emp_contact_mob=nvl(p_cont_mob, emp_contact_mob)
    WHERE       emp_id = sess.g_var_uid;
END IF;

【讨论】:

我认为你不需要IF 构造,NVL 无论如何都会处理它。 如果所有值都为null,则不需要执行update语句。在大多数情况下它不是必需的,但在某些情况下它可以派上用场。 最好不要在声明本身中将默认设置为 NULL。【参考方案2】:

您的方法效率低下,因为您正在进行 4 次更新。

您可以使用 NVL 在单个 UPDATE 语句中执行此操作。

UPDATE eis_employees_tb
SET emp_present_add     = NVL(p_pres_add, emp_present_add),
    emp_marital_status  = NVL(p_marital_stat, emp_marital_status),
    emp_contact_ll      = NVL(p_cont_ll,emp_contact_ll),
    emp_contact_mob     = NVL(p_cont_mob , emp_contact_mob)
WHERE emp_id            = sess.g_var_uid;

附带说明,生产系统不使用 DBMS_OUTPUT。如果您确实需要将输出推送给调用者,也许您需要一个 OUT 参数

【讨论】:

我已经修改了我的代码以尝试实现动态 sql,您能否查看链接并告诉我这是否是更好的方法? pastebin.com/nSy53PW0 @RajorshiMukherjee 不,不,不。不要(ab)将 EXECUTE IMMEDIATE 用于此类琐碎的事情。您应该将 UPDATE 作为静态 sql,不需要动态 sql。它不仅会扼杀性能,而且很难维护。您为什么不尝试提供的答案,它更短且更有效。 我尝试使用您的代码,不用说它可以完美运行,但是,我想显示一条消息,即当没有要更新的数据时,需要通知用户。我如何实现这一目标?我应该使用 AND 将其塞入一个 IF 条件,然后执行其余语句吗?比如pastebin.com/gHextjW8。在这里,我添加了另一个过程的代码,并正在检查是否缺少任何数据。我应该使用带有 AND 的 IF 来检查数据的有效性吗? @RajorshiMukherjee 您希望它们都不能为 NULL 并且所有四个属性都必须始终具有值吗?因为,即使其中一个为空,OR 条件也会得到满足。如果您的要求是所有字段都必须有一个值,那么您的方法很好。 为什么不删除默认的 NULL 并将它们设置为 NOT NULL 呢?

以上是关于在 Oracle 11gR2 中使用条件进行多次更新的主要内容,如果未能解决你的问题,请参考以下文章

100天精通Oracle-实战系列(第2天)史上最详细 Linux 6 安装单机 Oracle 11GR2 数据库

单机:Oracle 11GR2 数据库一键安装

单机:Oracle 11GR2 数据库一键安装

单机:Oracle 11GR2 数据库一键安装

RAC:Oracle 11GR2 数据库一键安装

RAC:Oracle 11GR2 数据库一键安装