我有一个oracle 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(从alertprop_tablename WHERE ALERT_TYPE = 2中选择ID alertPropId,LABEL alertLabel)循环此行,因为alertprop_tablename未填充,因此它失败了。
答案 0 :(得分:1)
alertprop_tablename
不是数据库对象,因此尝试从中选择值将无效。
您需要的是动态SQL的游标,并在其中进行遍历。