【问题标题】:Optimizing code in PL/SQL. Making it to proper. Code is running but not proper优化 PL/SQL 中的代码。使其正确。代码正在运行但不正确
【发布时间】:2020-12-10 05:39:40
【问题描述】:

我有 3 组桌子。 源表

ORGDE(ORG_ID,ORG_NAME,ORG_DESC,CREATION_DATE,LAST_UPDATE_DATE)       
ITEMDE(ITEM_ID,ITEM_NAME,ITEM_DESC,CREATION_DATE,LAST_UPDATE_DATE)   

目标表

DYNAMICENTITYGTT(ENTITY_TYPE,ENTITY_ID,ENTITY_CODE,SYNONYMS,ACTION)

条件表

BATCH_RUN_DETAILS(ENTITY_TYPE,LAST_RUN_DATE,MAX_LAST_UPDATE_DATE)

我们必须在 DYNAMICENTITYGTT 中插入来自 ORGDE 和 ITEMDE 的数据。 DYNAMICENTITYGTT will be 'update' where CREATION_DATE>max_last_update_date 中的操作 行动在DYNAMICENTITYGTT will be 'add' where CREATION_DATE<max_last_update_date 如果 p_entity_type 存在,那么它将为该实体插入数据,否则它将为两个表插入。

我写了下面的代码。我想改进它,让它变得更好。

CREATE OR REPLACE procedure UPDATE_DYNAMIC_ENTITY(P_ENTITY_TYPE varchar2 default null,P_UPDATE_MODE varchar2)
IS
BEGIN
IF UPPER(P_UPDATE_MODE)='INCREMENTAL'
THEN
 IF UPPER(p_entity_type)='ORG' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select P_Entity_type,ORG_id,org_name,org_desc,'add' from ORGDE where creation_date>(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
     INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select P_Entity_type,ORG_id,org_name,org_desc,'update' from ORGDE where creation_date<(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
 ELSIF UPPER(p_entity_type)='ITEM' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select P_Entity_type,item_id,item_name,item_desc,'add' from ITEMDE where creation_date>(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
     INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select P_Entity_type,item_id,item_name,item_desc,'update' from ITEMDE where creation_date<(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
 ELSIF P_ENTITY_TYPE=NULL THEN
     --Reading from org
     INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select p_Entity_type,ORG_id,org_name,org_desc,'add' from ORGDE where creation_date>(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
     INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select p_Entity_type,ORG_id,org_name,org_desc,'update' from ORGDE where creation_date<(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
     --reading from item
     INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select p_Entity_type,item_id,item_name,item_desc,'add' from ITEMDE where creation_date>(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
     INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select p_Entity_type,item_id,item_name,item_desc,'update' from ITEMDE where creation_date<(select max_last_update_date from BATCH_RUN_DETAILS where ENTITY_TYPE=P_ENTITY_TYPE);
  END IF;
END IF;
END UPDATE_DYNAMIC_ENTITY;  

您能否提出改进代码的建议。

【问题讨论】:

  • 只是注释ELSIF P_ENTITY_TYPE=NULL THEN 将始终导致错误。正确的条件是ELSIF P_ENTITY_TYPE IS NULL THEN
  • @KayaNatsumi 非常感谢。我批准了更改。你能帮我更好地修改上面的代码吗?
  • where ENTITY_TYPE=P_ENTITY_TYPE 存在同样的问题。 select p_Entity_type 可以为 null 可能也不是有意的。

标签: oracle plsql oracle11g oracle-sqldeveloper plsqldeveloper


【解决方案1】:

这与之前plsql procedure repetitive line of code. trying to make in better way 的回答类似。

我们现在要做的是将JOIN 添加到包含batch_run_details 的表中,并根据creation_datemax_last_update_date 确定每一行必须插入的操作。

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  IF lower(p_update_mode) <> 'incremental'
  THEN
    RETURN; -- Do nothing if incorrect mode
  END IF;
  --
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    SELECT upper(NVL(p_entity_type, 'ITEM')),
           t.item_id,
           t.item_name,
           t.item_desc,
           CASE
             WHEN t.creation_date > b.max_last_update_date THEN
               'update'
             WHEN t.creation_date < b.max_last_update_date THEN
               'add'
           END
      FROM itemde t
      JOIN batch_run_details b
        ON b.entity_type = 'ITEM'
     WHERE upper(p_entity_type) = 'ITEM'
        OR p_entity_type IS NULL;
  --
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    SELECT upper(NVL(p_entity_type, 'ORG')),
           t.org_id,
           t.org_name,
           t.org_desc,
           CASE
             WHEN t.creation_date > b.max_last_update_date THEN
               'update'
             WHEN t.creation_date < b.max_last_update_date THEN
               'add'
           END
      FROM orgde t
      JOIN batch_run_details b
        ON b.entity_type = 'ORG'
     WHERE upper(p_entity_type) = 'ORG'
        OR p_entity_type IS NULL;
END update_dynamic_entity;

为了完成上一篇文章,单插入版本也是如此:

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  IF lower(p_update_mode) <> 'incremental'
  THEN
    RETURN;
  END IF;
  --
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    WITH data_view AS
     ( -- ITEM table
      SELECT 'ITEM' entity_type, -- This separates inserted values
              item_id data_id,
              item_name data_name,
              item_desc data_desc,
              creation_date
        FROM itemde
      UNION ALL
      -- ORG table
      SELECT 'ORG' entity_type, -- This separates inserted values
              org_id,
              org_name,
              org_desc,
              creation_date
        FROM orgde
      -- NEXT entity table
      )
    SELECT upper(t.entity_type),
           t.data_id,
           t.data_name,
           t.data_desc,
           CASE
             WHEN t.creation_date > b.max_last_update_date THEN
               'update'
             WHEN t.creation_date < b.max_last_update_date THEN
               'add'
           END
      FROM data_view t
      JOIN batch_run_details b
        ON b.entity_type = t.entity_type
     WHERE upper(p_entity_type) = t.entity_type
        OR p_entity_type IS NULL;
END update_dynamic_entity;

【讨论】:

  • 基本上可以有两种模式,一种是满的,一种是增量的。在上一个问题中,我询问了完整的表格数据。在这种情况下,它是增量的。顺便说一句,我可以将其转换为简单的选择查询吗?这样我就可以在 UI 中使用它并在那里设置参数?
  • 我实际上将两个 if 块都放在了这段代码中。现在可以在单个块或单个查询中编写相同的内容吗?因为我们只将数据插入到单个表中?我们可以在单个查询中管理吗? stackoverflow.com/questions/63513687/…
  • 嗨,对不起,我之前睡过。您的问题已经有 Kevin McCabe 的答案,我认为它是正确的,并且与我会做的几乎完全相同。
  • 嗨,你能帮我解决这个问题吗stackoverflow.com/questions/63541003/…
【解决方案2】:

我要改进它的第一件事是格式化它,使其可读。我花的时间比写这句话的时间少:

CREATE OR replace PROCEDURE Update_dynamic_entity(
p_entity_type VARCHAR2 DEFAULT NULL,
p_update_mode VARCHAR2)
IS
BEGIN
    IF Upper(p_update_mode) = 'INCREMENTAL' THEN
      IF Upper(p_entity_type) = 'ORG' THEN
        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT p_entity_type,
               org_id,
               org_name,
               org_desc,
               'add'
        FROM   orgde
        WHERE  creation_date > (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);

        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT p_entity_type,
               org_id,
               org_name,
               org_desc,
               'update'
        FROM   orgde
        WHERE  creation_date < (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);
      ELSIF Upper(p_entity_type) = 'ITEM' THEN
        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT p_entity_type,
               item_id,
               item_name,
               item_desc,
               'add'
        FROM   itemde
        WHERE  creation_date > (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);

        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT p_entity_type,
               item_id,
               item_name,
               item_desc,
               'update'
        FROM   itemde
        WHERE  creation_date < (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);
      ELSIF p_entity_type = NULL THEN
        --Reading from org
        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT entity_type,
               org_id,
               org_name,
               org_desc,
               'add'
        FROM   orgde
        WHERE  creation_date > (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);

        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT entity_type,
               org_id,
               org_name,
               org_desc,
               'update'
        FROM   orgde
        WHERE  creation_date < (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);

        --reading from item
        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT entity_type,
               item_id,
               item_name,
               item_desc,
               'add'
        FROM   itemde
        WHERE  creation_date > (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);

        INSERT INTO dynamicentitygtt
                    (entity_type,
                     entity_id,
                     entity_code,
                     synonyms,
                     action)
        SELECT entity_type,
               item_id,
               item_name,
               item_desc,
               'update'
        FROM   itemde
        WHERE  creation_date < (SELECT max_last_update_date
                                FROM   batch_run_details
                                WHERE  entity_type = p_entity_type);
      END IF;
    END IF;
END update_dynamic_entity;  

我要做的第二件事是将 DYNAMICENTITYGTT 的名称更改为可读的名称 DYNAMIC_ENTITY_GTT。 (实际上是小写的。我用大写显示它,因为它在数据字典中是这样的。实际上我所有的代码都是用小写写的。)

为什么要在 DYNAMICENTITYGTT('add' 和 'update')中插入 两个 几乎相同的行?

带有“GTT”的表的名称表明它是一个全局临时表,所以我希望您在同一个会话中实际使用它。

【讨论】:

  • 谢谢埃德。实际上,添加和更新的条件几乎没有什么不同。表数据将被java读取并注入API。如果更新则将调用 PUT API 否则将使用数据调用 POST API。目标系统非常糟糕,所以创建数据时要牢记这一点。我可以使用 with 或 merge 命令以某种方式合并这两个插入吗?类似的东西?。
  • 啊,我错过了驱动插入的子选择条件下“大于”与“小于”的区别。
  • @Ed 谢谢。如果不是创建过程并从java调用它,我可以直接在java中使用select查询,这是否明智?我的意思是没有创建程序。我实际上是从 jdbc 调用这个过程。
  • 我更喜欢让所有数据处理尽可能接近数据。
【解决方案3】:

如果需要,您可以在一个插入语句中执行此操作。只需使用UNION ALL 将查询结果粘合在一起。使用CASE WHEN,您可以决定是写'add' 还是'update'

我在这里也做了一些假设:

  1. 您不仅要为creation_date 小于大于 写比max_last_update_date 的行,还希望两者相等 em>。
  2. orgde 复制的行应始终具有entity_type 'ORG'(当p_entity_type 为空时不为空)。 itemde'ITEM' 也是如此。
  3. orgde 复制的行应获得'update'/'add' 标志,具体取决于batch_run_details where entity_type = 'ORG'(当p_entity_type 为空时不为空)。 itemde'ITEM' 相同。

程序:

create or replace procedure update_dynamic_entity
(
  p_entity_type varchar2 default null,
  p_update_mode varchar2
) is
begin
  if upper(p_update_mode) = 'INCREMENTAL' then
    insert into dynamicentitygtt (entity_type, entity_id, entity_code, synonyms, action)
    select 
      'ORG', org_id, org_name, org_desc,
      case when creation_date > 
            (select max_last_update_date from batch_run_details where entity_type = 'ORG')
           then 'add' 
           else 'update'
      end
    from orgde
    where upper(p_entity_type) = 'ORG' or p_entity_type is null
    union all
    select 
      'ITEM', item_id, item_name, item_desc,
      case when creation_date >
            (select max_last_update_date from batch_run_details where entity_type = 'ITEM')
           then 'add' 
           else 'update'
      end
    from itemde
    where upper(p_entity_type) = 'ITEM' or p_entity_type is null;
  end if;
end update_dynamic_entity;

如果您更喜欢使用单独的语句(即没有 UNION ALL),我会再次将 WHERE 条件移到查询之外:

  if upper(p_update_mode) = 'INCREMENTAL' then
    if upper(p_entity_type) = 'ORG' or p_entity_type is null then
      insert into dynamicentitygtt (entity_type, entity_id, entity_code, synonyms, action)
      ...
      from orgde;
    end if;
    
    if upper(p_entity_type) = 'ITEM' or p_entity_type is null then
      insert into dynamicentitygtt (entity_type, entity_id, entity_code, synonyms, action)
      ...
      from itemde;
    end if;
  end if;

【讨论】:

  • 第二个代码有一个逻辑问题。两个 if 块都会运行。如果它是 org,那么这两个条件都将变为 true。要求是如果 p_entity_type 是 org 那么它应该为 orgde 插入数据,如果它是 item 那么它应该为 itemde 添加。如果它为空,那么 itemde 和 orgde 都是。
  • 这是有意的。 p_entity_type 不能同时是“ORG”和“ITEM”。所以如果是'ORG',只写'ORG'行,如果是'ITEM',就只写'ITEM'行,如果为null,都写。 (联合查询具有相同的逻辑,顺便说一句。)
  • 是的,现在很清楚了。谢谢@Thorsten。我很困惑。
  • 谢谢托尔斯滕。如果不是创建过程并从java调用它,我可以直接在java中使用select查询吗?我的意思是没有创建程序。我实际上是从 jdbc 调用这个过程。
  • 我认为,如果您从 Java 插入或创建一个过程并从 Java 调用它,这并没有太大的区别。我更喜欢这个程序。如果您想更改代码,则不必部署更改后的 Java 应用程序。这也使得以后用新的东西替换你的 Java 应用程序变得更容易,因为逻辑在数据库中,而应用程序只是调用一个过程。
猜你喜欢
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-07
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多