在 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 中使用条件进行多次更新的主要内容,如果未能解决你的问题,请参考以下文章