I can't seem to create the table inside this procedure. I read it online that for any DDL, I need to use EXECUTE IMMEDIATE and tried following few examples online. However, even after trying several solutions it keeps failing. '
Error ""ORA-00904: "End": invalid identifier ORA-06512: at
"EXTRACT_AUTOMATED_CHECKS", line 89 "
CREATE OR REPLACE PROCEDURE EXTRACT_AUTOMATED_CHECKS AS
BEGIN
--DROP TABLE
BEGIN
EXECUTE IMMEDIATE ('DROP TABLE extract_checks') ;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
--CREATE TABLE, INDEX
--TABLE
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE extract_checks
(
Card number(19) NOT NULL PRIMARY KEY
,Customer_Id number(19)
)';
COMMIT;
END;
--INDEX
BEGIN
EXECUTE IMMEDIATE('CREATE INDEX IDX_EXT_CHECKS extract_checks(Customer_Id)');
COMMIT;
END;
SOURCE.DBA_SEND_MAIL(
V_FROM=>'Notification#Company.com;',
V_RECIPIENT => 'employee#company.com',
V_SUBJECT => 'Automated Checks Completed',
V_MESSAGE => 'Automated Checks Completed' );
EXCEPTION WHEN OTHERS THEN
SOURCE.DBA_SEND_MAIL(
V_FROM=>'Notification#Company.com;',
V_RECIPIENT => 'employee#company.com',
V_SUBJECT => 'Automated Checks Failed',
V_MESSAGE => 'Automated Checks Failed' );
RAISE;
END EXTRACT_AUTOMATED_CHECKS;
There is no issue with CREATE TABLE.
you missed ; at the end of last call to send mail in exception block.
SOURCE.DBA_SEND_MAIL(
V_FROM=>'Notification#Company.com;',
V_RECIPIENT => 'employee#company.com',
V_SUBJECT => 'Automated PX Checks Failed',
V_MESSAGE => 'Automated PX Checks Failed' ); <<-- this ; is missing
Cheers!!
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
Is there a way to make Oracle Apex send emails for any error that occur for application error?
So it will be easier to know if there is a error when other users encounter it
I can't imagine a situation where I'd like to get an email every time a user gets any error at all - but if that's what you'd really like then you can do this with a custom error handling function.
Create a function like this (note: it must have exactly these parameters):
(example based on:
http://docs.oracle.com/cd/E59726_01/doc.50/e39149/apex_error.htm#AEAPI2217)
create or replace function apex_error_handling_example (
p_error in apex_error.t_error )
return apex_error.t_error_result
is
l_result apex_error.t_error_result;
l_reference_id number;
l_constraint_name varchar2(255);
begin
l_result := apex_error.init_error_result (
p_error => p_error );
apex_mail.send(
p_to => 'some_user#somewhere.com', -- change to your email address
p_from => 'some_sender#somewhere.com', -- change to a real senders email address
p_body => 'Apex Error '
||' message: ' || p_error.message
||' additional_info: ' || p_error.additional_info
||' page_item_name: ' || p_error.page_item_name
||' region_id: ' || p_error.region_id
||' column_alias: ' || p_error.column_alias
||' row_num: ' || p_error.row_num
||' apex_error_code: ' || p_error.apex_error_code
||' ora_sqlcode: ' || p_error.ora_sqlcode
||' ora_sqlerrm: ' || p_error.ora_sqlerrm
||' error_backtrace: ' || p_error.error_backtrace
||' error_statement: ' || p_error.error_statement
||' component.type: ' || p_error.component.type
||' component.id: ' || p_error.component.id
||' component.name: ' || p_error.component.name,
p_subj => 'Apex Error Report');
-- If it's an internal error raised by APEX, like an invalid statement or
-- code which cannot be executed, the error text might contain security sensitive
-- information. To avoid this security problem rewrite the error to
-- a generic error message and log the original error message for further
-- investigation by the help desk.
if p_error.is_internal_error then
-- mask all errors that are not common runtime errors (Access Denied
-- errors raised by application / page authorization and all errors
-- regarding session and session state)
if not p_error.is_common_runtime_error then
-- log error for example with an autonomous transaction and return
-- l_reference_id as reference#
-- l_reference_id := log_error (
-- p_error => p_error );
--
-- Change the message to the generic error message which doesn't expose
-- any sensitive information.
l_result.message := 'An unexpected internal application error has occurred. '||
'Please get in contact with XXX and provide '||
'reference# '||to_char(l_reference_id, '999G999G999G990')||
' for further investigation.';
l_result.additional_info := null;
end if;
else
-- Always show the error as inline error
-- Note: If you have created manual tabular forms (using the package
-- apex_item/htmldb_item in the SQL statement) you should still
-- use "On error page" on that pages to avoid loosing entered data
l_result.display_location := case
when l_result.display_location = apex_error.c_on_error_page then apex_error.c_inline_in_notification
else l_result.display_location
end;
-- If it's a constraint violation like
--
-- -) ORA-00001: unique constraint violated
-- -) ORA-02091: transaction rolled back (-> can hide a deferred constraint)
-- -) ORA-02290: check constraint violated
-- -) ORA-02291: integrity constraint violated - parent key not found
-- -) ORA-02292: integrity constraint violated - child record found
--
-- try to get a friendly error message from our constraint lookup configuration.
-- If the constraint in our lookup table is not found, fallback to
-- the original ORA error message.
if p_error.ora_sqlcode in (-1, -2091, -2290, -2291, -2292) then
l_constraint_name := apex_error.extract_constraint_name (
p_error => p_error );
begin
select message
into l_result.message
from constraint_lookup
where constraint_name = l_constraint_name;
exception when no_data_found then null; -- not every constraint has to be in our lookup table
end;
end if;
-- If an ORA error has been raised, for example a raise_application_error(-20xxx, '...')
-- in a table trigger or in a PL/SQL package called by a process and the
-- error has not been found in the lookup table, then display
-- the actual error text and not the full error stack with all the ORA error numbers.
if p_error.ora_sqlcode is not null and l_result.message = p_error.message then
l_result.message := apex_error.get_first_ora_error_text (
p_error => p_error );
end if;
-- If no associated page item/tabular form column has been set, use
-- apex_error.auto_set_associated_item to automatically guess the affected
-- error field by examine the ORA error for constraint names or column names.
if l_result.page_item_name is null and l_result.column_alias is null then
apex_error.auto_set_associated_item (
p_error => p_error,
p_error_result => l_result );
end if;
end if;
return l_result;
end apex_error_handling_example;
In Apex, set the Application Definition attribute Error Handling Function to the name of the function, e.g. apex_error_handling_example.
Side note: it's good practice to put this function in a package instead of using a schema-level function.
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 ??
We are planning to install the UTL_MAIL Package and we're currently testing the installation steps in our Development Environment.
After sucessfully installing the UTL_MAIL Package Scripts and creating the sufficient PUBLIC Synonyms and Grants,
we are getting the error ORA-29278 when running the test Anonymous Block below:
BEGIN
UTL_MAIL.SEND(sender => 'xxx#oracle.com'
, recipients => 'Migs.Isip.23#gmail.com'
, subject => 'Testmail'
, message => 'Hello');
END;
Full Details of the error Message:
ORA-29278: SMTP transient error: 421 4.3.2 Service not available
ORA-06512: at "SYS.UTL_MAIL", line 662
ORA-06512: at "SYS.UTL_MAIL", line 679
ORA-06512: at line 3
29278. 00000 - "SMTP transient error: %s"
*Cause: A SMTP transient error occurred.
*Action: Correct the error and retry the SMTP operation.
As per research from related links (Send Email Using PLSQL),
i may need to setup the proper access control list (ACL) for this to work. However, upon executing the script below, i'm still getting the same error.
DECLARE
-- ACL name to be used for email access reuse the same value for all
-- future calls
l_acl VARCHAR2 (30) := 'utl_smtp.xml';
-- Oracle user to be given permission to send email
l_principal VARCHAR2 (30) := 'APPS';
-- Name of email server
g_mailhost VARCHAR2 (60) := 'smtprelay.xxxxx.com';
l_cnt INTEGER;
PROCEDURE validate_smtp_server
AS
l_value v$parameter.VALUE%TYPE;
l_parameter v$parameter.name%TYPE := 'smtp_out_server';
BEGIN
SELECT VALUE
INTO l_value
FROM v$parameter
WHERE name = l_parameter;
IF l_value IS NULL
THEN
raise_application_error (
-20001
, 'Oracle parameter '
|| l_parameter
|| ' has not been set'
|| UTL_TCP.crlf
|| 'it s/b smtprelay.alorica.com'
);
END IF;
DBMS_OUTPUT.put_line ('parameter ' || l_parameter || ' value is ' || l_value);
END validate_smtp_server;
PROCEDURE create_if_needed (p_acl IN VARCHAR2)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acls a
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl;
IF l_cnt = 0
THEN
DBMS_OUTPUT.put_line ('creating acl ' || p_acl);
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => p_acl
, description => 'Allow use of utl_smtp'
, principal => l_principal
, is_grant => TRUE
, privilege => 'connect'
);
DBMS_NETWORK_ACL_ADMIN.assign_acl (acl => p_acl, HOST => g_mailhost);
COMMIT;
ELSE
DBMS_OUTPUT.put_line (p_acl || ' acl already exists');
END IF;
END create_if_needed;
PROCEDURE add_if_needed (
p_principal IN VARCHAR2
, p_acl IN VARCHAR2
)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acl_privileges
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl
AND principal = p_principal;
IF l_cnt = 0
THEN
DBMS_NETWORK_ACL_ADMIN.add_privilege (
acl => 'utl_smtp.xml'
, principal => p_principal
, is_grant => TRUE
, privilege => 'connect'
);
COMMIT;
DBMS_OUTPUT.put_line ('access to ' || p_acl || ' added for ' || p_principal);
ELSE
DBMS_OUTPUT.put_line (p_principal || ' already has access to ' || p_acl);
END IF;
END add_if_needed;
BEGIN
EXECUTE IMMEDIATE 'grant execute on utl_mail to ' || l_principal;
create_if_needed (p_acl => l_acl);
add_if_needed (p_principal => l_principal, p_acl => l_acl);
DBMS_OUTPUT.put_line ('Verification SQL:');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acls;');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acl_privileges;');
COMMIT;
validate_smtp_server;
END;
What other steps can i take or what other instructions do i need to provide to the DBAs for this?
Oracle Database Version:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
"CORE 11.2.0.4.0 Production"
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
Thank you very much.
I was able to resolve this by contacting our System Administrator and asking for the details of the Mail Server.
Turns out, if we'll only be sending the email internally, we are advised to use a different server mail.xxx.xxx.xxxx since its not going to be blocked by the firewall.
On the other hand, if we'll be sending email externally, another server is involved smtprelay.xxxxx.com
and this involves an extra step of Whitelisting the External Servers to be sent to.
As i checked in V$PARAMETER, we were using the smtprelay.xxxxx.com server and decided to try the other server mail.xxx.xxx.xxxx.
I issued the Alter command as below:
alter system set smtp_out_server = 'mail.xxx.xxx.xxxx';
and ran the anonymous block and was able to recieve the email successfully.
BEGIN
UTL_MAIL.SEND(sender => 'xxx#oracle.com'
, recipients => 'Migs.Isip.23#gmail.com'
, subject => 'Testmail'
, message => 'Hello');
END;
I came up with SMTP email challenges for 19c database. I was able to solve it. Below is the complete solution:-
Give grant to corresponding schema name for utl_tcp,utl_smtp and utl_http.
grant execute on utl_tcp to schemaname;
grant execute on utl_smtp to schemaname;
grant execute on utl_http to schemaname;
CREATE_ACL using DBMS_NETWORK_ACL_ADMIN sys package:-
BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
acl => '/sys/acls/utl_http.xml',
description => 'Allowing SMTP Connection',
principal => 'SCHEMANAME',
is_grant => TRUE,
privilege => 'connect',
start_date => SYSTIMESTAMP,
end_date => NULL);
COMMIT;
END;
/
ADD_PRIVILEGE to schema using DBMS_NETWORK_ACL_ADMIN package:-
BEGIN
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(
acl => '/sys/acls/utl_http.xml',
principal => 'SCHEMANAME',
is_grant => true,
privilege => 'resolve');
COMMIT;
END;
/
ASSIGN_ACL to mail server using DBMS_NETWORK_ACL_ADMIN package:-
BEGIN
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL (
acl => '/sys/acls/utl_http.xml',
host => 'mailhostname');
COMMIT;
END;
/
when I try the following code, I get a procedure completed with 0 compilation errors.. message instead of procedure successfully completed message.
what's wrong with this? and help me in correcting this error
CREATE OR REPLACE PROCEDURE omar_manager_report1 (
pi_co_id IN VARCHAR2, -- Company ID
pi_cntr_nbr IN NUMBER DEFAULT 0,
-- if Contract number is passed then Case 1: will be executed
pi_overdue_days IN NUMBER DEFAULT 0,
--No of days related to Over due of application passed.
po_var_ref OUT sys_refcursor
)
IS
lv_query VARCHAR2(400) ;
lv_co_id VARCHAR2 (200);
BEGIN
lv_co_id := REPLACE (pi_co_id, ',', ''',''');
--Default option for all group office
lv_query :=
'select distinct gue.co_id,
(SELECT event_descp FROM get_event WHERE co_id = gue.co_id AND event_cd = gue.event_cd) AS event_desc
FROM get_uwtg_event gue';
DBMS_OUTPUT.put_line ('lv_query');
OPEN po_var_ref FOR lv_query;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLCODE);
END;
/
Executing a CREATE OR REPLACE PROCEDURE... statement compiles the procedure, but it does not call the procedure. You'll need to write a PL/SQL block similar to the following to invoke your procedure:
DECLARE
csrOut SYS_REFCURSOR;
BEGIN
omar_manager_report1(pi_co_id => '123456',
pi_cntr_nbr => 0,
pi_overdue_days => 0,
po_var_ref => csrOut);
-- Add code here to fetch from csrOut and use the results appropriately
-- Close the cursor opened by omar_manager_report1
CLOSE csrOut;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Exception: ' || SQLCODE || ' : ' || SQLERRM);
END;
Best of luck.