Title: DDL alter in execute immediate pl/sql procedure - dynamic sql

If someone has a few minutes to read through this, I'd be most appreciative.  I could use a second set of eyes looking this over. 

This procedure is designed to maintain a table/sequence map, executed after an import and increment any sequences which have a lower nextval that the max value in the column it's supposed to be matching.  Often the sequences are out-of-sync after an import (even full=y and direct=y) and we have to manually adjust them.  This is an effort to automate the process.   

These are the displays and error from the procedure, and the code follows.  The problem is in the execute immediate which is doing DDL.  It's Oracle 8.1.7 on Solaris so DDL in execute immediate alter is supposed to work.  The execute immediate insert does work.   

Any suggestions or comments are welcome.  Thanks, Linda


top of loop, counter is:1
top of loop, counter is:2
top of loop, counter is:3
top of loop, counter is:4
top of loop, counter is:5
top of loop, counter is:6
top of loop, counter is:7
top of loop, counter is:8
top of loop, counter is:9
top of loop, counter is:10
top of loop, counter is:11
top of loop, counter is:12
Show l_sql_string 4 DECLARE L_SEQUENCE_OWNER   VARCHAR2(30):= :1; L_SEQUENCE_NAME    VARCHAR2(30):= :2; BEGIN insert into

dbauser.table_sequence_map values (:1,:2, null,null,null,sysdate,sysdate); END;
top of loop, counter is:13
top of loop, counter is:14
top of loop, counter is:15
top of loop, counter is:16
top of loop, counter is:17
top of loop, counter is:18
top of loop, counter is:19
Show l_sql_string 1 DECLARE L_SEQUENCE_OWNER   VARCHAR2(30):= :1; L_SEQUENCE_NAME    VARCHAR2(30):= :2; L_INCREMENT_VALUE  NUMBER

:= :3; BEGIN alter sequence :1.:2 increment by :3; END;
BEGIN table_sequence_mender ('01-DEC-2001','dev01') ; END;

*
ERROR at line 1:
ORA-06550: line 1, column 129:
PLS-00103: Encountered the symbol "ALTER" when expecting one of the following:
begin declare exit for goto if loop mod null pragma raise
return select update while <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
close current delete fetch lock insert open rollback
savepoint set sql execute commit forall
<a single-quoted SQL string>
ORA-06512: at "DBAUSER.TABLE_SEQUENCE_MENDER", line 148
ORA-06512: at line 1


 
 create or replace procedure table_sequence_mender (date_in in date, ORACLE_SID in char ) is
    fileid0 UTL_FILE.FILE_TYPE;
    c_sequences_added    number ;
    c_sequences_unmapped number ;
    c_sequences_ok       number ;
    c_sequences_fixed    number ;
    c_sequences_total    number ;
    v_column_name        varchar(30);
    v_create_dt          date ;
    v_dt                 date ;
    v_increment          number ;
    v_max_column         number ;
    v_nextval            number ;
    v_sequence_owner     varchar(30);
    v_sequence_name      varchar(30);
    v_sqlcode            number ;
    v_table_owner        varchar(30);
    v_table_name         varchar(30);
    v_sql                varchar(200) ;
    v_cursor_id          integer;
    v_insert             varchar(200) ;
    l_sql_string         varchar(2000) ;
   
--
-- The purpose of this procedure is to adjust the existing sequences after an import to match the dependent columns.
-- Requirements: A table matching the sequences to the table/column names.  This is built manually because there is
-- no physical relationship between a sequence and a column.  The table is populated by install_sequence_mender.ksh.
-- The execution is running under userid dbauser.  Table access in PL/SQL will not use roles, but individual grants;
-- Therefore a grant of DBA to dbauser is insufficient to run this procedure.  The install ksh grants the necessary
-- authority to dbauser. 
--
cursor c is
   select sequence_owner, sequence_name
   from dba_sequences
   where sequence_owner not in ('SYS','SYSTEM') ;

Begin
  c_sequences_added    := 0 ;
  c_sequences_ok       := 0 ;
  c_sequences_fixed    := 0 ;
  c_sequences_unmapped := 0 ;
  c_sequences_total    := 0 ;

        if date_in is null
    then v_dt := sysdate;
    else v_dt := date_in;
  end if;
  Begin
-- Scan table_sequence_map and delete any rows for sequences that no longer exist
  Delete from table_sequence_map where sequence_owner||sequence_name not in
    (select sequence_owner||sequence_name from dba_sequences) ;
  End ;

-- start processing the rows in dba_sequences
  begin
    for i_row in c loop
      c_sequences_total := c_sequences_total + 1 ;
      dbms_output.put_line ('top of loop, counter is:'||c_sequences_total ) ;
        begin
-- For every row in dba_sequences, find a matching row in the table_sequence_map
         select table_owner, table_name, column_name, create_dt
         into v_table_owner, v_table_name, v_column_name, v_create_dt
         from dbauser.table_sequence_map a
         where i_row.sequence_owner = a.sequence_owner
         and   i_row.sequence_name = a.sequence_name ;
         v_sqlcode := SQLCODE ;
-- If a row exists for the sequence, and if the table information is populated,
-- then check the max value in the data column and the nextval from the sequence. 
         if v_sqlcode = 0 then
           if v_table_owner is not null and v_table_name is not null and v_column_name is not null
              then begin
              v_sql := 'select max('||v_column_name||') from '||v_table_owner||'.'||v_table_name ;
              execute immediate v_sql into v_max_column ;
              v_sql := 'select '||i_row.sequence_owner||'.'||i_row.sequence_name||'.nextval from dual ' ;
              execute immediate v_sql into v_nextval ;
                end ;
-- If the max column number is > the nextval, it means the sequence is broken or out of sync and
-- has to be incremented to higher than the max column.  Do the math to find the difference,
-- alter the sequence increment, call it to move the number up, and alter the sequence increment
-- back to 1. 
                            if v_max_column > v_nextval   then begin  v_increment := v_max_column - v_nextval + 1 ;          

                                     l_sql_string:= 'DECLARE '||
                                                    'L_SEQUENCE_OWNER   VARCHAR2(30):= :1; '||
                                                    'L_SEQUENCE_NAME    VARCHAR2(30):= :2; '||
                                                    'L_INCREMENT_VALUE  NUMBER      := :3; '||
                                                    'BEGIN '; 
                                    
                                     l_sql_string:= l_sql_string||'alter sequence :1.:2 increment by :3; END;';
             dbms_output.put_line ('Show l_sql_string 1 '||l_sql_string) ;
                                     execute immediate l_sql_string using i_row.sequence_owner, i_row.sequence_name, v_increment ;

                                     commit;
           
                                     l_sql_string:= 'DECLARE '||
                                                    'L_SEQUENCE_OWNER   VARCHAR2(30):= :1; '||
                                                    'L_SEQUENCE_NAME    VARCHAR2(30):= :2; '||
                                                    'L_INCREMENT_VALUE  NUMBER      := :3; '||
                                                    'BEGIN '; 
                                     l_sql_string:= l_sql_string||'select :1.:2 into v_nextval from dual; END;';
             dbms_output.put_line ('Show l_sql_string 2 '||l_sql_string) ;
                                     execute immediate l_sql_string using i_row.sequence_owner, i_row.sequence_name  ;
                                     commit;
                                    
                                     l_sql_string:= 'DECLARE '||
                                                    'L_SEQUENCE_OWNER   VARCHAR2(30):= :1; '||
                                                    'L_SEQUENCE_NAME    VARCHAR2(30):= :2; '||
                                                    'L_INCREMENT_VALUE  NUMBER      := :3; '||
                                                    'BEGIN '; 
                                     l_sql_string:= l_sql_string||'alter sequence :1.:2 increment by 1; END; ';
             dbms_output.put_line ('Show l_sql_string 3 '||l_sql_string) ;
                                     execute immediate l_sql_string using i_row.sequence_owner, i_row.sequence_name  ;
                                     commit;

                          c_sequences_fixed := c_sequences_fixed + 1 ;
             end ;       
              end if ;
-- If the table_sequence_map contains an entry for the sequence, but the table information is blank,
-- it means that the sequence was added to the database, and to the table_sequence_map by a previous
-- execution of this job, and the table information was never added.  Updating the table information
-- has to be manual because there are no naming conventions to guarantee that a
-- sequence and column are associated.
           elsif ( (v_table_owner is null) or (v_table_name is null) or (v_column_name is null) ) then
           dbms_output.put_line (i_row.sequence_owner||'.'||i_row.sequence_name||' is not mapped in table_sequence_map since '||v_create_dt ) ;

          c_sequences_unmapped := c_sequences_unmapped + 1  ;
          end if ;
        end if ;
        exception
-- If there's no entry in the table_sequence_map for the sequence, it means a new sequence has been
-- added to the database.  This section will add a row for the sequence to the table_sequence_map. 
-- The table and column information has to be manually entered with an update statement as there's
-- no naming convention to guarantee that a sequence and column are associated.
         when no_data_found
                 then
                  begin
                   l_sql_string:= 'DECLARE '||
                                                    'L_SEQUENCE_OWNER   VARCHAR2(30):= :1; '||
                                                    'L_SEQUENCE_NAME    VARCHAR2(30):= :2; '||
                                                    'BEGIN '; 
    l_sql_string:= l_sql_string||'insert into dbauser.table_sequence_map values (:1,:2, null,null,null,sysdate,sysdate); END;';

             dbms_output.put_line ('Show l_sql_string 4 '||l_sql_string) ;
                                     execute immediate l_sql_string using i_row.sequence_owner, i_row.sequence_name  ;
                                     commit;
                                     exception
            when no_data_found then null ;
            c_sequences_added := c_sequences_added + 1   ;
                               dbms_output.put_line ('New row added to the map table '||i_row.sequence_owner||'.'||i_row.sequence_name ) ;

            COMMIT ;
            end ;
         when others then raise ;
       end ;
      end loop ;
     end ;
  end ;
/

 











 

Reply via email to