繁体   English   中英

PL/SQL 存储过程用于更新由参数指定的列的值

[英]PL/SQL stored procedure to update values of a column that is specified by the parameter

我正在尝试在 PL/SQL 中创建一个存储过程,它可以通过采用 3 个参数来更新值

  1. 旧值
  2. 新值
  3. 列名

如何在不重复重写 set/update 语句的情况下实现这一点?

此代码不起作用:

CREATE OR REPLACE PROCEDURE dp_replace_values (
    old_value varchar2, new_value varchar2, column_name varchar2
) IS
    
BEGIN
    UPDATE dp_mock_data
    SET
        first_name = case when column_name = 'first_name' then old_value end,
        last_name = case when column_name = 'last_name' then new_value end
    WHERE
        last_name = old_value;

END dp_replace_values;

下面的代码确实有效,但它不断重复更新和设置语句。

CREATE OR REPLACE PROCEDURE dp_replace_values (
    old_value varchar2, new_value varchar2, column_name varchar2
) IS
    
BEGIN
    
    IF column_name = 'first_name' then

    UPDATE dp_mock_data
    SET
        first_name = new_value
    WHERE
        first_name = old_value;

    ELSIF column_name = 'last_name' then
    
     UPDATE dp_mock_data
    SET
        last_name = new_value
    WHERE
        last_name = old_value;
    end if;

END dp_replace_values;

您必须使用动态 SQL。

CREATE OR REPLACE PROCEDURE dp_replace_values (
    old_value varchar2, 
    new_value varchar2, 
    column_name varchar2
) 
IS
BEGIN
  EXECUTE IMMEDIATE 'UPDATE dp_mock_data ' ||
                    '   SET ' || column_name || ' = :1 '
                    ' WHERE ' || column_name || ' = :2 '
    USING new_value, old_value;
END;

实际上,您需要添加逻辑来防止 SQL 注入。 至少,使用dbms_assert来验证column_name是 SQL 标识符。 但可能更多——我想查询all_tab_columns以确认column_name实际上是dp_mock_data表中列的名称。 如果您的系统碰巧使用任何区分大小写的列名,则需要添加代码。 您需要添加代码来记录在执行之前生成的语句,以便进行调试。

如果你走动态 SQL 路线,你会更难维护代码。 你把很多编译错误变成了运行时错误。 你使调试变得更加困难。 您消除了使用数据库的数据字典查找对象之间依赖关系的能力。 而且收益往往不是特别大。 通常很容易为每一列创建一个update过程,或者创建一个允许您更新一个或多个列并保持其他列不变的过程。 而且您通常希望在进行更新时指定一个键,而不是使用相同的old_value更新每一行(如果可能是多行,我怀疑您想要规范化您的数据模型并只更新查找表)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM