I have a scheduler job which calls the procedure PR_DELETE_AUDIT_LOG. This code was working fine until the Oracle database was migrated to Exadata. Now whenever the job is executed we get the following errors as shown below.
ORA-29913: Error executing call
ORA-06512: in "ABC.PR_DELETE_AL_IMPORTLOG", AT LINE 49
ORA-06512: in "ABC.PR_DELETE_AL_IMPORTLOG", AT LINE 34
ORA-06512: in "ABC.PR_DELETE_AL_IMPORTLOG", AT LINE 34
The code for the job and the procedures are as follows.
DELETE_AL_IMPORTLOG_JOB
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'ABC.DELETE_AL_IMPORTLOG_JOB',
job_type => 'STORED_PROCEDURE',
job_action => 'ABC.PR_DELETE_AL_IMPORTLOG',
number_of_arguments => 0,
start_date => NULL,
repeat_interval => 'FREQ=DAILY;BYTIME=000000',
end_date => NULL,
enabled => FALSE,
auto_drop => FALSE,
comments => '');
DBMS_SCHEDULER.SET_ATTRIBUTE(
name => 'ABC.DELETE_AL_IMPORTLOG_JOB',
attribute => 'store_output', value => TRUE);
DBMS_SCHEDULER.SET_ATTRIBUTE(
name => 'ABC.DELETE_AL_IMPORTLOG_JOB',
attribute => 'logging_level', value => DBMS_SCHEDULER.LOGGING_OFF);
DBMS_SCHEDULER.enable(
name => 'ABC.DELETE_AL_IMPORTLOG_JOB');
END;
/
PR_DELETE_AL_IMPORTLOG
CREATE OR REPLACE EDITIONABLE PROCEDURE "ABC"."PR_DELETE_AL_IMPORTLOG"
AS
V_DELETION_DATE DATE;
CURSOR CUR_OLD_FILES
IS SELECT FNAME
FROM EXT_TAB_AL_IMPORTLOG_FILE_LIST
WHERE REGEXP_LIKE(FNAME,'AL_\d{2}-\d{2}-\d{2}_\d{8}_\d{6}.txt')
AND TO_DATE(SUBSTR(FNAME, -19,15),'YYYYMMDD_HH24MISS') < V_DELETION_DATE;
BEGIN
SELECT ADD_MONTHS
( TRUNC
( SYSDATE
, DECODE( STARTZEITPUNKTABF
, 1 ,'DD'
, 2 ,'MM'
, 3 ,'Q'
, 4 ,'YY'
,'DD'
)
)
, DECODE(PERIODEABF,2,-DAUERABF,3,-DAUERABF*12,0)) - DECODE(PERIODEABF,1,DAUERABF,0)
INTO V_DELETION_DATE
FROM LOESCHREGEL
WHERE VERWENDUNGSZWECK_ID = 'CLALL';
FOR REC_OLD_FILES IN CUR_OLD_FILES
LOOP
UTL_FILE.FREMOVE('ABC_AL_IMPORTLOG', REC_OLD_FILES.FNAME);
dbms_output.put_line('Deleted file '||REC_OLD_FILES.FNAME);
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DECLARE
V_PROCEDURE_NAME VARCHAR2(30) := $$PLSQL_UNIT;
V_SUBJECT VARCHAR2(255) := 'Error on DB procedure '||V_PROCEDURE_NAME||' on '||to_char(sysdate,'dd.mm.yyyy hh24:mi:ss');
V_BODY VARCHAR2(10000) := 'Hi all,'||chr(10)||chr(10)||'Procedure '||V_PROCEDURE_NAME||' returned the following error:'||chr(10)||SQLERRM;
BEGIN
SEND_MAIL ( 'GENERIC_DB_ERROR', V_SUBJECT,V_BODY);
RAISE;
END;
END PR_DELETE_AL_IMPORTLOG;
/
DDL for Table EXT_TAB_AL_IMPORTLOG_FILE_LIST
CREATE TABLE ABC.EXT_TAB_AL_IMPORTLOG_FILE_LIST
( FNAME VARCHAR2(255 CHAR )
)
ORGANIZATION EXTERNAL
( TYPE ORACLE_LOADER
DEFAULT DIRECTORY COLEIN_AUDITLOG
ACCESS PARAMETERS
( RECORDS DELIMITED BY NEWLINE
PREPROCESSOR COLEIN_PROCESS:'AL_ImportLog_list_files.sh'
noLOGFILE
nobadfile
nodiscardfile
FIELDS TERMINATED BY WHITESPACE
)
LOCATION
( 'lsOutput.log'
)
)
REJECT LIMIT UNLIMITED ;
where is the problem?
The error seems to come from a value of ext_tab_al_importlog_file_list.fname that doesn't match the expected filename format. You might want to check the values to see which one is invalid and how it got there.
If you are using Oracle 12.2 or later, change the cursor to use an on conversion error clause:
select fname
from ext_tab_al_importlog_file_list
where regexp_like(fname, 'AL_\d{2}-\d{2}-\d{2}_\d{8}_\d{6}.txt')
and to_date(substr(fname, -19, 15) default null on conversion error, 'YYYYMMDD_HH24MISS') < v_deletion_date;
If not, you could try adding some more filters:
select fname
from ext_tab_al_importlog_file_list
where regexp_like(fname, 'AL_\d{2}-\d{2}-\d{2}_\d{8}_\d{6}.txt')
and to_date(substr(fname, -19, 15), 'YYYYMMDD_HH24MISS') < v_deletion_date
and to_number(substr(fname,-10,2)) < 24
and to_number(substr(fname,-8,2)) < 60
and to_number(substr(fname,-6,2)) < 60;
This worked in my quick test, but combining filters with a conversion function is risky because there is no guarantee that Oracle will apply the filtering conditions in any particular order.
You can find the invalid values using either of the following:
select fname
from ext_tab_al_importlog_file_list
where regexp_like(fname, 'AL_\d{2}-\d{2}-\d{2}_\d{8}_\d{6}.txt')
and to_date(substr(fname, -19, 15) default null on conversion error, 'YYYYMMDD_HH24MISS') is null;
select fname
from ext_tab_al_importlog_file_list
where regexp_like(fname, 'AL_\d{2}-\d{2}-\d{2}_\d{8}_\d{6}.txt')
and ( to_number(substr(fname,-10,2)) >= 24
or to_number(substr(fname,-8,2)) >= 60
or to_number(substr(fname,-6,2)) >= 60 );
Related
The following tries to APPEND data to the CLASS table from a dmp that contains several hundred records for that table. There is 1 record already in database and that record also exists in the .dmp. The job completes but no data is appended.
If i switch the parameter to TRUNCATE, the single value is removed and replacedw ith the content of the .dmp i.e .works correctly.
Can anyone tell me what's wrong with this proc that's causing APPEND to fail?
The documentation doesn't seem to offer much beyond a reference to metadata (https://docs.oracle.com/database/121/ARPLS/d_datpmp.htm#ARPLS66059)... i have tried removing the metadata filter included in the code below, but with no +ve result.
Thanks
create or replace procedure import_backup (in_file_name in varchar2,
in_job_name in varchar2,
in_export_filename in varchar2)
is
l_dp_handle number;
l_status varchar2(200); -- Data Pump Status
l_file_name varchar2(100) := nvl(in_file_name,'IMPORTBACKUP');
l_job_name varchar2(100) := nvl(in_job_name,'IMPORTBACKUP20');
l_ipaddress VARCHAR2(20);
l_time VARCHAR2(20);
PROCEDURE_NAME VARCHAR2(30) := 'export_backup';
begin
select PARAM_VALUE
into l_ipaddress
from PARAMETER
where PARAM_NAME = 'DATABASE_SERVER';
select to_char(sysdate, 'YYYYMMDDHHMISS')
into l_time
from dual;
--Log_Message(PROCEDURE_NAME,'Starting with in_file_name: ' || l_file_name || ' and in_job_name: ' || l_job_name);
-- Open a table export job.
l_dp_handle := dbms_datapump.open(operation => 'IMPORT',
job_mode => 'TABLE',
remote_link => NULL,
job_name => l_job_name,
version => 'LATEST');
-- Specify the dump file name and directory object name.
dbms_datapump.add_file(handle => l_dp_handle,
filename => in_export_filename,
directory => 'EXPORT_DIR');
--Specify Truncate mode (to remove table contents and replace with file's contents
DBMS_DATAPUMP.SET_PARAMETER (
handle => l_dp_handle,
name => 'TABLE_EXISTS_ACTION',
value => 'APPEND' );
-- Specify the log file name and directory object name.
dbms_datapump.add_file(
handle => l_dp_handle,
filename => in_export_filename || l_time ||'expdp_XYZ.log',
directory => 'EXPORT_DIR',
filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE);
-- Specify the table to be imported, filtering the schema and table.
dbms_datapump.metadata_filter(handle => l_dp_handle,
name => 'NAME_EXPR',
value => 'IN (''CLASS'')',
object_type => 'TABLE');
-- Exclude table stats
dbms_datapump.metadata_filter(handle => l_dp_handle,
name => 'EXCLUDE_PATH_EXPR',
value => 'IN (''STATISTICS'')');
dbms_datapump.start_job(l_dp_handle);
-- Wait for job
dbms_datapump.wait_for_job(handle => l_dp_handle,job_state => l_status );
dbms_output.put_line( l_status );
--Log_Message(PROCEDURE_NAME,'Completed DataPump Job');
-- Job will continue running the background until it completes or errors
--dbms_datapump.detach(l_dp_handle);
exception
when others then
--Log_Message(PROCEDURE_NAME,'Datapump job failed');
begin
dbms_datapump.detach(l_dp_handle);
execute immediate 'Drop table ' ||l_job_name ;
end;
end import_backup;
Have attempted using 1 record in exiting table and using APPEND - no results
Have attemped using 1 record in exiting table and using using TRUNCATE - the 1 record is deleted and replaced with the content of the dmp's CLASS table
my goal is to run a select to a table and based on the certain rows dynamically create an audit trail or policy on them.
so..
create a set_policy function that gets called/Looped:
create or replace
function set_policy
( sch VARCHAR2 ,
tab VARCHAR2,
colm VARCHAR2,
pred VARCHAR2,
emailer VARCHAR2
)
return VARCHAR2 is
policy_sql_stmt varchar2(1000);
BEGIN
policy_sql_stmt :=
'BEGIN
SYS.DBMS_FGA.ADD_POLICY (
object_schema => :s,
object_name => :t,
policy_name => ''CHK_:s_:t'',
audit_column => :c,
audit_condition => :p,
handler_schema => ''SYSADMIN_FGA'',
handler_module => '''||emailer||'(:s,:t,''''CHK_:s_:t'''')'',
enable => TRUE,
statement_types => ''SELECT, UPDATE'',
audit_trail => SYS.DBMS_FGA.DB + SYS.DBMS_FGA.EXTENDED);
END;';
--DBMS_OUTPUT.PUT_LINE('policy_sql_stmt = :' || policy_sql_stmt);
BEGIN
EXECUTE IMMEDIATE policy_sql_stmt USING sch,tab,colm,pred;
--EXECUTE IMMEDIATE policy_sql_stmt USING pred;
EXCEPTION
WHEN OTHERS THEN
BEGIN
--dbms_output.put_line('set_policy error code: '||SQLCODE);
--dbms_output.put_line(DBMS_UTILITY.FORMAT_CALL_STACK);
RETURN ('set_policy error code: '||SQLCODE);
END;
END;
RETURN 'success';
END;
Then a procedure that calls the function...
CREATE OR REPLACE PROCEDURE audit_slac_tables
AS
--DECLARE
emailer VARCHAR2(40):='audit_email_alert';
isSuccess VARCHAR2(40);
CURSOR myCursor
IS
SELECT SCHEMA AS sch,
TABLE_NAME AS tab,
FILTER_COLUMN AS colm,
WHERE_COND AS pred
FROM SLAC_REDACTION_TABLE slac;
--WHERE slac.table_name IN ('RECIPIENT','CARD');
BEGIN
FOR curRec IN myCursor
LOOP
BEGIN
--emailer := getEmailer(curRec.sch ,curRec.tab);
isSuccess := set_policy(curRec.sch ,curRec.tab, curRec.colm, curRec.pred, emailer);
DBMS_OUTPUT.PUT_LINE('Proc isSuccess = :' || isSuccess);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Proc error code: '||SQLCODE);
dbms_output.put_line('Proc error msg: '||SQLERRM);
--dbms_output.put_line(DBMS_UTILITY.FORMAT_CALL_STACK);
--dbms_output.put_line('================================================');
CONTINUE;
END;
--dbms_output.put_line('================================================');
END LOOP;
COMMIT;
END audit_slac_tables;
if I call it...
exec AUDIT_SLAC_TABLES;
I get the following bewildering error
Error starting at line : 6 in command -
exec AUDIT_SLAC_TABLES
Error report -
ORA-06550: line 12, column 18:
PLS-00201: identifier 'SYS.DBMS_FGA' must be declared
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored
ORA-06512: at "GAPLITE.SET_POLICY", line 51
ORA-06512: at "GAPLITE.AUDIT_SLAC_TABLES", line 27
ORA-06512: at line 1
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Why a reference problem where the script DBMS_FGA.ADD_POLICY never had a problem?
I can run this script ( listed 1st above ) but not dynamically... it loses trhe contextual reference to the SYS packages somehow ??
can you please check this for me
this is not working
do we need special utl_mail
no idea what this utl_mail is
create or replace
procedure check_stock_qty
begin
for r ( select inv_qoh from inventory
where qty = 0 )
loop
UTL_MAIL.send(sender => 'na#yahoo.com',
recipients => 'krn9#mail.ca',
subject => 'Test Mail',
message => (r.inv_qoh),
mime_type => 'text; charset=us-ascii');
end loop;
end;
BEGIN
dbms_scheduler.create_job (
job_name => 'stock check',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN check_stock_qty; END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=minutely; interval=7200; bysecond=0;',
end_date => NULL,
enabled => TRUE,
END;
my error is
Error(2,1): PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: ( ; is with authid as cluster compress order using compiled wrapped external deterministic parallel_enable pipelined result_cache
The syntax for creating the procedure is
create or replace procedure <Name>
(<variable list>)
as (or is)
local variable declaration
begin
code section
exceptions
end;
here you missed the IS or AS Keyword before BEGIN
i tried with as
Error(5,8): PLS-00103: Encountered the symbol "(" when expecting one of the following: in The symbol "in" was substituted for "(" to continue.
Error(16,1): PLS-00103: Encountered the symbol "BEGIN"
Error(25,1): PLS-00103: Encountered the symbol "END" when expecting one of the following: ( - + case mod new not null continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date pipe
so much errors :(
ORACLE's dbms_redefinition.copy_table_dependents copies indexes/triggers/constraints and renames them to
TMP$$_[original object name]
Is it possible to change the string "TMP$$_" , so that copy_table_dependents uses a different prefix?
I know I can rename the objects afterwards, but I wonder whether one can change the prefix.
No, you can't change the object_name.
I don't think this matters much, as the TMP$$ objects are removed once you run DBMS_REDEFINITION.FINISH_REDEF_TABLE.
If you assume the following environment
create table test_redef_source ( id number, tstamp date, primary key (id) );
create or replace trigger tr_test_redef_sources
before insert on test_redef_source
for each row
begin
:new.tstamp := sysdate;
end;
/
create table test_redef_int as
select * from test_redef_source;
declare
l_errors number;
begin
dbms_redefinition.start_redef_table (
uname => user
, orig_table => 'TEST_REDEF_SOURCE'
, int_table => 'TEST_REDEF_INT'
);
dbms_redefinition.copy_table_dependents (
uname => user
, orig_table => 'TEST_REDEF_SOURCE'
, int_table => 'TEST_REDEF_INT'
, copy_indexes => 1
, num_errors => l_errors
);
end;
/
You can see by querying USER_DEPENDENCIES; that the TMP$$ objects are dependent on the interim table:
select name, type, referenced_name
from user_dependencies
where referenced_name like '%TEST_REDEF%'
;
NAME TYPE REFERENCED_NAME
------------------------------ ------------------ --------------------
TMP$$_TR_TEST_REDEF_SOURCES0 TRIGGER TEST_REDEF_INT
TR_TEST_REDEF_SOURCES TRIGGER TEST_REDEF_SOURCE
When you've completed the redefinition; these objects are removed:
begin
dbms_redefinition.finish_redef_table (
uname => user
, orig_table => 'TEST_REDEF_SOURCE'
, int_table => 'TEST_REDEF_INT'
);
end;
/
PL/SQL procedure successfully completed.
select name, type, referenced_name
from user_dependencies
where referenced_name like '%TEST_REDEF%'
;
NAME TYPE REFERENCED_NAME
------------------------------ ------------------ --------------------
TR_TEST_REDEF_SOURCES TRIGGER TEST_REDEF_SOURCE
As they're only temporary objects, and the names are guaranteed to be unique; I don't see any particular problem with maintaining the standard name.
I've trying to figure out oracle's DBMS_SCHEDULER (Oracle 11g) and need help setting up the following:
I have a procedure that calls a list of other procedures like this:
CREATE OR REPLACE
PROCEDURE RUN_JOBS AS
BEGIN
MYUSER.MYPROCEDURE1();
MYUSER.MYPROCEDURE2();
MYUSER.MYPROCEDURE3();
MYUSER.MYPROCEDURE4();
MYUSER.MYPROCEDURE5();
END;
/
I would like to use DBMS_SCHEDULER to run MYPROCEDURE3(), MYPROCEDURE4(), MYPROCEDURE5()
in parallel after the completion of MYPROCEDURE2().
Can someone show me an example on how to set this up?
You can refer to Chains under the DBMS_SCHEDULER package: http://docs.oracle.com/cd/B28359_01/server.111/b28310/scheduse009.htm
You can also achieve the same by going through Oracle Enterprise Manager, but I can't find any links to documentation right now.
You can do that using DBMS_SCHEDULER.
CREATE OR REPLACE PROCEDURE RUN_JOBS
AS
v_JobNum NUMBER := 1;
BEGIN
BEGIN
DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE1;',sysdate,'sysdate +1');
DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE2;',sysdate,'sysdate +1');
DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE3;',sysdate,'sysdate +1');
DBMS_JOB.SUBMIT(v_JobNum,'MYUSER.MYPROCEDURE4;',sysdate,'sysdate +1');
COMMIT;
END;
END RUN_JOBS;
/
This will submit the job and run them immediately.
create three different jobs for each procedure and schedule them at same time.
Here is my custom approach to parallellize work into N separate jobs retaining dbms_scheduler's logging and backpressure support. Date intervals are spread by mod N.
create table message_fixup_log (
source_date date not null,
started_at timestamp(6) not null,
finished_at timestamp(6),
fixed_message_count number(10)
);
alter table message_fixup_log add duration as (finished_at - started_at);
create unique index ix_message_fixup_log_date on message_fixup_log(source_date desc);
create or replace procedure message_fixup(jobNumber number, jobCount number, jobName varchar default null)
is
minSince date;
maxSince date;
since date;
msgUpdatedCount number;
begin
-- choose interval
select trunc(min(ts)) into minSince from message_part;
select trunc(max(ts))+1 into maxSince from message_part;
begin
select max(source_date) + jobCount into since from message_fixup_log
where finished_at is not null
and mod(source_date - minSince, jobCount) = jobNumber
and source_date >= minSince;
exception when no_data_found then null;
end;
if (since is null) then
since := minSince + jobNumber;
end if;
if (since >= maxSince) then
if (jobName is not null) then
dbms_scheduler.set_attribute(jobName, 'end_date', systimestamp + interval '1' second);
end if;
return;
end if;
insert into message_fixup_log(source_date, started_at) values(since, systimestamp);
-- perform some actual work for chosen interval
msgUpdatedCount := sql%rowcount;
update message_fixup_log
set fixed_message_count = msgUpdatedCount, finished_at = systimestamp
where source_date = since;
end;
-- manual test
--call message_fixup(0, 1);
declare
jobName varchar2(256);
jobCount number default 8;
begin
for jobNumber in 0..(jobCount-1) loop
jobName := 'message_fixup_job' || jobNumber;
begin
dbms_scheduler.drop_job(jobName, true);
exception
when others then null;
end;
dbms_scheduler.create_job(
job_name => jobName,
job_type => 'stored_procedure',
job_action => 'message_fixup',
enabled => false,
start_date => systimestamp,
repeat_interval => 'freq = minutely; interval = 1',
number_of_arguments => 3
);
dbms_scheduler.set_attribute(jobName, 'logging_level', dbms_scheduler.logging_full);
dbms_scheduler.set_job_anydata_value(jobName, 1, ANYDATA.ConvertNumber(jobNumber));
dbms_scheduler.set_job_anydata_value(jobName, 2, ANYDATA.ConvertNumber(jobCount));
dbms_scheduler.set_job_argument_value(jobName, 3, jobName);
dbms_scheduler.enable(jobName);
end loop;
end;