Sunday, November 20, 2011

Send EMAIL using UTL_MAIL in Oracle 10g

The UTL_MAIL package was introduced in Oracle 10g and it is easier to use when compared to UTL_SMTP. In order to use Oracle UTL_MAIL package you need to set a new init.ora parameter “SMTP_OUT_SERVER”, set to your outgoing mailserver.
Follow the simple steps to send an email using UTL_MAIL package
Step 1: Install UTL_MAIL package
To install the UTL_MAIL package, run the below files as user "SYS"
$ORACLE_HOME/rdbms/admin/utlmail.sql
$ORACLE_HOME/rdbms/admin/prvtmail.plb
Step 2: Grant permissions
Grants the execute permission on UTL_MAIL privilege to PUBLIC or the user which will use the package. Run the below command as user “SYS”
SQL> GRANT EXECUTE ON UTL_MAIL TO PUBLIC;
-or-
SQL> GRANT EXECUTE ON UTL_MAIL TO ;
Step 3: Set SMTP_OUT_SERVER parameter
SQL> ALTER SYSTEM SET smtp_out_server=’smtp.domain.com’ SCOPE=both;
Step 4: Create procedure to send email
CREATE OR REPLACE PROCEDURE test_email AS
BEGIN
UTL_MAIL.SEND(sender => 'xxx@ esscongroup.com',
recipients => 'xxx@ esscongroup.com',
cc => 'xxx@ esscongroup.com',
bcc => 'xxx@ esscongroup.com',
subject => 'Test Mail',
message => 'Hi, This is just a test mail');
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20001,'The following error has occured:' ||sqlerrm);
END;
SQL> exec test_email;
Step 5: Send email using UTL_MAIL with attachments
You must set UTL_FILE_DIR to a directory, where the attachment files exists
CREATE OR REPLACE PROCEDURE test_email_attach AS
BEGIN
UTL_MAIL.SEND_ATTACH_VARCHAR2(sender => 'xxx@ esscongroup.com',
recipients => 'xxx@ esscongroup.com',
cc => 'xxx@ esscongroup.com',
bcc => 'xxx@ esscongroup.com',
subject => 'Test Mail',
message => 'Hi, This is just a test mail'
attachment => ‘text’
att_filename => ‘test_attach.txt’);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20001,'The following error has occured: '
sqlerrm);
END;
Please note that with att_inline you can specify, whether the attachment is viewable inline with the message body or not.
You can also use the below parameters
attachment - A text attachment.
priority - The message priority, the default is NULL.
mime_type - The mime type of the message, default is ‘text/plain; charset=us-ascii‘.
att_inline - Specifies whether the attachment is viewable inline with the message body, default is TRUE.
att_mime_type - The mime type of the attachment, default is ‘text/plain; charset=us-ascii‘.
att_filename - The string specifying a filename containing the attachment, default is NULL.

Saturday, November 19, 2011

Restrict DDL Operations on a Schema in Oracle Database

In order to ensure schema consistency, DBAs may want to streamline who can issue Data Definition Language commands. Certain users are not permitted to make structural changes to object definitions, which implies no DDL operations can be performed by certain group of users. In that case DBA can achieve his goal simply by making a trigger on the schema.

For instance we want the user Nathan not to be able to perform any DDL. Then create trigger as below:

SQL> conn nathan/n
Connected.

SQL> create table before_trigger(a number);
Table created.

SQL>conn system/s
Connected.
SQL> CREATE OR REPLACE
2 TRIGGER BEFORE_DDL_Nathan
3 BEFORE DDL
4 ON Nathan.SCHEMA
5 BEGIN
6 RAISE_APPLICATION_ERROR(-30900,'DDL Operation is not Permitted.' );
7 END;
8 /

Trigger created.

SQL> conn nathan/n
Connected.

SQL> create table after_trigger(a number);
create table after_trigger(a number)
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-21000: error number argument to raise_application_error of -30900 is out of
range
ORA-06512: at line 2

Create Read only user for a Schema in Oracle

I will demonstrate the procedure with examples to setup a read only user for a schema in oracle database. In the example I will make chris user with read only permission on sam schema.
Let's start by creating SAM user.
SQL> CREATE USER SAM IDENTIFIED BY S;
User created.

SQL> GRANT DBA TO SAM;
Grant succeeded.

SQL> CONN SAM/S;
Connected.

SQL> CREATE TABLE SAM_TAB1 ( A NUMBER PRIMARY KEY, B NUMBER);
Table created.

SQL> INSERT INTO SAM_TAB1 VALUES(1,2);
1 row created.

SQL> CREATE TABLE SAM_TAB2(DATE_COL DATE);
Table created.

SQL> CREATE OR REPLACE TRIGGER SAM_TAB2_T AFTER INSERT ON SAM_TAB1
BEGIN
INSERT INTO SAM_TAB2 VALUES(SYSDATE);
END;
/
Trigger created.

SQL>CREATE VIEW A AS SELECT * FROM SAM_TAB2;
View created.


Method 1: Granting Privilege Manually

Step 1: Create Chris User
SQL> CREATE USER CHRIS IDENTIFIED BY C;
User created.

Step 2: Grant only select session and create synonym privilege to Chris user.
SQL> GRANT CREATE SESSION ,CREATE SYNONYM TO CHRIS;
Grant succeeded.

Step 3:Make script to grant select privilege.
$vi /oradata2/script.sql
SET PAGESIZE 0
SET LINESIZE 200
SET HEADING OFF
SET FEEDBACK OFF
SET ECHO OFF
SPOOL /oradata2/select_only_to_sam.sql
@@/oradata2/select_only_script.sql
SPOOL OFF

This script will run the /oradata2/select_only_script.sql and generate an output script /oradata2/select_only_to_sam.sql which will be rerun.

Step 4:
Prepare the /oradata2/select_only_script.sql script which will work as input for /oradata2/script.sql file.

$vi /oradata2/select_only_script.sql
SELECT 'GRANT SELECT ON SAM.' ||TABLE_NAME || ' TO CHRIS;' FROM DBA_TABLES WHERE OWNER='SAM';
SELECT 'GRANT SELECT ON SAM.' ||VIEW_NAME || ' TO CHRIS;' FROM DBA_VIEWS WHERE OWNER='SAM';


Step 5:
Now execute the /oradata2/script.sql which will generate scipt /oradata2/select_only_to_sam.sql.
SQL> @/oradata2/script.sql
GRANT SELECT ON SAM.SAM_TAB1 TO CHRIS;
GRANT SELECT ON SAM.SAM_TAB2 TO CHRIS;


Step 6:
Execute the output script select_only_to_sam.sql which will grant read only permission to chris user no sam's schema.
SQL> @/oradata2/select_only_to_sam.sql

Step 7:
Log on as chris user and create synonym that will access sam's table without any dot(.). Like to access sam_tab2 of sam schema he need to write sam.sam_tab2. But after creating synonym he simply can use sam_tab2 to access chris table and views.
To create synonym do the following,

SQL>CONN CHRIS/C;

SQL>host vi /oradata2/script_synonym.sql
SET PAGESIZE 0
SET LINESIZE 200
SET HEADING OFF
SET FEEDBACK OFF
SET ECHO OFF
SPOOL /oradata2/synonym_to_sam.sql
@@/oradata2/synonym_script.sql
SPOOL OFF


SQL>host vi /oradata2/synonym_script.sql
SELECT 'CREATE SYNONYM ' ||TABLE_NAME|| ' FOR SAM.' ||TABLE_NAME||';' FROM ALL_TABLES WHERE OWNER='SAM';
SELECT 'CREATE SYNONYM ' ||VIEW_NAME|| ' FOR SAM.' ||VIEW_NAME||';' FROM ALL_VIEWS WHERE OWNER='SAM';
SQL>@/oradata2/script_synonym.sql
SQL>@/oradata2/synonym_to_sam.sql

Step 8: At this stage you have completed your job. Log on as chris schema and see,
SQL> select * from sam_tab1;
1 2

SQL> show user
USER is "CHRIS"

Only select privilege is there. So DML will throw error. Like,

SQL> insert into sam_tab1 values(4,3);
insert into sam_tab1 values(4,3)
*
ERROR at line 1:
ORA-01031: insufficient privileges

Method 2: Writing PL/SQL Code
This is script for table :
set serveroutput on
DECLARE
sql_txt VARCHAR2(300);
CURSOR tables_cur IS
SELECT table_name FROM dba_tables where owner='SAM';
BEGIN
dbms_output.enable(10000000);
FOR tables IN tables_cur LOOP
sql_txt:='GRANT SELECT ON SAM.'||tables.table_name||' TO chris';
execute immediate sql_txt;
END LOOP;
END;
/


This is the script for grant select permission for views.
DECLARE
sql_txt VARCHAR2(300);
CURSOR tables_cur IS
SELECT view_name FROM dba_views where owner='SAM';
BEGIN dbms_output.enable(10000000);
FOR tables IN tables_cur LOOP
sql_txt:='GRANT SELECT ON SAM.'||tables.view_name||' TO chris';
--dbms_output.put_line(sql_txt);
execute immediate sql_txt;
END LOOP;
END;
/



To create synonym on sam schema,
Log on as chris and execute the following procedure.
SQL>CONN CHRIS/C
SQL>
DECLARE
sql_txt VARCHAR2(300);
CURSOR syn_cur IS
SELECT table_name name FROM all_tables where owner='SAM'
UNION SELECT VIEW_NAME name from all_views where owner='SAM' ;
BEGIN dbms_output.enable(10000000);
FOR syn IN syn_cur LOOP
sql_txt:='CREATE SYNONYM '||syn.name|| ' FOR SAM.'||syn.name ;
dbms_output.put_line(sql_txt);
execute immediate sql_txt;
END LOOP;
END;
/


Method 3: Writing a Trigger

After granting select permission in either of two ways above you can avoid creating synonym by simply creating a trigger.

Create a log on trigger that eventually set current_schema to sam just after log in CHRIS user.

create or replace trigger log_on_after_chris
after logon ON CHRIS.SCHEMA
BEGIN
EXECUTE IMMEDIATE 'alter session set CURRENT_SCHEMA = sam';
END;
/

Saturday, November 27, 2010

Purging trace and dump files with Oracle 11g ADRCI

Oracle 11g uses the ADR (Automatic Diagnostic Repository) utility which is defined by the diagnostic_dest parameter. To access ADR, execute adrci from the UNIX prompt. We no longer have to manually remove trace files and core dumps, this is now all done automatically. How?
The MMON background process does it automatically based on a control date established for each database instance..
There are two time attributes which are used to manage the retention of information in ADR (in hours):
LONGP_POLICY (long term) defaults to 365 (8760 hours) days and relates to things like Incidents and Health Monitor warnings.
SHORTP_POLICY (short term) defaults to 30 (720 hours) days and relates to things like trace and core dump files
Log in to adrci. You must set the homepath to the Oracle database instances diag directory first before making changes. For example:
adrci
ADRCI: Release 11.2.0.1.0 - Production on Wed Oct 13 10:45:33 2010

Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
ADR base = "/u01/app/oracle"
adrci> show homepath
diag/rdbms/db11d/DB11D
diag/rdbms/dbua0/DBUA0
diag/clients/user_oracle/host_1240304075_11
diag/clients/user_unknown/host_411310321_11
diag/tnslsnr/panacea/listener
diag/tnslsnr/panacea/listener_db11d
adrci> set homepath diag/rdbms/DB11D
adrci> show control
ADR Home = /u01/app/oracle/diag/rdbms/DB11D/db11d:
*************************************************************************
ADRID SHORTP_POLICY LONGP_POLICY LAST_MOD_TIME LAST_AUTOPRG_TIME LAST_MANUPRG_TIME ADRDIR_VERSION ADRSCHM_VERSION ADRSCHMV_SUMMARY ADRALERT_VERSION CREATE_TIME
-------------------- -------------------- -------------------- ---------------------------------------- ---------------------------------------- ---------------------------------------- -------------------- -------------------- -------------------- -------------------- ----------------------------------------
3085591152 720 8760 2010-10-13 07:45:05.954963 -04:00 2010-10-06 19:24:19.114301 -04:00 1 2 76 1 2010-09-21 09:01:57.306537 -04:00
1 rows fetched
adrci> set control (SHORTP_POLICY =360)
adrci> set control (LONGP_POLICY=4380)
This will reduce the short term to 15 days and the long term to 180 days. MMON will automatically delete the designated files by the dates specified. You no longer have to monitor this space!