How to execute ORACLE APEX PLSQL Dynamic Content - oracle

I am new to Oracle APEX, i am trying to import csv file then parse the file contents, actually we have various staging table, according to that i need to write some logic like below, can anyone please let me know how to execute plsql dynamic content in oracle apex.
DECLARE
p_TABLE_NAME VARCHAR2(50);
p_file_name VARCHAR2(255);
l_columns_item varchar2(4000);
l_ddl VARCHAR2(4000);
BEGIN
p_TABLE_NAME := :P120_TABLENAME;
p_file_name := :P120_BRO_FILENAME;
IF p_TABLE_NAME = 'DUMMY' THEN
l_columns_item := 'col001,col002,col003,col004,col005,col006,col007,col008,col009';
END IF;
l_ddl := 'select line_number,'
|| l_columns_item
|| ' '
|| 'from apex_application_temp_files f, '
|| ' table( apex_data_parser.parse(
p_content => f.blob_content,
p_add_headers_row => 'Y',
p_max_rows => 50,
p_store_profile_to_collection => 'FILE_PARSER_COLLECTION',
p_file_name => f.filename )) p '
|| 'where f.name ='''
|| p_file_name
|| '''';
execute immediate l_ddl;
RETURN l_ddl;
END;
The variable l_ddl contain below query how do i execute using oracle apex plsql dynamic content
select line_number,col001,col002,col003,col004,col005,col006,col007,col008,col009,col010,col011,col012,col013 from apex_application_temp_files f, table( apex_data_parser.parse(
p_content => f.blob_content,
p_max_rows => 50,
p_file_name => f.filename )) p where f.name ='a.csv'

Related

Send SQL query output as CSV attachment (pl/sql)

I have a pl/sql query and I want it's output to be sent in email in CSV format straightaway. I have no directory to first create and save a CSV file and then pick it up to send as an attachment.
Please help with your inputs as I am not able to get away.
Regards,
Sachin
Finally figured out a solution with the help of pointers received and providing the same to further help in case someone else needs in future.
My problem was that I was mostly seeing the examples where i could either save the file on a directory or pick the file from a directory to send as an attchment but I had no provision of directory and I wanted query result to be put in CSV and sent in email dynamically. So here is the complete solution.
CREATE OR REPLACE PROCEDURE SEND_CSV_ATTACHMENT AS
v_sender VARCHAR2(130);
v_recipients VARCHAR2(4000);
v_cc VARCHAR2(4000);
v_bcc VARCHAR2(2000);
v_subj VARCHAR2(200);
v_msg CLOB;
v_mime VARCHAR2(40);
v_tbl VARCHAR2(20000);
c_cr_lf CONSTANT CHAR (2) := (CHR (13) || CHR (10)); -- Carriage Return/Line Feed characters for formatting text emails
v_loop_count PLS_INTEGER := 0;
v_attachment CLOB;
v_block_qry VARCHAR2(3000);
v_block_row VARCHAR2(6000);
TYPE bl_cur IS REF CURSOR;
v_result bl_cur;
v_rowcount NUMBER;
errMsg VARCHAR2(15000);
BEGIN
v_sender := 'somesender#xyzcommunications.com';
SELECT NVL(EMAIL_LIST, 'someone#abcd.com')
FROM
(
SELECT LISTAGG(EMAIL_ID, ',') WITHIN GROUP (ORDER BY EMAIL_ID) AS EMAIL_LIST FROM RECIPEINTS_TABLE WHERE SEND_TO = 1 AND IS_ACTIVE = 1
);
SELECT NVL(EMAIL_LIST, 'someone#abcd.com')
FROM
(
SELECT LISTAGG(EMAIL_ID, ',') WITHIN GROUP (ORDER BY EMAIL_ID) AS EMAIL_LIST FROM RECIPEINTS_TABLE WHERE SEND_CC = 1 AND IS_ACTIVE = 1
);
v_bcc := 'someone#abcd.com';
-- Generate attachment - Begin
v_attachment := '"COL1", "COL2"' || CHR(13) || CHR(10);
v_block_qry := 'SELECT ''"'' || COL1 || ''", "'' || COL2 || ''"'' AS ROWTXT
FROM MY_TABLE';
OPEN v_result FOR v_block_qry;
LOOP
v_rowcount := v_result%ROWCOUNT;
FETCH v_result INTO v_block_row;
EXIT WHEN v_result%NOTFOUND;
v_attachment := v_attachment || v_block_row || chr(13) || chr(10);
END LOOP;
CLOSE v_result;
-- Generate attachment - End
v_subj:= 'MAIL_SUBJECT ' || TO_CHAR(TRUNC(SYSDATE-1), 'YYYY-MM-DD');
UTL_MAIL.send_attach_varchar2(sender => v_sender,
recipients => v_recipients,
cc => v_cc,
bcc => v_bcc,
subject => v_subj,
message => v_msg,
mime_type => 'text/html; charset=us-ascii', -- send html e-mail
attachment => v_attachment,
att_inline => FALSE,
att_filename => 'Change_Report' || TO_CHAR(TRUNC(SYSDATE-1), 'YYYY-MM-DD') || '.csv');
EXCEPTION
WHEN OTHERS THEN
errMsg := SQLERRM;
SEND_MAIL_HTML ('someone#abcd.com', NULL, NULL, errMsg, 'SEND_MAIL ERROR: ' || errMsg);
END SEND_CSV_ATTACHMENT;
You may create such a procedure :
create or replace procedure prFileSend is
v_mail_owner varchar2(100):='myname#someComp.com';
v_url varchar2(4000);
v_rep varchar2(4000);
delimiter varchar2(1) := chr(38);
begin
for c in ( select * from myTable )
loop
begin
v_url := 'http://www.mycompany.com/einfo/default.aspx?email='||c.email || delimiter || 'p1=' || c.col1 || delimiter ||'p2='||c.col2;
v_rep := utl_http.request(utl_url.escape(v_url, false,'ISO-8859-9'));
end;
end loop;
exception
when others then
prErrorMsgSend(v_mail_owner,'Error : ' || sqlerrm); -- a function like this one which sends an error message back to you.
end;
and create a scheduler job
begin
dbms_scheduler.create_job (
job_name => 'jbFileSend ',
job_type => 'STORED_PROCEDURE',
job_action => 'prFileSend',
start_date => '22-jan-2018 09:00:00 am',
repeat_interval => 'FREQ=DAILY; INTERVAL=1',
comments => 'Sending Every day'
enabled => true);
end;
working every day as an example.

Oracle 10g - Get list of tables from query i'm executing

I am working on internal tools of my organization, I have a automation need currently.
Example input query:
Select name,userid,url,address_line_1 from user join address on
user.user_id = address.user_id where userid = 'xxyy';
what I need is list of tables
user
address
Is there a built in way in Oracle 10G to get the list of tables from this query? Or Is there a python parser that can help me with the list of tables from the query?
Note: This is a basic example, my queries run in several lines and are more complex.
Interesting question.
You could build a little SQL analyzer in PL/SQL using DBMS_FGA. The idea would be:
Automatically modify the input SQL to also use a table with a FGA policy on it
In that FGA policy, you will have access to the current SQL (the first 32K of it, anyway. That's a limitation...)
Use the current SQL to build a throw-away view on the current SQL
Read the throw-away view's dependencies from USER_DEPENDENCIES
Drop the throw-away view.
Here is an example of how it would work:
(I apologize for putting my first name in all the objects; I share this database with others.)
-- Tester
BEGIN
matt_analysis_pkg.analyze_sql(p_sql =>
'WITH oel AS ( SELECT *
FROM oe_order_lines
WHERE ship_from_org_id = 88 )
SELECT oel.line_id, msi.segment1
FROM oel INNER JOIN mtl_system_items msi
ON msi.organization_id = 92 and msi.inventory_item_id = oel.inventory_item_id');
END;
/
Objects referenced by current SQL:
APPS.MTL_SYSTEM_ITEMS (SYNONYM)
APPS.OE_ORDER_LINES (SYNONYM)
The example (below) just reports the 1st level of dependencies. You could use DBA_DEPENDENCIES recursively to get more depth. Also, this version just writes to DBMS_OUTPUT.
As others have reported, just because a SQL depends on an object doesn't mean Oracle will actually access that object at run-time. Still, I think this is pretty close to what you were asking for.
Also, I noticed you tagged your question with Oracle 10g. I think the only thing in my solution that won't work in 10g is my direct access of a sequence. You'll have to replace that part with SELECT ... INTO to get the current sequence value.
Anyway, here is the source code for it (Oracle 12c):
-- This table doesn't do anything other than have a FGA policy on it.
CREATE TABLE matt_analysis_tab ( dummy varchar2(1) );
INSERT INTO matt_analysis_tab (dummy) VALUES ('X');
-- Sequence so we can create unique view names, in case two people analyze at the same time.
CREATE SEQUENCE matt_analysis_view_s;
-- Package to do the work.
CREATE OR REPLACE PACKAGE matt_analysis_pkg IS
PROCEDURE analyze_sql ( p_sql CLOB );
PROCEDURE analyze_current_sql (schema_name VARCHAR2, table_name VARCHAR2, policy_name VARCHAR2);
END matt_analysis_pkg;
/
CREATE OR REPLACE PACKAGE BODY matt_analysis_pkg AS
PROCEDURE analyze_sql (p_sql CLOB) IS
l_modified_sql CLOB := 'WITH v1$ AS ( SELECT /*+ MATERIALIZE */ dummy FROM matt_analysis_tab ) SELECT v1$.dummy, v2$.* FROM v1$, ( ' || p_sql || ') v2$';
BEGIN
DBMS_OUTPUT.PUT_LINE('l_modified_sql := ' || l_modified_sql);
EXECUTE IMMEDIATE l_modified_sql;
END analyze_sql;
PROCEDURE analyze_current_sql (schema_name VARCHAR2, table_name VARCHAR2, policy_name VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION;
l_sql CLOB;
l_column_count INTEGER;
l_view_name VARCHAR2(30);
l_view_columns VARCHAR2(4000);
BEGIN
l_sql := SYS_CONTEXT ('userenv', 'CURRENT_SQL',4000)
|| SYS_CONTEXT ('userenv', 'CURRENT_SQL1',4000)
|| SYS_CONTEXT ('userenv', 'CURRENT_SQL2',4000)
|| SYS_CONTEXT ('userenv', 'CURRENT_SQL3',4000)
|| SYS_CONTEXT ('userenv', 'CURRENT_SQL4',4000)
|| SYS_CONTEXT ('userenv', 'CURRENT_SQL5',4000)
|| SYS_CONTEXT ('userenv', 'CURRENT_SQL6',4000)
|| SYS_CONTEXT ('userenv', 'CURRENT_SQL7',4000)
;
DBMS_OUTPUT.put_line ('Current SQL: ' || l_sql);
DBMS_OUTPUT.put_line ('Current SQL length (calc): ' || length(l_sql));
DBMS_OUTPUT.put_line ('Current SQL length (userenv): ' || SYS_CONTEXT('userenv','CURRENT_SQL_LENGTH'));
-- Parse the SQL to get the column count
DECLARE
l_cursor INTEGER;
l_column_descriptions SYS.DBMS_SQL.desc_tab;
BEGIN
l_cursor := sys.DBMS_SQL.open_cursor;
-- parse SQL
sys.DBMS_SQL.parse (c => l_cursor, statement => l_sql, language_flag => sys.DBMS_SQL.native);
-- Describe columns
sys.DBMS_SQL.describe_columns (c => l_cursor, col_cnt => l_column_count, desc_t => l_column_descriptions);
sys.DBMS_SQL.close_cursor (l_cursor);
END;
DBMS_OUTPUT.PUT_LINE('Column count = ' || l_column_count);
-- Build view columns. We need to do this because the column names in the SQL are not necessarily unique.
SELECT listagg('C' || lpad(rownum,4,'0'),',') within group ( order by rownum )
INTO l_view_columns
FROM dual
CONNECT BY rownum <= l_column_count;
DBMS_OUTPUT.PUT_LINE('l_view_columns = ' || l_view_columns);
l_view_name := 'matt_analysis_view_' || lpad(matt_analysis_view_s.nextval,6,'0') || '$';
DBMS_OUTPUT.PUT_LINE('l_view_name = ' || l_view_name);
l_sql := 'CREATE OR REPLACE FORCE VIEW ' || l_view_name || ' (' || l_view_columns || ') AS ' || l_sql;
EXECUTE IMMEDIATE l_sql;
DBMS_OUTPUT.PUT_LINE('Objects referenced by current SQL: ');
FOR r IN ( select referenced_owner || '.' || referenced_name || ' (' || referenced_type || ')' reference_info
from user_dependencies where name = upper(l_view_name)
AND referenced_name not like 'MATT_ANALYSIS%' ) LOOP
DBMS_OUTPUT.PUT_LINE(r.reference_info);
END LOOP;
EXECUTE IMMEDIATE 'DROP VIEW ' || l_view_name;
COMMIT;
END analyze_current_sql;
END matt_analysis_pkg;
/
-- Create the FGA policy
BEGIN
DBMS_FGA.add_policy (
object_schema => NULL, -- My current schema
object_name => 'MATT_ANALYSIS_TAB',
policy_name => 'MATT_ANALYSIS_POLICY',
audit_condition => NULL,
audit_column => NULL,
handler_schema => NULL, -- My current schema
handler_module => 'matt_analysis_pkg.analyze_current_sql',
enable => TRUE);
END;
/
-- Script to drop the policy, just in case
--EXEC DBMS_FGA.drop_policy (NULL, 'MATT_ANALYSIS_TAB', 'MATT_ANALYSIS_POLICY');
I am still waiting for the solution, but, for now, I came up with a quick and dirty way to get the table names along with aliases using the following python.
from copy import deepcopy
import cx_Oracle
############################################################################
####################### Database connection instantiation###################
############################################################################
#connObj = pyodbc.connect(connString,autocommit=True)
qry = """
Select name,userid,url,address_line_1 from user join address on
user.user_id = address.user_id where userid = 'xxyy'
"""
def getConn():
connObj = cx_Oracle.connect('asap', 'sdfssa', cx_Oracle.makedsn('DBLDEV03', 1521, '23432'))
return connObj
def destroy(connObj):
connObj.commit()
connObj.close()
del connObj
##################### Logic ########################################
import datetime
def getTablesFromQuery(qry):
listTables = []
listAliases = []
connObj = getConn()
cursor = connObj.cursor()
listSpaceItems = qry.split(" ")
found =False
for spaceItem in listSpaceItems:
if spaceItem != '' and spaceItem!='\n':
spaceItem = spaceItem.replace("\n",'')
listCommaItems = spaceItem.split(",")
if found == True:
##### We are assuming that the next item is always alias, the sql query should follow that rule to
##### get the aliases properly.
listAliases.append(spaceItem)
found = False
for commaItem in listCommaItems:
if commaItem != '':
item = commaItem
if "." in commaItem:
item=commaItem.split(".")[1]
cursor.execute('select * from all_tables where table_name=\''+item.upper()+'\'')
res = cursor.fetchall()
if res is not None and res.__len__()>0:
listTables.append(commaItem)
found = True
destroy(connObj)
return listTables,listAliases
try:
listTables, listAliases = getTablesFromQuery(qry)
for item in listTables:
print(''+item)
except:
print('Exception..')
############################################################################
####################### close database connection###########################
############################################################################
You could create a package procedure to accept a SQL statement as input. What it would do is wrap the SQL in a CREATE VIEW and then analyze the dependencies of the resulting view.
Here is the source code.
CREATE OR REPLACE PACKAGE matt_analysis_pkg IS
PROCEDURE analyze_sql ( p_sql CLOB );
END matt_analysis_pkg;
/
CREATE OR REPLACE PACKAGE BODY matt_analysis_pkg AS
PROCEDURE analyze_sql (p_sql CLOB) IS
PRAGMA AUTONOMOUS_TRANSACTION;
l_sql CLOB;
l_column_count INTEGER;
l_view_name VARCHAR2(30);
l_view_columns VARCHAR2(4000);
BEGIN
DBMS_OUTPUT.put_line ('Current SQL: ' || p_sql);
-- Parse the SQL to get the column count
DECLARE
l_cursor INTEGER;
l_column_descriptions SYS.DBMS_SQL.desc_tab;
BEGIN
l_cursor := sys.DBMS_SQL.open_cursor;
-- parse SQL
sys.DBMS_SQL.parse (c => l_cursor, statement => p_sql, language_flag => sys.DBMS_SQL.native);
-- Describe columns
sys.DBMS_SQL.describe_columns (c => l_cursor, col_cnt => l_column_count, desc_t => l_column_descriptions);
sys.DBMS_SQL.close_cursor (l_cursor);
END;
DBMS_OUTPUT.PUT_LINE('Column count = ' || l_column_count);
-- Build view columns. We need to do this because the column names in the SQL are not necessarily unique.
SELECT listagg('C' || lpad(rownum,4,'0'),',') within group ( order by rownum )
INTO l_view_columns
FROM dual
CONNECT BY rownum <= l_column_count;
DBMS_OUTPUT.PUT_LINE('l_view_columns = ' || l_view_columns);
l_view_name := 'matt_analysis_view_' || lpad(matt_analysis_view_s.nextval,6,'0') || '$';
DBMS_OUTPUT.PUT_LINE('l_view_name = ' || l_view_name);
l_sql := 'CREATE OR REPLACE FORCE VIEW ' || l_view_name || ' (' || l_view_columns || ') AS ' || p_sql;
EXECUTE IMMEDIATE l_sql;
DBMS_OUTPUT.PUT_LINE('Objects referenced by current SQL: ');
FOR r IN ( select referenced_owner || '.' || referenced_name || ' (' || referenced_type || ')' reference_info
from user_dependencies where name = upper(l_view_name)
AND referenced_name not like 'MATT_ANALYSIS%' ) LOOP
DBMS_OUTPUT.PUT_LINE(r.reference_info);
END LOOP;
EXECUTE IMMEDIATE 'DROP VIEW ' || l_view_name;
COMMIT;
END analyze_sql;
END matt_analysis_pkg;
/
Tester
BEGIN
matt_analysis_pkg.analyze_sql(p_sql =>
'WITH oel AS ( SELECT *
FROM oe_order_lines
WHERE ship_from_org_id = 88 )
SELECT oel.line_id, msi.segment1
FROM oel INNER JOIN mtl_system_items msi
ON msi.organization_id = 92 and msi.inventory_item_id = oel.inventory_item_id');
END;
Objects referenced by current SQL:
APPS.MTL_SYSTEM_ITEMS (SYNONYM)
APPS.OE_ORDER_LINES (SYNONYM)

Oracle: Search an entire DB for a string: Error ORA-00911

I have created the PL/SQL stored procedure below to search an entire Oracle11g database for a string (srchstr) and return the table and column where that string was found to a table called VALUESEARCHRESULTS.
The procedure has ran successfully in Oracle XE via SQL Developer as a user. However, when try to run it as user SYS in Oracle11g for schema ABC, I receive the following error:
ORA-00911: invalid character
Cause: identifiers may not start with any ASCII character other than letters and numbers. $#_ are also allowed after the first character. Identifiers enclosed by double quotes may contain any character other than a double quote. Alternative quotes (q"#...#") cannot use spaces, tabs, or carriage returns as delimiters. For all other contexts, consult the SQL Language Reference Manual.
Does anyone know why this may be? Please see my code below.
CREATE OR REPLACE PROCEDURE ABC.FIND_STRING(p_str IN VARCHAR2) authid current_user is
l_query clob;
srchstr varchar2(30) := '';
r_cname varchar2(30) := '';
l_case clob;
l_runquery boolean;
l_tname varchar2(30);
l_cname varchar2(30);
begin
dbms_application_info.set_client_info( '%' || upper(p_str) || '%' );
for x in (select * from user_tables)
loop
l_query := 'select ''' || x.table_name || ''', $$
from ' || x.table_name || '
where rownum = 1 and ( 1=0 ';
l_case := 'case ';
l_runquery := FALSE;
for y in ( select *
from user_tab_columns
where table_name = x.table_name
and (data_type in('CHAR', 'DATE', 'FLOAT', 'NCHAR', 'NUMBER', 'NVARCHAR2', 'VARCHAR2' )
or data_type like 'INTERVAL%' or data_type like 'TIMESTAMP%' )
)
loop
l_runquery := TRUE;
l_query := l_query || ' or upper(' || y.column_name ||
') like userenv(''client_info'') ';
l_case := l_case || ' when upper(' || y.column_name ||
') like userenv(''client_info'') then ''' ||
y.column_name || '''';
end loop;
if ( l_runquery )
then
l_case := l_case || ' else NULL end';
l_query := replace( l_query, '$$', l_case ) || ')';
begin
execute immediate l_query into l_tname, l_cname;
r_cname := l_cname;
dbms_application_info.read_client_info(srchstr);
insert into ABC.ValueSearchResults (resulttable, resultcolumn, searchstring) values (x.table_name, r_cname, srchstr);
dbms_output.put_line
( srchstr || ' found in ' || l_tname || '.' || l_cname );
exception
when no_data_found then
dbms_output.put_line
( srchstr || ' has no hits in ' || x.table_name );
end;
end if;
end loop;
end;
EDIT: The stored procedure above compiles without error. The code below executes the stored procedure by passing values from a table into the stored procedure. The error shows when the code below is ran:
BEGIN
FOR c IN (SELECT ControlValue FROM ABC.ControlValues) LOOP
ABC.FIND_STRING(c.ControlValue);
END LOOP;
END;
I have found a resolution for the issue I initially raised.
Cause of error: Not specifying a schema; only grabbing user-specific tables.
While the stored procedure would execute when deployed as user ABC, the error generated when running the stored procedure as a user other ABC. It appeared the same table name existed in multiple schemas. Thus, adding an OWNER variable specified the schema associated with the table name and eliminated the error.
Additionally, the procedure was originally searching for USER_TABLES. This limited the results to only the tables of the current schema. By replacing USER_TABLES with DBA_TABLES, the stored procedure's search spanned through all tables of the database.
See below for the corrected code:
CREATE OR REPLACE
PROCEDURE FIND_STRING(
p_str IN VARCHAR2) authid current_user
IS
l_query CLOB;
srchstr VARCHAR2(100) := '';
r_cname VARCHAR2(100) := '';
l_case CLOB;
l_runquery BOOLEAN;
l_tname VARCHAR2(100);
l_cname VARCHAR2(100);
BEGIN
dbms_application_info.set_client_info( '%' || upper(p_str) || '%' );
FOR x IN
(SELECT *
FROM dba_tables
WHERE table_name <> 'CONTROLVALUES'
AND table_name <> 'VALUESEARCHRESULTS'
AND tablespace_name <> 'SYSTEM'
AND tablespace_name <> 'SYSAUX'
AND tablespace_name <> 'TEMP'
AND tablespace_name <> 'UNDOTBS1'
)
LOOP
l_query := 'select ''' || x.owner || '.' || x.table_name || ''', $$
from ' || x.owner || '.' || x.table_name || '
where rownum = 1 and ( 1=0 ';
l_case := 'case ';
l_runquery := FALSE;
FOR y IN
(SELECT *
FROM dba_tab_columns
WHERE table_name = x.table_name
AND owner = x.owner
AND (data_type IN ( 'CHAR', 'DATE', 'FLOAT', 'NCHAR', 'NUMBER', 'NVARCHAR2', 'VARCHAR2' )
OR data_type LIKE 'INTERVAL%'
OR data_type LIKE 'TIMESTAMP%' )
)
LOOP
l_runquery := TRUE;
l_query := l_query || ' or upper(' || y.column_name || ') like userenv (''client_info'') ';
l_case := l_case || ' when upper(' || y.column_name || ') like userenv (''client_info'') then ''' || y.column_name || '''';
END LOOP;
IF ( l_runquery ) THEN
l_case := l_case || ' else NULL end';
l_query := REPLACE( l_query, '$$', l_case ) || ')';
BEGIN
EXECUTE immediate l_query INTO l_tname, l_cname;
r_cname := l_cname;
dbms_application_info.read_client_info(srchstr);
INSERT
INTO VALUESEARCHRESULTS
(
resulttable,
resultcolumn,
searchstring
)
VALUES
(
x.table_name,
r_cname,
srchstr
);
dbms_output.put_line ( srchstr || ' found in ' || l_tname || '.' || l_cname );
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line ( srchstr || ' has no hits in ' || x.owner || '.' || x.table_name );
END;
END IF;
END LOOP;
END;

How to execute a procedure with DBMS_SCHEDULER.CREATE_JOB procedure

I want to create a job that would drop a database object at a given date. The job created all right but the procedure is not executed. Tried executing the procedure alone and it works.
Here's the code for the create job
v_jobnam := v_objnam;
v_jobnam := DBMS_SCHEDULER.generate_job_name (v_jobnam);
v_startdate := to_timestamp(v_startdate);
select sysdate + (v_delhrs/1440)
into v_startdate
from dual;
DBMS_SCHEDULER.CREATE_JOB(job_name => v_jobnam, job_type => 'PLSQL_BLOCK', JOB_ACTION => 'BEGIN DROP_OBJ1(' || v_objnam|| ', ' || v_objtyp || ', '|| v_schema || ',' || v_objid ||'); END;', start_date => SYSTIMESTAMP, repeat_interval => 'freq=secondly; bysecond=0', end_date => NULL, enabled => TRUE, comments => 'Calls PLSQL once');
where v_delhrs is a number.
Here's the code for the procedure:
PROCEDURE DROP_OBJ1
(
p_objnam IN CHAR,
p_objtyp IN CHAR,
p_copyto IN ALL_OBJECTS.OWNER%TYPE,
p_objid IN NUMBER
)
IS
v_objnam VARCHAR2 (30);
v_objtyp VARCHAR2 (30);
v_copyto VARCHAR2 (30);
v_objid NUMBER (3);
BEGIN
v_objnam := UPPER (p_objnam);
v_objtyp := UPPER (p_objtyp);
v_copyto := UPPER (p_copyto);
v_objid := p_objid;
--v_copyby := UPPER (p_copyby);
EXECUTE IMMEDIATE ( ' DROP '
|| v_objtyp
|| ' '
|| v_copyto
|| '.'
|| v_objnam
);
EXECUTE IMMEDIATE ( ' DELETE FROM COPY_OBJ_DET WHERE OBJ_ID = '
|| v_objid
);
COMMIT;
END;
I know its a very minor problem.
Thanks in advance gurus.
Cheers!
It apears to me that you have missed some quote marks in the DBMS_JOBS setup call.
Try this:
DBMS_SCHEDULER.CREATE_JOB(job_name => v_jobnam,
job_type => 'PLSQL_BLOCK',
JOB_ACTION => 'BEGIN DROP_OBJ1(''' || v_objnam
|| ''', ''' || v_objtyp || ''', '''
|| v_schema || ''',' || v_objid
|| '); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=secondly; bysecond=0',
end_date => NULL,
enabled => TRUE,
comments => 'Calls PLSQL once');
If this is not the solution I will setup your code on a database and try it myself.

why dbms_job.submit doesn't work while the same code work with execute immediate?

This is the frist time that I am going to use dbms_job.submit.
The following piece of code doesn't work:
declare
i_job_no BINARY_INTEGER;
begin
dbms_job.submit(JOB => i_job_no, what => 'declare x number; begin x := f_threads(''my_program'', '|| 6058883 ||' , '|| 2 || '); end;', next_date => sysdate);
dbms_output.put_line(i_job_no);
end;
but the same thing works fine with execute immediate. Can anyone help?!
> declare
i_job_no BINARY_INTEGER;
begin
execute immediate 'declare x number; begin x := f_threads(''my_program'', '|| 6058883 ||' , '|| 2 || '); end;';
end;
thanks!
in this way your pl/sql block will work:
declare
i_job_no BINARY_INTEGER;
begin
dbms_job.submit(JOB => i_job_no, what => 'declare x number; begin x := f_threads(''my_program'', '|| 6058883 ||' , '|| 2 || '); end;', next_date => sysdate);
dbms_output.put_line(i_job_no);
commit;
end;
You are missing a commit in you code
Regards
Giova
try this:
declare
i_job_no BINARY_INTEGER;
begin
dbms_job.submit(JOB => i_job_no, what => 'declare x number; begin x := f_threads(''my_program'', '|| 6058883 ||' , '|| 2 || '); end;', next_date => sysdate);
dbms_output.put_line(i_job_no);
commit;
dbms_job.run(i_job_no);
end;

Resources