oracle-databaseplsqlora-00942

create and use table within one plsql block


I'm trying to create a user defined alert for oracle cloud control for long running statements. So that's the reason I can't do some specific actions (like create required table) before clock execution. There is an issue:

Error report -
ORA-06550: line 32, column 10:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 30, column 5:
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

When I run this peace of code:

SET SERVEROUTPUT ON
DECLARE
    -- VARIABLES
    sql_id_var V$SESSION.sql_id%TYPE;
    SQL_CHILD_NUMBER_var  V$SESSION.SQL_CHILD_NUMBER%TYPE;
    ALREADY_EXISTS NUMBER := 0;

    --TO GET SQL_ID,CHILD_ID
    CURSOR  sql_id_cursor IS
    select ses.sql_id, ses.SQL_CHILD_NUMBER
    from V$SESSION ses
    where SES.STATUS = 'ACTIVE'
    and SES.USERNAME is not null
    --and Ses.AUDSID <> userenv('SESSIONID') 
    and ses.sql_id is not null
    and (SYSDATE - ses.SQL_EXEC_START) > 5/(24*60*60) --SECONDS;

begin

 --CREATE TABLE TO STORE SQL_ID OF LONG RUNNING QUERIES
 EXECUTE IMMEDIATE 'CREATE TABLE LONG_SQL (SQL_ID VARCHAR2(13),
                     SQL_CHILD_NUMBER NUMBER,
                     DETECTED_DATE DATE)' ;
  exception when others then
  if SQLCODE = -00955 then null;dbms_output.put_line( 'TABLE EXISTS ' ); else raise; end if;


  --PROCESSING EVERY LONG QUER
  FOR sql_id_row IN sql_id_cursor
  LOOP
    dbms_output.put_line( 'SQL_ID: ' || sql_id_row.sql_id || ' , SQL_CHILD_NUMBER: ' ||  sql_id_row.SQL_CHILD_NUMBER || ' , NOW IS :' || SYSDATE);
    SELECT COUNT(*)
    INTO ALREADY_EXISTS
    FROM LONG_SQL
    WHERE LONG_SQL.SQL_ID = sql_id_row.sql_id
    AND LONG_SQL.SQL_CHILD_NUMBER = sql_id_row.SQL_CHILD_NUMBER;
    dbms_output.put_line( 'SQL_ID: ' || sql_id_row.sql_id || ' , SQL_CHILD_NUMBER: ' ||  sql_id_row.SQL_CHILD_NUMBER || ' , FOUND ' || ALREADY_EXISTS || ' TIMES INTO LOG TABLE');

  END LOOP;


end;
/

Within this plsql I create table LONG_SQL if it's not exists and then I want to make some query that uses this new table. Could you suggest something here to workaround it? Is it possible to create and then use table within one plsql block?


Solution

  • Those who live by dynamic SQL, die by dynamic SQL.

    If you created table dynamically, you'll have to use it dynamically as well. In other words, this query:

    SELECT COUNT(*)
        INTO ALREADY_EXISTS
        FROM LONG_SQL ...
    

    will also have to be dynamic and executed with execute immediate.