Mengoptimalkan kode di PL / SQL. Membuatnya menjadi benar. Kode berjalan tetapi tidak sesuai

Aug 20 2020

Saya memiliki 3 set tabel. Tabel sumber

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

Tabel target

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

Tabel kondisi

BATCH_RUN_DETAILS(ENTITY_TYPE,LAST_RUN_DATE,MAX_LAST_UPDATE_DATE)

Kami harus memasukkan data dalam DYNAMICENTITYGTT dari ORGDE dan ITEMDE. Action in DYNAMICENTITYGTT will be 'update' where CREATION_DATE>max_last_update_dateAction DYNAMICENTITYGTT will be 'add' where CREATION_DATE<max_last_update_datejika p_entity_type ada maka itu akan memasukkan data untuk entitas itu yang lain akan disisipkan untuk kedua tabel.

Saya telah menulis kode di bawah ini. saya ingin memperbaikinya dan membuatnya lebih baik.

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;  

Bisakah Anda menyarankan perbaikan pada kode.

Jawaban

2 KayaNatsumi Aug 20 2020 at 20:59

Ini akan serupa dengan jawaban sebelumnya pada prosedur plsql baris kode berulang. mencoba membuatnya dengan cara yang lebih baik .

Apa yang kita lakukan sekarang adalah menambahkan JOINke tabel yang berisi batch_run_detailsdan kasus yang akan menentukan untuk setiap baris tindakan apa yang harus disisipkan berdasarkan creation_datedan 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;

Dan hanya untuk menyelesaikan dari posting sebelumnya, versi sisipan tunggal juga:

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

Hal pertama yang akan saya lakukan untuk memperbaikinya adalah memformatnya agar dapat dibaca. Saya membutuhkan lebih sedikit waktu untuk memformatnya daripada yang dibutuhkan untuk menulis kalimat ini:

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;  

Hal kedua yang akan saya lakukan adalah mengubah nama DYNAMICENTITYGTT menjadi nama yang dapat dibaca, DYNAMIC_ENTITY_GTT. (sebenarnya kode itu dalam huruf kecil. Saya tunjukkan dalam huruf besar karena begitulah dalam kamus data. Saya sebenarnya menulis semua kode saya dalam huruf kecil.)

Mengapa Anda menyisipkan dua baris yang hampir identik ke DYNAMICENTITYGTT ('add', dan 'update')?

Nama tabel itu, dengan 'GTT' menunjukkan itu adalah Tabel Sementara Global, jadi saya berharap Anda benar-benar melakukan sesuatu dengannya, di sesi yang sama.

1 ThorstenKettner Aug 20 2020 at 21:30

Anda dapat melakukan ini dalam satu pernyataan sisipan, jika Anda mau. Cukup gunakan UNION ALLuntuk merekatkan hasil kueri. Dengan CASE WHENAnda dapat memutuskan apakah akan menulis 'add'atau 'update'.

Saya juga membuat beberapa asumsi di sini:

  1. Anda tidak hanya ingin menulis baris creation_date kurang atau lebih besar dari max_last_update_date, tetapi juga ketika keduanya sama .
  2. Baris yang disalin dari orgdeharus selalu memiliki jenis_itas 'ORG'(bukan null jika p_entity_type null). Sama untuk itemdedan 'ITEM'.
  3. Baris yang disalin orgdeakan mendapatkan 'update'/ 'add'flag bergantung pada batch_run_details di mana entity_type = 'ORG'(bukan null jika p_entity_type null). Sama untuk itemdedan 'ITEM'.

Prosedur:

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;

Jika Anda menginginkan ini lebih baik dengan pernyataan terpisah (yaitu tidak UNION ALL), saya akan memindahkan WHEREkondisi di luar kueri lagi:

  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;