Как использовать динамическую таблицу во вложенном цикле в оракуле PL SQL - PullRequest
0 голосов
/ 14 февраля 2019

У меня есть сценарий оракула PL SQL, который имеет два цикла for (вложенный).Во втором цикле я не могу динамическое имя таблицы в запросе выбора.Это всегда принимает статический запрос. Но я хочу динамическое имя таблицы, как SIGNALALERTPROP_1, SIGNALALERTPROP_2 ... и т. д. может кто-нибудь, пожалуйста, помогите разобраться в этой проблеме.Я дал ниже сценарий SQL

/**
 * 
 * Script to add two new columns abbrev and color to SIGNALALERTPROP_% table * 

 * 
 * Prompts for input parameter: update_scope
 * Response can be a specific configuration ID, ALL for all configurations
 * 
 * The script logs progress and errors and warnings to the spool file.
 */

SPOOL update_signalalertprop.log
SET SERVEROUTPUT ON
SET VERIFY OFF
ACCEPT update_scope PROMPT "Enter Signal Configuration ID, or ALL [ALL]: " DEFAULT ALL

declare
configId number;
alertprop_tablename varchar2(20);
v_abrev varchar2(1 CHAR);
v_colorId number;
block varchar2(4000);

procedure executeBlock (block varchar2) is    
begin
  begin
    execute immediate block;
    exception when others then
      dbms_output.put_line('');
      dbms_output.put_line('Error executing...');
      dbms_output.put_line(substr(block, 1, 100));
      dbms_output.put_line(SQLERRM); 
      dbms_output.put_line('');
      return;
  end; 
end;

function stringToInt(p_str in varchar2) return number as
 retVal number := null;
begin
 if regexp_instr(p_str, '^[[:space:]]*[[:digit:]]{1,5}[[:space:]]*$') > 0 then
  retVal := to_number(p_str);
 end if;
return retVal;
end;

function does_constraint_exist (i_constraint_name varchar2 ) return boolean is    
    cnt number;    
    begin
    select count(*) into cnt from user_constraints where constraint_name = i_constraint_name;
    return (cnt > 0);
end; 

begin
    configId := stringToInt('&update_scope');
    alertprop_tablename := 'SIGNALALERTPROP_' || configId;
FOR v_rec IN (select 'SIGNALALERTPROP' item_type, id config_id from signalconfig where id = decode(configId, null, id, configId)) LOOP
    dbms_output.put_line('');
    dbms_output.put_line('Adding Columns to SIGNALALERTPROP_' || v_rec.config_id );
    dbms_output.put_line('table_name=' || v_rec.item_type || ', config_id=' || v_rec.config_id);
    dbms_output.put_line('');
    block := 'ALTER TABLE SIGNALALERTPROP_' || v_rec.config_id || ' ADD (ABBREV VARCHAR2(1 CHAR) DEFAULT null, COLOR DEFAULT 0 NOT NULL )';
    executeBlock(block);

    -- adding foreign key
    if(not does_constraint_exist('SIGNALALERTPROP_COLOR_'||configId||'_FK'))
    then
      block := 'ALTER TABLE "SIGNALALERTPROP_'||configId||'" ADD CONSTRAINT "SIGNALALERTPROP_COLOR_'||configId||'_FK" FOREIGN KEY ( color )
      REFERENCES "SIGNALALERTCOLORS" ( id )
      NOT DEFERRABLE';
      executeBlock(block);
    end if; 

    -- update color and abbrev for tracked alerts
    -- 
 FOR v_alert_rec IN (select ID alertPropId, LABEL alertLabel from alertprop_tablename WHERE ALERT_TYPE = 2 ) LOOP
    v_abrev := SUBSTR(v_alert_rec.alertLabel, 1, 1);    
    v_colorId := MOD(v_alert_rec.alertPropId, 14) + 1;
    dbms_output.put_line('v_abrev ' || v_abrev);
    dbms_output.put_line('v_colorId ' || v_colorId);
    block := 'UPDATE SIGNALALERTPROP_'||configId||  ' SET COLOR = ' || v_colorId || ', ABBREV = ' || v_abrev || ' WHERE ID = ' || v_alert_rec.alertPropId ;
    executeBlock(block);    
    dbms_output.put_line('block ' || block);

END LOOP; 
END LOOP;
commit; 
end;
/
spool off;

я получаю сообщение об ошибке, как v_alert_rec является недействительным.Я проверил FOR v_alert_rec IN (выберите ID alertPropId, LABEL alertLabel из alertprop_tablename WHERE ALERT_TYPE = 2) LOOP эта строка не работает, так как alertprop_tablename не заполняется.

1 Ответ

0 голосов
/ 14 февраля 2019

alertprop_tablename не является объектом базы данных, поэтому попытка выбрать из него значения не будет работать.

Вам нужен курсор для динамического SQL и цикл по нему.

Вот пример того, как это работает

...