procedimiento plsql línea repetitiva de código. tratando de hacer de una mejor manera

Aug 21 2020

Tengo un escenario. Si el usuario pasa el parámetro Entity_type, debe insertar datos solo para ese entity( table). Si no pasa ningún parámetro, debe insertar datos para todas las tablas requeridas en una tabla.

entonces tenemos una tabla DYNAMICENTITYGTTque tomará datos de la Itemtabla si se pasa, orgtabla si se pasa. Pero tomará datos de la tabla si el Entity_typeparámetro es nulo en proc ..

También almacenará otra columna dependiendo del tipo de UPDATE_MODEmedio que agregue o elimine. La tabla de destino es la misma. La tabla de origen y su nombre de columna son diferentes pero el tipo es el mismo.

He escrito a continuación el procedimiento para el mismo.

Solo estoy solicitando si hay alguna forma para mejorar este código. Quiero decir, ¿se puede escribir esto de una manera más inteligente? Porque estoy repitiendo varias líneas. He dado un ejemplo de 2 entidades pero hay 7, por lo que el código sería enorme.

CREATE OR REPLACE procedure UPDATE_DYNAMIC_ENTITY(ENTITY_TYPE varchar2 default null,UPDATE_MODE varchar2)
Is
x number;
BEGIN
IF UPPER(entity_type)='ITEM' then
    if upper(UPDATE_MODE)='DELETE' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'delete' from ITEMDE;
    ELSIF lower(UPDATE_MODE)='add' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'add' from ITEMDE;
    END IF;
ELSIF UPPER(entity_type)='ORG' then
    if upper(UPDATE_MODE)='DELETE' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'delete' from ORGDE;
    ELSIF lower(UPDATE_MODE)='add' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'add' from ORGDE;
    END IF;
ELSE
   if upper(UPDATE_MODE)='DELETE' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'delete' from ITEMDE;
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'delete' from ORGDE;
    ELSIF lower(UPDATE_MODE)='add' then
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,Item_id,item_name,item_desc,'add' from ITEMDE;
      INSERT INTO DYNAMICENTITYGTT(Entity_type,Entity_id,Entity_code,Synonyms,Action) select Entity_type,ORG_id,org_name,org_desc,'add' from ORGDE;
   END IF;
   
END IF;
END UPDATE_DYNAMIC_ENTITY;

Respuestas

1 KayaNatsumi Aug 20 2020 at 22:10

Básicamente veo dos inserciones con dos variables que determinan su contenido. Está insertando desde la declaración de selección, por lo tanto, puede manipular estas selecciones para no devolver valores cuando las condiciones no sean las esperadas.

Para el parámetro p_update_modees fácil, si contiene el valor "eliminar" insertar "eliminar", si contiene el valor "agregar" insertar "agregar".

Para el parámetro p_entity_type, insertamos de ambas selecciones cuando su valor es "NULL", solo de la itemdetabla si el valor es "ELEMENTO" y solo de la orgdetabla si el valor es "ORG".

Ahora, en caso de que haya algún valor no válido en p_entity_typeninguna de las selecciones, se producirán datos, ya que solo reconocemos "NULL", "ITEM" y "ORG". Pero para el parámetro p_update_modemodificamos directamente el valor y lo usamos en la inserción, por lo tanto, sería mejor realizar alguna verificación si el valor de entrada es válido para nosotros.

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  IF lower(p_update_mode) NOT IN ('add', 'delete')
  THEN
    RAISE VALUE_ERROR; -- maybe use raise_application_error for more details about problem
  END IF;
  --
  INSERT INTO dynamicentitygtt
    (entity_type, entity_id, entity_code, synonyms, action)
    SELECT upper(NVL(p_entity_type, 'ITEM')), item_id, item_name, item_desc, lower(p_update_mode)
      FROM itemde
     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')), org_id, org_name, org_desc, lower(p_update_mode)
      FROM orgde
     WHERE upper(p_entity_type) = 'ORG'
        OR p_entity_type IS NULL;
END update_dynamic_entity;

Mientras escribe, tiene 7 entidades, por lo tanto, este enfoque llevaría a tener 7 inserciones, ya que creo (y avíseme si me equivoco) cada entidad tiene su propio conjunto de datos en diferentes tablas.

También existe la posibilidad de unir todas estas tablas y convertirlas en una sola inserción como se muestra a continuación, y cada nueva entidad significaría solo agregar una nueva selección en WITHparte de la declaración. Pero no estoy seguro del rendimiento en este caso. Eso dependería de lo llenas que estén tus mesas.

CREATE OR REPLACE PROCEDURE update_dynamic_entity(p_entity_type VARCHAR2 DEFAULT NULL,
                                                  p_update_mode VARCHAR2) IS
BEGIN
  IF lower(p_update_mode) NOT IN ('add', 'delete')
  THEN
    RAISE VALUE_ERROR; -- maybe use raise_application_error for more details about problem
  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
        FROM itemde
      UNION ALL
      -- ORG table
      SELECT 'ORG' entity_type, -- This separates inserted values
              org_id,
              org_name,
              org_desc
        FROM orgde
      -- NEXT entity table
      )
    SELECT upper(entity_type), data_id, data_name, data_desc, lower(p_update_mode)
      FROM data_view
     WHERE upper(p_entity_type) = entity_type
        OR p_entity_type IS NULL;
END update_dynamic_entity;

E incluso si esto se complica para usted, puede crear un VIEWlugar en el que haga las UNIONs y eliminarlo WITHde PROCEDUREy con nuevas entidades agregando selecciones en VIEWlugar de PROCEDURE.