Code in PL / SQL optimieren. Machen Sie es richtig. Code läuft, ist aber nicht richtig

Aug 20 2020

Ich habe 3 Tische. Quelltabelle

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

Zieltabelle

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

Konditionstabelle

BATCH_RUN_DETAILS(ENTITY_TYPE,LAST_RUN_DATE,MAX_LAST_UPDATE_DATE)

Wir müssen Daten aus ORGDE und ITEMDE in DYNAMICENTITYGTT einfügen. Aktion in DYNAMICENTITYGTT will be 'update' where CREATION_DATE>max_last_update_dateAktion DYNAMICENTITYGTT will be 'add' where CREATION_DATE<max_last_update_dateWenn p_entity_type vorhanden ist, werden Daten für diese Entität eingefügt, andernfalls werden Daten für beide Tabellen eingefügt.

Ich habe unten Code geschrieben. Ich möchte es verbessern und verbessern.

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;  

Können Sie bitte eine Verbesserung des Codes vorschlagen?

Antworten

2 KayaNatsumi Aug 20 2020 at 20:59

Dies wäre ähnlich wie bei der vorherigen Codezeile der plsql-Prozedur. versuchen, besser zu machen .

Was wir jetzt tun, ist das Hinzufügen JOINzu einer Tabelle, die einen batch_run_detailsFall enthält, der für jede Zeile bestimmt, welche Aktion basierend auf creation_dateund eingefügt werden muss max_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;

Und nur zur Vervollständigung aus dem vorherigen Beitrag, Single-Insert-Version:

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;
2 EdStevens Aug 20 2020 at 20:51

Das erste, was ich tun würde, um es zu verbessern, ist es so zu formatieren, dass es lesbar ist. Ich habe weniger Zeit gebraucht, um es zu formatieren, als es nötig war, um diesen Satz zu schreiben:

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;  

Als zweites würde ich den Namen von DYNAMICENTITYGTT in einen lesbaren Namen ändern, DYNAMIC_ENTITY_GTT. (Codiere es tatsächlich in Kleinbuchstaben. Ich zeige es in Großbuchstaben, weil es so im Datenwörterbuch ist. Ich schreibe tatsächlich meinen gesamten Code in Kleinbuchstaben.)

Warum fügen Sie zwei nahezu identische Zeilen in DYNAMICENTITYGTT ein ('add' und 'update')?

Der Name dieser Tabelle mit 'GTT' deutet darauf hin, dass es sich um eine globale temporäre Tabelle handelt. Ich würde also erwarten, dass Sie in derselben Sitzung tatsächlich etwas damit tun.

1 ThorstenKettner Aug 20 2020 at 21:30

Sie können dies in einer Einfügeanweisung tun, wenn Sie möchten. Verwenden Sie einfach UNION ALL, um die Abfrageergebnisse zusammenzukleben. Mit können CASE WHENSie entscheiden, ob Sie schreiben 'add'oder 'update'.

Ich mache hier auch einige Annahmen:

  1. Sie möchten nicht nur Zeilen für creation_date weniger oder mehr als schreiben max_last_update_date, sondern auch, wenn beide gleich sind .
  2. Zeilen, aus denen kopiert wurde, orgdemüssen immer den Entitätstyp haben 'ORG'(nicht null, wenn p_entity_type null ist). Gleiches gilt für itemdeund 'ITEM'.
  3. Von kopierte Zeilen orgdeerhalten das Flag 'update'/ in 'add'Abhängigkeit von batch_run_details, wobei entity_type = 'ORG'(nicht null, wenn p_entity_type null ist). Gleiches gilt für itemdeund 'ITEM'.

Der Ablauf:

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;

Wenn Sie dies mit separaten Anweisungen (dh nein UNION ALL) besser möchten, würde ich die WHEREBedingungen erneut außerhalb der Abfragen verschieben:

  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;