【问题标题】:DB Procedure to Dynamically update DB columns动态更新数据库列的数据库过程
【发布时间】:2019-06-22 09:38:40
【问题描述】:

要求仅在 db 列中更新从前端编辑的那些列。 我使用的逻辑是将 2 个数组从 java 代码发送到 DB procedire。

第一个数组是:Column_array,其中包含必须更新的列名。

&

第二个数组:value_array 包含对应于 column_array 的列的值。

来自 JAVA:

Array value_array = ((OracleConnection) dbConnection).createOracleArray("STRING_ARRAY",
                valueList.toArray());

        Array param_array = ((OracleConnection) dbConnection).createOracleArray("STRING_ARRAY",
                            paramList.toArray());

 stmt = dbConnection.prepareCall(SqlConstants.UPDATE_SUBSCRIBER_CONFIG_IN_BOLTES);//
            stmt.setLong(1, 3628);
            stmt.setLong(2, 3629);
            stmt.setLong(3, 3632);
            stmt.setArray(4, param_array);
            stmt.setArray(5, value_array);
            int count = stmt.executeUpdate();

现在在数据库端:

我怎样才能遍历这个列表来更新并在 SET 子句中设置它???

 PROCEDURE update_subscriber_config (
    p_app_id        VARCHAR2,
    p_service_id     VARCHAR2,
    p_pubsub_id       VARCHAR2,
    column_list     string_array,
    value_list      string_array
)
    AS
BEGIN

FOR a IN 1..column_list.count LOOP
        update  bolt_oracle_pubsub_config set 
            column_list(a)=value_list(a),
             ...how to do iteration here???

      where  APP_ID = p_app_id AND SERVICE_ID =  p_service_id AND PUBSUB_ID = p_pubsub_id;
       END LOOP;

END update_subscriber_config;

请帮忙。

【问题讨论】:

  • 为什么不创建一个动态 SQL 语句字符串,只更新列表中传入的列?
  • 同意。在您的代码中动态创建一条 UPDATE 语句。
  • 在更新SQL中,更新有值的列,其他为空或NULL。为什么要使用两个数组来检查哪些列被更新了?
  • 我们必须使用数据库程序。我怎样才能实现它,你能帮我写sql吗?
  • @NehaGoswami 我已经添加了一个答案,老实说,我认为避免使用具有列名的数组并避免使用动态 SQL,原因很简单,您可以使用一个简单的更新语句。

标签: sql oracle stored-procedures plsql dynamic-sql


【解决方案1】:

您必须使用动态 SQL 来组装定制的更新语句。它看起来像这样:

PROCEDURE update_subscriber_config (
    p_app_id        VARCHAR2,
    p_service_id     VARCHAR2,
    p_pubsub_id       VARCHAR2,
    column_list     string_array,
    value_list      string_array
)
AS
   stmt varchar2(32767);
BEGIN

    stmt := 'update  bolt_oracle_pubsub_config set ';

    FOR a IN 1..column_list.count LOOP
        if a != 1 then
           stmt := stmt ||', ';
        end if;
        stmt := stmt || column_list(a) ||'=''' ||value_list(a)||'''';
       END LOOP;

       stmt := stmt ||
             ' where  APP_ID = :p1 AND SERVICE_ID = :p2 AND PUBSUB_ID = :p3';
      execute immediate stmt using p_app_id , p_service_id , p_pubsub_id;
END update_subscriber_config;

这是一个非常粗略的实现,因为它假设所有传递的列都可以被视为字符串。如果您的表格有数字或日期列,您应该考虑处理数据转换,因为这可能会成为一个问题。

动态 SQL 很难,因为它将编译错误转化为运行时错误。在您的情况下,您有一段代码可能会在您每次调用它时执行不同的更新语句。所以测试这个程序是一场噩梦。这意味着您严重依赖具有有效内容的前端传递数组。

【讨论】:

  • 太棒了!非常感谢。这段代码非常适合我!! :) 就我而言,我只会得到字符串。
【解决方案2】:

也许您可以尝试避免使用列数组之一,因为如果值为空,Oracle SQL 会容忍。

以下是伪代码。

PROCEDURE update_subscriber_config (p_app_id             VARCHAR2,
                                    p_service_id         VARCHAR2,
                                    p_pubsub_id          VARCHAR2,
                                    p_first_column       VARCHAR2,
                                    p_second_column      VARCHAR2,
                                    --column_list     string_array,
                                    i_array           IN my_array_type)
AS
BEGIN
   FORALL i IN 1 .. i_array.COUNT
      UPDATE bolt_oracle_pubsub_config
         SET your_first_column =
                TREAT (i_array (i) AS my_array_type).column_array_name,
             your_second_column =
                TREAT (i_array (i) AS my_array_type).second_column_array_name
       WHERE     APP_ID = p_app_id
             AND SERVICE_ID = p_service_id
             AND PUBSUB_ID = p_pubsub_id;

END update_subscriber_config;

如果更新 SQL 中声明的任何列为空,则执行更新后在表中为空或为空。话虽如此,请确保已填充所有 NOT NULL 或必填列。

由于容易出错,我估计要避免动态 SQL 更新。如果你在不使用动态 SQL 的情况下实现了结果,那么为什么要使用动态 SQL 更新麻烦。

【讨论】:

    【解决方案3】:

    我找到了比数组迭代更简单的解决方案。

    解决方法是使用 COALESCE 方法。

     PROCEDURE TEST (
          p_app_id       NUMBER,
        p_service_id   NUMBER,
        p_pubsub_id    NUMBER,
        p_pubsub_name       VARCHAR2,
        p_host              VARCHAR2,
        p_user_name           VARCHAR2,
        p_auth_key              VARCHAR2
    )
        AS
    BEGIN
    
         update bolt_elastic_pubsub_config set 
          PUBSUB_NAME = coalesce(p_pubsub_name, PUBSUB_NAME),
           HOST = coalesce(p_host, HOST),
            USER_NAME = coalesce(p_user_name, USER_NAME),
            AUTH_KEY = coalesce(p_auth_key, AUTH_KEY)
         where  APP_ID = p_app_id AND SERVICE_ID =  p_service_id AND PUBSUB_ID = p_pubsub_id;
    
    END TEST;
    

    【讨论】:

    • 很好,coalesce 或 NVL 将有助于简单的更新语句。
    猜你喜欢
    • 1970-01-01
    • 2011-12-07
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    相关资源
    最近更新 更多