Sunteți pe pagina 1din 39

pl/pdf examples

http://www.plpdf.com/23-926.html
http://plnet.org/
http://orafaq.com/cgi-bin/sqlformat/pp/utilities/sqlformatter.tpl //gr8 site
_____________
begin
execute immediate 'garbage';
exception
when others then
dbms_output.put_line( 'error msg is'||sqlcode);
dbms_output.put_line( 'error code is '||sqlerrm );
dbms_output.put_line( 'new code is '||dbms_utility.format_error_backtrace );
dbms_output.put_line ( 'type of statement executed: '
|| dbms_sql.last_sql_function_code ( )
);

raise;
end;
/
--------

how can one search pl/sql code for a string/ key value?
select type, name, line
from user_source
where upper(text) like '%&keyword%';

__________
how can one search pl/sql code for a string/ key value?
select object_name,
to_char(created, 'dd-mon-rr hh24:mi') create_time,
to_char(last_ddl_time, 'dd-mon-rr hh24:mi') mod_time,
status
from user_objects
where last_ddl_time > '&check_from_date';
___________
set serveroutput on size 200000
-------
is there a limit on the size of a pl/sql block?
yes, the max size is not an explicit byte limit, but related to the parse tree
that is created when you compile the code. you can run the following select
statement to query the size of an existing package or procedure:
select * from dba_object_size where name = 'procedure_name';
----------
sql and pl/sql formatter site
http://orafaq.com/cgi-bin/sqlformat/pp/utilities/sqlformatter.tpl
----------
rem -----------------------------------------------------------------------
rem filename: encode.sql
rem purpose: demonstrate simple encoding and decoding of secret messages
rem this method can be extended to create simple password
rem encryption
rem date: 15-feb-2001
rem author: frank naude, oracle faq
rem -----------------------------------------------------------------------

select translate(
'hello world', -- message to encode
'abcdefghijklmnopqrstuvwxyz ',
'1234567890!@#$%^&*()-=_+;,.') encoded_message
from dual
/

select translate(
'85@@%._%*@4', -- message to decode
'1234567890!@#$%^&*()-=_+;,.',
'abcdefghijklmnopqrstuvwxyz ') decoded_message
from dual
/
--------------------
rem -----------------------------------------------------------------------
rem filename: password.sql
rem purpose: simple password encryption package to demonstrate how
rem values can be encrypted and decrypted using oracle's
rem dbms obfuscation toolkit
rem note: connect to sys as sysdba and run ?/rdbms/admin/catobtk.sql
rem date: 18-mar-2003
rem author: frank naude, oracle faq
rem -----------------------------------------------------------------------

create or replace package password as


function encrypt(i_password varchar2) return varchar2;
function decrypt(i_password varchar2) return varchar2;
end password;
/
show errors

create or replace package body password as

-- key must be exactly 8 bytes long


c_encrypt_key varchar2(8) := 'key45678';

function encrypt (i_password varchar2) return varchar2 is


v_encrypted_val varchar2(38);
v_data varchar2(38);
begin
-- input data must have a length divisible by eight
v_data := rpad(i_password,(trunc(length(i_password)/8)+1)*8,chr(0));

dbms_obfuscation_toolkit.desencrypt(
input_string => v_data,
key_string => c_encrypt_key,
encrypted_string => v_encrypted_val);
return v_encrypted_val;
end encrypt;

function decrypt (i_password varchar2) return varchar2 is


v_decrypted_val varchar2(38);
begin
dbms_obfuscation_toolkit.desdecrypt(
input_string => i_password,
key_string => c_encrypt_key,
decrypted_string => v_decrypted_val);
return v_decrypted_val;
end decrypt;

end password;
/
show errors

-- test if it is working...
select password.encrypt('password1') from dual;
select password.decrypt(app_password.encrypt('password1')) from dual;
select password.encrypt('psw2') from dual;
select password.decrypt(app_password.encrypt('psw2')) from dual;

------------------
/*
------------------------------------------------------------------------------
filename: random.txt
purpose: random number/ string generator package
author: unknown
original: http://orafaq.net/scripts/sql/random.txt
edits:
19990908 phil rand <prand@spu.edu> added functions rand_string(), smaller().
------------------------------------------------------------------------------
*/

create or replace package random


is
procedure srand(new_seed in number);
procedure get_rand(r out number);
procedure get_rand_max(r out number, n in number);
function rand return number;
function rand_max(n in number) return number;
function rand_string(ssiz in number) return varchar2;
function smaller(x in number, y in number) return number;
pragma restrict_references(rand, wnds);
pragma restrict_references(rand_max, wnds);
pragma restrict_references(random, wnds, rnps);
pragma restrict_references(rand_string, wnds);
pragma restrict_references(smaller, wnds);
end random;
/

create or replace package body random


is
multiplier constant number := 22695477;
increment constant number := 1;
"2^32" constant number := 2 ** 32;
"2^16" constant number := 2 ** 16;
"0x7fff" constant number := 32767;
seed number := 1;

function smaller(x in number, y in number) return number is


begin
if x <= y then
return x;
else
return y;
end if;
end smaller;

function rand_string(ssiz in number) return varchar2 is


i number;
m number;
c char;
result varchar2(2000) := '';
begin
m := smaller(ssiz,2000);
for i in 1..m loop
c := substr('abcdefghijklmnopqrstuvwxyz0123456789',rand_max(36),1);
result := result || c;
end loop;
return result;
end rand_string;

procedure srand(new_seed in number) is


begin
seed := new_seed;
end srand;

function rand return number is


begin
seed := mod(multiplier * seed + increment, "2^32");
return bitand(seed/"2^16", "0x7fff");
end rand;

procedure get_rand(r out number) is


begin
r := rand;
end get_rand;

function rand_max(n in number) return number is


begin
return mod(rand, n) + 1;
end rand_max;

procedure get_rand_max(r out number, n in number) is


begin
r := rand_max(n);
end get_rand_max;

begin
select userenv('sessionid')
into seed
from dual;
end random;
/

-- some examples:
select random.rand_max(10) from dual;
select random.rand_max(10) from dual;
select random.rand_string(20) from dual;
select random.rand_string(20) from dual;

------------
rem -----------------------------------------------------------------------
rem filename: leapyear.sql
rem purpose: check if a year is a leap year
rem author: frank naude, oracle faq
rem -----------------------------------------------------------------------

create or replace function isleapyear(i_year number) return boolean as


begin
-- a year is a leap year if it is evenly divisible by 4
-- but not if it's evenly divisible by 100
-- unless it's also evenly divisible by 400

if mod(i_year, 400) = 0 or ( mod(i_year, 4) = 0 and mod(i_year, 100) != 0) then


return true;
else
return false;
end if;
end;
/
show errors

-- let's test it
set serveroutput on
begin
if isleapyear(2004) then
dbms_output.put_line('yes, it is a leap year');
else
dbms_output.put_line('no, it is not a leap year');
end if;
end;
/

-----------
rem -----------------------------------------------------------------------
rem filename: ftpclient.sql
rem purpose: pl/sql ftp client
rem date: 19-nov-2003
rem author: russ johnson, braun consulting
rem -----------------------------------------------------------------------

create or replace package brnc_ftp_pkg


as
/**
*
* pl/sql ftp client
*
* created by: russ johnson, braun consulting
*
* www.braunconsult.com
*
* overview
* --------------------
* this package uses the standard packages utl_file and utl_tcp to perform
* client-side ftp functionality (put and get) for text files as defined in
* the world wide web consortium's rfc 959 document -
http://www.w3.org/protocols/rfc959/
* the procedures and functions in this package allow single or multiple file
transfer using
* standard tcp/ip connections.
*
* limitations
* --------------------
* currently the api is limited to transfer of ascii text files only. this
is
* primarily because utl_file only supports text i/o, but also because the
original
* design was for creating text files from data in the oracle database, then
transferring the file to a remote host.
* furthermore, the api does not support ssh/secure ftp or connection through
a proxy server.
* keep in mind that ftp passes the username/password combo in plain text
over tcp/ip.
*
* db versions - 8i (8.1.x) and above. 8.0.x may work if it has the
sys.utl_tcp package.
*
*
* note: since utl_file is used for the client-side i/o, this package is also
limited to
* transfer of files that exist in directories available to utl_file
for read/write.
* these directories are defined by the utl_file_dir parameter in the
init.ora file.
*
* usage
* --------------------

* three functions are available for ftp - put, get, and ftp_multiple.
ftp_multiple takes
* a table of records that define the files to be transferred (filename,
directory, etc.).
* that table can have 1 record or multiple records. the put and get
functions are included
* for convenience to ftp one file at a time. put and get return true if the
file is transferred
* successfully and false if it fails. ftp_multiple returns true if no
batch-level errors occur
* (such as an invalid host, refused connection, or invalid login
information). it also takes the
* table of file records in and passes it back out. each record contains
individual error information.
*
* example
* --------------------
* transfer multiple files - 1 get and 2 put from a windows machine to a host
(assuming unix here).
* display any errors that occur.
* declare
*
* v_username varchar2(40) := 'rjohnson';
* v_password varchar2(40) := 'password';
* v_hostname varchar2(255) := 'ftp.oracle.com';
* v_error_message varchar2(1000);
* b_put boolean;
* t_files brnc_ftp_pkg.t_ftp_rec; -- declare our table of
file records
*
* begin
*
* t_files(1).localpath := 'd:\oracle\utl_file\outbound';
* t_files(1).filename := 'myfile1.txt';
* t_files(1).remotepath := '/home/oracle/text_files';
* t_files(1).transfer_mode := 'put';
*
* t_files(2).localpath := 'd:\oracle\utl_file\inbound';
* t_files(2).filename := 'incoming_file.xml';
* t_files(2).remotepath := '/home/oracle/xml_files';
* t_files(2).transfer_mode := 'get';
*
* t_files(3).localpath := 'd:\oracle\utl_file\outbound';
* t_files(3).filename := 'myfile2.txt';
* t_files(3).remotepath := '/home';
* t_files(3).transfer_mode := 'put';
*
* b_put := brnc_ftp_pkg.ftp_multiple(v_error_message,
* t_files,
* v_username,
* v_password,
* v_hostname);
* if b_put = true
* then
* for i in t_files.first..t_files.last
* loop
* if t_files.exists(i)
* then
* dbms_output.put_line(t_files(i).status||' | '||
* t_files(i).error_message||' | '||
* to_char(t_files(i).bytes_transmitted)||' | '||
* to_char(t_files(i).trans_start,'yyyy-mm-dd
hh:mi:ss')||' | '||
* to_char(t_files(i).trans_end,'yyyy-mm-dd
hh:mi:ss'));
* end if;
* end loop;
* else
* dbms_output.put_line(v_error_message);
* end if;
*
* exception
* when others
* then
* dbms_output.put_line(sqlerrm);
* end;
*
* credits
* --------------------
* the w3c's rfc 959 that describes the ftp process.
*
* http://www.w3c.org
*
* much of the pl/sql code in this package was based on java code written by
* bruce blackshaw of enterprise distributed technologies ltd. none of that
code
* was copied, but the objects and methods greatly helped my understanding of
the
* ftp client process.
*
* http://www.enterprisedt.com
*
* version history
* --------------------
* 1.0 11/19/2002 unit-tested single and multiple transfers between
disparate hosts.
*
*
*/

/**
* exceptions
*
*/

ctrl_exception exception;
data_exception exception;

/**
* constants - ftp valid response codes
*
*/

connect_code constant pls_integer := 220;


user_code constant pls_integer := 331;
login_code constant pls_integer := 230;
pwd_code constant pls_integer := 257;
pasv_code constant pls_integer := 227;
cwd_code constant pls_integer := 250;
tsfr_start_code1 constant pls_integer := 125;
tsfr_start_code2 constant pls_integer := 150;
tsfr_end_code constant pls_integer := 226;
quit_code constant pls_integer := 221;
syst_code constant pls_integer := 215;
type_code constant pls_integer := 200;

/**
* ftp file record datatype
*
* elements:
* localpath - full directory name in which the local file resides or will
reside
* windows: 'd:\oracle\utl_file'
* unix: '/home/oracle/utl_file'
* filename - filename and extension for the file to be received or sent
* changing the filename for the put or get is currently not allowed
* examples: 'myfile.dat' 'myfile20021119.xml'
* remotepath - full directory name in which the local file will be sent or
the
* remote file exists. should be in unix format regardless of ftp
server - '/one/two/three'
* filetype - reserved for future use, ignored in code
* transfer_mode - 'put' or 'get'
* status - status of the transfer. 'error' or 'success'
* error_message - meaningful (hopefully) error message explaining the reason
for failure
* bytes_transmitted - how many bytes were sent/received
* trans_start - date/time the transmission started
* trans_end - date/time the transmission ended
*
*/

type r_ftp_rec is record(localpath varchar2(255),


filename varchar2(255),
remotepath varchar2(255),
filetype varchar2(20),
transfer_mode varchar2(5),
status varchar2(40),
error_message varchar2(255),
bytes_transmitted number,
trans_start date,
trans_end date);

/**
* ftp file table - used to store many files for transfer
*
*/

type t_ftp_rec is table of r_ftp_rec index by binary_integer;

/**
* internal convenience procedure for creating passive host ip address
* and port number.
*
*/

procedure create_pasv(p_pasv_cmd in varchar2,


p_pasv_host out varchar2,
p_pasv_port out number);

/**
* function used to validate ftp server responses based on the
* code passed in p_code. reads single or multi-line responses.
*
*/

function validate_reply(p_ctrl_con in out utl_tcp.connection,


p_code in pls_integer,
p_reply out varchar2)
return boolean;

/**
* function used to validate ftp server responses based on the
* code passed in p_code. reads single or multi-line responses.
* overloaded because some responses can have 2 valid codes.
*
*/

function validate_reply(p_ctrl_con in out utl_tcp.connection,


p_code1 in pls_integer,
p_code2 in pls_integer,
p_reply out varchar2)
return boolean;
/**
* procedure that handles the actual data transfer. meant
* for internal package use. returns information about the
* actual transfer.
*
*/

procedure transfer_ascii(u_ctrl_con in out utl_tcp.connection,


p_localpath in varchar2,
p_filename in varchar2,
p_pasv_host in varchar2,
p_pasv_port in pls_integer,
p_transfer_mode in varchar2,
v_status out varchar2,
v_error_message out varchar2,
n_bytes_transmitted out number,
d_trans_start out date,
d_trans_end out date);

/**
* function to handle ftp of many files.
* returns true if no batch-level errors occur.
* returns false if a batch-level error occurs.
*
* parameters:
*
* p_error_msg - error message for batch level errors
* p_files - brnc_ftp_pkg.t_ftp_rec table type. accepts
* list of files to be transferred (may be any combination of put or
get)
* returns the table updated with transfer status, error message,
* bytes_transmitted, transmission start date/time and transmission
end
* date/time
* p_username - username for ftp server
* p_password - password for ftp server
* p_hostname - hostname or ip address of server ex: 'ftp.oracle.com' or
'127.0.0.1'
* p_port - port number to connect on. ftp is usually on 21, but this may be
overridden
* if the server is configured differently.
*
*/

function ftp_multiple(p_error_msg out varchar2,


p_files in out t_ftp_rec,
p_username in varchar2,
p_password in varchar2,
p_hostname in varchar2,
p_port in pls_integer default 21)
return boolean;

/**
* convenience function for single-file put
*
* parameters:
* p_localpath - full directory name in which the local file resides or will
reside
* windows: 'd:\oracle\utl_file'
* unix: '/home/oracle/utl_file'
* p_filename - filename and extension for the file to be received or sent
* changing the filename for the put or get is currently not allowed
* examples: 'myfile.dat' 'myfile20021119.xml'
* p_remotepath - full directory name in which the local file will be sent or
the
* remote file exists. should be in unix format regardless of ftp
server - '/one/two/three'
* p_username - username for ftp server
* p_password - password for ftp server
* p_hostname - ftp server ip address or host name ex: 'ftp.oracle.com' or
'127.0.0.1'
* v_status - status of the transfer. 'error' or 'success'
* v_error_message - meaningful (hopefully) error message explaining the
reason for failure
* n_bytes_transmitted - how many bytes were sent/received
* d_trans_start - date/time the transmission started
* d_trans_end - date/time the transmission ended
* p_port - port number to connect to, default is 21
* p_filetype - always set to 'ascii', reserved for future use, ignored in
code
*
*/

function put(p_localpath in varchar2,


p_filename in varchar2,
p_remotepath in varchar2,
p_username in varchar2,
p_password in varchar2,
p_hostname in varchar2,
v_status out varchar2,
v_error_message out varchar2,
n_bytes_transmitted out number,
d_trans_start out date,
d_trans_end out date,
p_port in pls_integer default 21,
p_filetype in varchar2 := 'ascii')
return boolean;

/**
* convenience function for single-file get
*
* parameters:
* p_localpath - full directory name in which the local file resides or will
reside
* windows: 'd:\oracle\utl_file'
* unix: '/home/oracle/utl_file'
* p_filename - filename and extension for the file to be received or sent
* changing the filename for the put or get is currently not allowed
* examples: 'myfile.dat' 'myfile20021119.xml'
* p_remotepath - full directory name in which the local file will be sent or
the
* remote file exists. should be in unix format regardless of ftp
server - '/one/two/three'
* p_username - username for ftp server
* p_password - password for ftp server
* p_hostname - ftp server ip address or host name ex: 'ftp.oracle.com' or
'127.0.0.1'
* v_status - status of the transfer. 'error' or 'success'
* v_error_message - meaningful (hopefully) error message explaining the
reason for failure
* n_bytes_transmitted - how many bytes were sent/received
* d_trans_start - date/time the transmission started
* d_trans_end - date/time the transmission ended
* p_port - port number to connect to, default is 21
* p_filetype - always set to 'ascii', reserved for future use, ignored in
code
*
*/

function get(p_localpath in varchar2,


p_filename in varchar2,
p_remotepath in varchar2,
p_username in varchar2,
p_password in varchar2,
p_hostname in varchar2,
v_status out varchar2,
v_error_message out varchar2,
n_bytes_transmitted out number,
d_trans_start out date,
d_trans_end out date,
p_port in pls_integer default 21,
p_filetype in varchar2 := 'ascii')
return boolean;

end brnc_ftp_pkg;
/
create or replace package body brnc_ftp_pkg
as

/*****************************************************************************
** create the passive host ip and port number to connect to
**
*****************************************************************************/

procedure create_pasv(p_pasv_cmd in varchar2,


p_pasv_host out varchar2,
p_pasv_port out number)
is

v_pasv_cmd varchar2(30) := p_pasv_cmd; --host and port to connect to for


data transfer
n_port_dec number;
n_port_add number;

begin

p_pasv_host := replace(substr(v_pasv_cmd,1,instr(v_pasv_cmd,',',1,4)-
1),',','.');

n_port_dec :=
to_number(substr(v_pasv_cmd,instr(v_pasv_cmd,',',1,4)+1,(instr(v_pasv_cmd,',',1,5)
-(instr(v_pasv_cmd,',',1,4)+1))));
n_port_add :=
to_number(substr(v_pasv_cmd,instr(v_pasv_cmd,',',1,5)+1,length(v_pasv_cmd)-
instr(v_pasv_cmd,',',1,5)));

p_pasv_port := (n_port_dec*256) + n_port_add;

exception
when others
then
--dbms_output.put_line(sqlerrm);
raise;

end create_pasv;

/*****************************************************************************
** read a single or multi-line reply from the ftp server and validate
** it against the code passed in p_code.
**
** return true if reply code matches p_code, false if it doesn't or error
** occurs
**
** send full server response back to calling procedure
*****************************************************************************/

function validate_reply(p_ctrl_con in out utl_tcp.connection,


p_code in pls_integer,
p_reply out varchar2)
return boolean
is
n_code varchar2(3) := p_code;
n_byte_count pls_integer;
v_msg varchar2(255);
n_line_count pls_integer := 0;
begin
loop
v_msg := utl_tcp.get_line(p_ctrl_con);
n_line_count := n_line_count + 1;
if n_line_count = 1
then
p_reply := v_msg;
else
p_reply := p_reply || substr(v_msg,4);
end if;
exit when instr(v_msg,'-',1,1) <> 4;
end loop;
if to_number(substr(p_reply,1,3)) = n_code
then
return true;
else
return false;
end if;
exception
when others
then
p_reply := sqlerrm;
return false;
end validate_reply;
/*****************************************************************************
** reads a single or multi-line reply from the ftp server
**
** return true if reply code matches p_code1 or p_code2,
** false if it doesn't or error occurs
**
** send full server response back to calling procedure
*****************************************************************************/

function validate_reply(p_ctrl_con in out utl_tcp.connection,


p_code1 in pls_integer,
p_code2 in pls_integer,
p_reply out varchar2)
return boolean
is
v_code1 varchar2(3) := to_char(p_code1);
v_code2 varchar2(3) := to_char(p_code2);
v_msg varchar2(255);
n_line_count pls_integer := 0;
begin
loop
v_msg := utl_tcp.get_line(p_ctrl_con);
n_line_count := n_line_count + 1;
if n_line_count = 1
then
p_reply := v_msg;
else
p_reply := p_reply || substr(v_msg,4);
end if;
exit when instr(v_msg,'-',1,1) <> 4;
end loop;
if to_number(substr(p_reply,1,3)) in(v_code1,v_code2)
then
return true;
else
return false;
end if;
exception
when others
then
p_reply := sqlerrm;
return false;
end validate_reply;

/*****************************************************************************
** handles actual data transfer. responds with status, error message, and
** transfer statistics.
**
** potential errors could be with connection or file i/o
**
*****************************************************************************/

procedure transfer_ascii(u_ctrl_con in out utl_tcp.connection,


p_localpath in varchar2,
p_filename in varchar2,
p_pasv_host in varchar2,
p_pasv_port in pls_integer,
p_transfer_mode in varchar2,
v_status out varchar2,
v_error_message out varchar2,
n_bytes_transmitted out number,
d_trans_start out date,
d_trans_end out date)
is
u_data_con utl_tcp.connection;
u_filehandle utl_file.file_type;
v_tsfr_mode varchar2(3) := p_transfer_mode;
v_mode varchar2(1);
v_tsfr_cmd varchar2(10);
v_buffer varchar2(32767);
v_localpath varchar2(255) := p_localpath;
v_filename varchar2(255) := p_filename;
v_host varchar2(20) := p_pasv_host;
n_port pls_integer := p_pasv_port;
n_bytes number;
v_msg varchar2(255);
v_reply varchar2(1000);
v_err_status varchar2(20) := 'error';

begin

/** initialize some of our out variables **/

v_status := 'success';
v_error_message := ' ';
n_bytes_transmitted := 0;

if upper(v_tsfr_mode) = 'put'
then
v_mode := 'r';
v_tsfr_cmd := 'stor ';

elsif upper(v_tsfr_mode) = 'get'


then
v_mode := 'w';
v_tsfr_cmd := 'retr ';
end if;

/** open data connection on passive host and port **/

u_data_con := utl_tcp.open_connection(v_host,n_port);

/** open the local file to read and transfer data **/

u_filehandle := utl_file.fopen(v_localpath,v_filename,v_mode);

/** send the stor command to tell the server we're going to upload a file
**/

n_bytes := utl_tcp.write_line(u_ctrl_con,v_tsfr_cmd||v_filename);
if validate_reply(u_ctrl_con,tsfr_start_code1,tsfr_start_code2,v_reply) =
false
then
raise ctrl_exception;
end if;
d_trans_start := sysdate;

if upper(v_tsfr_mode) = 'put'
then
loop
begin
utl_file.get_line(u_filehandle,v_buffer);
exception
when no_data_found
then
exit;
end;

n_bytes := utl_tcp.write_line(u_data_con,v_buffer);
n_bytes_transmitted := n_bytes_transmitted + n_bytes;

end loop;

elsif upper(v_tsfr_mode) = 'get'


then
loop
begin
v_buffer := utl_tcp.get_line(u_data_con,true);

/** sometimes the tcp/ip buffer sends null data **/


/** we only want to receive the actual data **/

if v_buffer is not null


then
utl_file.put_line(u_filehandle,v_buffer);
n_bytes := length(v_buffer);
n_bytes_transmitted := n_bytes_transmitted + n_bytes;
end if;

exception
when utl_tcp.end_of_input
then
exit;
end;

end loop;

end if;

/** flush the buffer on the data connection **/

--utl_tcp.flush(u_data_con);

d_trans_end := sysdate;

/** close the file **/

utl_file.fclose(u_filehandle);

/** close the data connection **/


utl_tcp.close_connection(u_data_con);

/** verify the transfer succeeded **/

if validate_reply(u_ctrl_con,tsfr_end_code,v_reply) = false
then
raise ctrl_exception;
end if;

exception
when ctrl_exception
then
v_status := v_err_status;
v_error_message := v_reply;
if utl_file.is_open(u_filehandle)
then
utl_file.fclose(u_filehandle);
end if;
utl_tcp.close_connection(u_data_con);

when utl_file.invalid_path
then
v_status := v_err_status;
v_error_message := 'directory '||v_localpath||' is not available to
utl_file. check the init.ora file for valid utl_file directories.';
utl_tcp.close_connection(u_data_con);

when utl_file.invalid_operation
then
v_status := v_err_status;

if upper(v_tsfr_mode) = 'put'
then
v_error_message := 'the file '||v_filename||' in the directory '||
v_localpath||' could not be opened for reading.';

elsif upper(v_tsfr_mode) = 'get'


then
v_error_message := 'the file '||v_filename||' in the directory '||
v_localpath||' could not be opened for writing.';

end if;

if utl_file.is_open(u_filehandle)
then
utl_file.fclose(u_filehandle);
end if;
utl_tcp.close_connection(u_data_con);

when utl_file.read_error
then
v_status := v_err_status;
v_error_message := 'the system encountered an error while trying to read '||
v_filename||' in the directory '||v_localpath;

if utl_file.is_open(u_filehandle)
then
utl_file.fclose(u_filehandle);
end if;
utl_tcp.close_connection(u_data_con);

when utl_file.write_error
then
v_status := v_err_status;
v_error_message := 'the system encountered an error while trying to write to
'||v_filename||' in the directory '||v_localpath;

if utl_file.is_open(u_filehandle)
then
utl_file.fclose(u_filehandle);
end if;
utl_tcp.close_connection(u_data_con);

when utl_file.internal_error
then
v_status := v_err_status;
v_error_message := 'the utl_file package encountered an unexpected internal
system error.';

if utl_file.is_open(u_filehandle)
then
utl_file.fclose(u_filehandle);
end if;
utl_tcp.close_connection(u_data_con);

when others
then
v_status := v_err_status;
v_error_message := sqlerrm;
if utl_file.is_open(u_filehandle)
then
utl_file.fclose(u_filehandle);
end if;
utl_tcp.close_connection(u_data_con);
end transfer_ascii;

/*****************************************************************************
** handles connection to host and ftp of multiple files
** files can be any combination of put and get
**
*****************************************************************************/

function ftp_multiple(p_error_msg out varchar2,


p_files in out t_ftp_rec,
p_username in varchar2,
p_password in varchar2,
p_hostname in varchar2,
p_port in pls_integer default 21)
return boolean
is
v_username varchar2(30) := p_username;
v_password varchar2(30) := p_password;
v_hostname varchar2(30) := p_hostname;
n_port pls_integer := p_port;
u_ctrl_con utl_tcp.connection;
n_byte_count pls_integer;
n_first_index number;
v_msg varchar2(250);
v_reply varchar2(1000);
v_pasv_host varchar2(20);
n_pasv_port number;

invalid_transfer exception;
begin

p_error_msg := 'ftp successful'; --assume the overall transfer will succeed

/** attempt to connect to the host machine **/

u_ctrl_con := utl_tcp.open_connection(v_hostname,n_port);
if validate_reply(u_ctrl_con,connect_code,v_reply) = false
then
raise ctrl_exception;
end if;

/** send username **/

n_byte_count := utl_tcp.write_line(u_ctrl_con,'user '||v_username);


if validate_reply(u_ctrl_con,user_code,v_reply) = false
then
raise ctrl_exception;
end if;

/** send password **/

n_byte_count := utl_tcp.write_line(u_ctrl_con,'pass '||v_password);


if validate_reply(u_ctrl_con,login_code,v_reply) = false
then
raise ctrl_exception;
end if;

/** we should be logged in, time to transfer all files **/

for i in p_files.first..p_files.last
loop
if p_files.exists(i)
then
begin

/** change to the remotepath directory **/

n_byte_count := utl_tcp.write_line(u_ctrl_con,'cwd '||


p_files(i).remotepath);
if validate_reply(u_ctrl_con,cwd_code,v_reply) = false
then
raise ctrl_exception;
end if;

/** switch to image mode **/

n_byte_count := utl_tcp.write_line(u_ctrl_con,'type i');


if validate_reply(u_ctrl_con,type_code,v_reply) = false
then
raise ctrl_exception;
end if;

/** get a passive connection to use for data transfer **/

n_byte_count := utl_tcp.write_line(u_ctrl_con,'pasv');
if validate_reply(u_ctrl_con,pasv_code,v_reply) = false
then
raise ctrl_exception;
end if;

create_pasv(substr(v_reply,instr(v_reply,'(',1,1)+1,instr(v_reply,')',1,1)-
instr(v_reply,'(',1,1)-1),v_pasv_host,n_pasv_port);

/** transfer data **/

if upper(p_files(i).transfer_mode) = 'put'
then
transfer_ascii(u_ctrl_con,
p_files(i).localpath,
p_files(i).filename,
v_pasv_host,
n_pasv_port,
p_files(i).transfer_mode,
p_files(i).status,
p_files(i).error_message,
p_files(i).bytes_transmitted,
p_files(i).trans_start,
p_files(i).trans_end);

elsif upper(p_files(i).transfer_mode) = 'get'


then
transfer_ascii(u_ctrl_con,
p_files(i).localpath,
p_files(i).filename,
v_pasv_host,
n_pasv_port,
p_files(i).transfer_mode,
p_files(i).status,
p_files(i).error_message,
p_files(i).bytes_transmitted,
p_files(i).trans_start,
p_files(i).trans_end);
else
raise invalid_transfer; -- raise an exception here
end if;

exception
when ctrl_exception
then
p_files(i).status := 'error';
p_files(i).error_message := v_reply;

when invalid_transfer
then
p_files(i).status := 'error';
p_files(i).error_message := 'invalid transfer method. use put or
get.';
end;
end if;
end loop;

/** send quit command **/


n_byte_count := utl_tcp.write_line(u_ctrl_con,'quit');

/** don't need to validate quit, just close the connection **/

utl_tcp.close_connection(u_ctrl_con);
return true;

exception
when ctrl_exception
then
p_error_msg := v_reply;
utl_tcp.close_all_connections;
return false;
when others
then
p_error_msg := sqlerrm;
utl_tcp.close_all_connections;
return false;
end ftp_multiple;

/*****************************************************************************
** convenience function for single-file put
** formats file information for ftp_multiple function and calls it.
**
*****************************************************************************/

function put(p_localpath in varchar2,


p_filename in varchar2,
p_remotepath in varchar2,
p_username in varchar2,
p_password in varchar2,
p_hostname in varchar2,
v_status out varchar2,
v_error_message out varchar2,
n_bytes_transmitted out number,
d_trans_start out date,
d_trans_end out date,
p_port in pls_integer default 21,
p_filetype in varchar2 := 'ascii')
return boolean
is
t_files t_ftp_rec;
v_username varchar2(30) := p_username;
v_password varchar2(50) := p_password;
v_hostname varchar2(100) := p_hostname;
n_port pls_integer := p_port;
v_err_msg varchar2(255);
b_ftp boolean;
begin
t_files(1).localpath := p_localpath;
t_files(1).filename := p_filename;
t_files(1).remotepath := p_remotepath;
t_files(1).filetype := p_filetype;
t_files(1).transfer_mode := 'put';

b_ftp := ftp_multiple(v_err_msg,
t_files,
v_username,
v_password,
v_hostname,
n_port);
if b_ftp = false
then
v_status := 'error';
v_error_message := v_err_msg;
return false;
elsif b_ftp = true
then
v_status := t_files(1).status;
v_error_message := t_files(1).error_message;
n_bytes_transmitted := t_files(1).bytes_transmitted;
d_trans_start := t_files(1).trans_start;
d_trans_end := t_files(1).trans_end;
return true;
end if;
exception
when others
then
v_status := 'error';
v_error_message := sqlerrm;
return false;
--dbms_output.put_line(sqlerrm);
end put;

/*****************************************************************************
** convenience function for single-file get
** formats file information for ftp_multiple function and calls it.
**
*****************************************************************************/

function get(p_localpath in varchar2,


p_filename in varchar2,
p_remotepath in varchar2,
p_username in varchar2,
p_password in varchar2,
p_hostname in varchar2,
v_status out varchar2,
v_error_message out varchar2,
n_bytes_transmitted out number,
d_trans_start out date,
d_trans_end out date,
p_port in pls_integer default 21,
p_filetype in varchar2 := 'ascii')
return boolean
is
t_files t_ftp_rec;
v_username varchar2(30) := p_username;
v_password varchar2(50) := p_password;
v_hostname varchar2(100) := p_hostname;
n_port pls_integer := p_port;
v_err_msg varchar2(255);
b_ftp boolean;
begin
t_files(1).localpath := p_localpath;
t_files(1).filename := p_filename;
t_files(1).remotepath := p_remotepath;
t_files(1).filetype := p_filetype;
t_files(1).transfer_mode := 'get';

b_ftp := ftp_multiple(v_err_msg,
t_files,
v_username,
v_password,
v_hostname,
n_port);
if b_ftp = false
then
v_status := 'error';
v_error_message := v_err_msg;
return false;
elsif b_ftp = true
then
v_status := t_files(1).status;
v_error_message := t_files(1).error_message;
n_bytes_transmitted := t_files(1).bytes_transmitted;
d_trans_start := t_files(1).trans_start;
d_trans_end := t_files(1).trans_end;
return true;
end if;
exception
when others
then
v_status := 'error';
v_error_message := sqlerrm;
return false;
--dbms_output.put_line(sqlerrm);
end get;

end brnc_ftp_pkg;
/

-------------
rem -----------------------------------------------------------------------
rem filename: smtp.sql
rem purpose: send e-mail messages from pl/sql
rem notes: from oracle8i release 8.1.6 one can send e-mail messages
rem directly from pl/sql using either the utl_tcp or utl_smtp
rem packages. jserver needs to be installed and configured.
rem pont the ip address to your local smtp (simple mail
rem transport) server. no pipes or external procedures are
rem required.
rem date: 27-mar-2000
rem author: frank naude, oracle faq
rem -----------------------------------------------------------------------

create or replace procedure send_mail (


msg_from varchar2 := 'oracle',
msg_to varchar2,
msg_subject varchar2 := 'e-mail message from your database',
msg_text varchar2 := '' )
is
c utl_tcp.connection;
rc integer;
begin
c := utl_tcp.open_connection('127.0.0.1', 25); -- open the smtp port 25 on
local machine
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'helo localhost');
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'mail from: '||msg_from);
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'rcpt to: '||msg_to);
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'data'); -- start message body
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'subject: '||msg_subject);
rc := utl_tcp.write_line(c, '');
rc := utl_tcp.write_line(c, msg_text);
rc := utl_tcp.write_line(c, '.'); -- end of message body
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'quit');
dbms_output.put_line(utl_tcp.get_line(c, true));
utl_tcp.close_connection(c); -- close the connection
exception
when others then
raise_application_error(
-20000, 'unable to send e-mail message from pl/sql because of: '||
sqlerrm);
end;
/
show errors

-- examples:
set serveroutput on

exec send_mail(msg_to =>'you@yourdomain.com');

exec send_mail(msg_to =>'you@yourdomain.com', -


msg_text=>'look ma, i can send mail from plsql' -
);
---------------
rem ----------------------------------------------------------------------
rem filename: smtp-att.sql
rem purpose: send e-mail messages and attachments from pl/sql
rem notes: from oracle8i release 8.1.6 one can send e-mail messages
rem directly from pl/sql using either the utl_tcp or utl_smtp
rem packages. jserver needs to be installed and configured.
rem no pipes or external procedures required.
rem date: 15-mar-2001
rem author: virgilio nunes (virgilio@logtek.co.za)
rem ----------------------------------------------------------------------

create or replace procedure send_mail (


msg_from varchar2 := 'emailaddress@domain.com', ----- mail box sending the
email
msg_to varchar2 := 'emailaddress@domain.com', ----- mail box recieving
the email
msg_subject varchar2 := 'output file test1', ----- email subject
msg_text varchar2 := 'this is the text of the email message.',
v_output1 varchar2 := 'this is the text of the attachment file. this text
should be in a text file attached to the email.')
is
c utl_tcp.connection;
rc integer;
crlf varchar2(2):= chr(13)||chr(10);
mesg varchar2( 32767 );
begin
c := utl_tcp.open_connection('196.35.140.18', 25); ----- open smtp port
connection
rc := utl_tcp.write_line(c, 'helo 196.35.140.18'); ----- performs
handshaking with smtp server
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'ehlo 196.35.140.18'); ----- performs
handshaking with smtp server, including extra information
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'mail from: '||msg_from); ----- mail box sending
the email
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'rcpt to: '||msg_to); ----- mail box
recieving the email
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'data'); ----- email message
body start
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'date: '||to_char( sysdate, 'dd mon yy
hh24:mi:ss' ));
rc := utl_tcp.write_line(c, 'from: '||msg_from||' <'||msg_from||'>');
rc := utl_tcp.write_line(c, 'mime-version: 1.0');
rc := utl_tcp.write_line(c, 'to: '||msg_to||' <'||msg_to||'>');
rc := utl_tcp.write_line(c, 'subject: '||msg_subject);
rc := utl_tcp.write_line(c, 'content-type: multipart/mixed;'); -----
indicates that the body consists of more than one part
rc := utl_tcp.write_line(c, ' boundary="-----secbound"'); -----
seperator used to seperate the body parts
rc := utl_tcp.write_line(c, ''); ----- inserts
a blank line. part of the mime format and none of them should be removed.
rc := utl_tcp.write_line(c, '-------secbound');
rc := utl_tcp.write_line(c, 'content-type: text/plain'); ----- 1st
body part. email text message
rc := utl_tcp.write_line(c, 'content-transfer-encoding: 7bit');
rc := utl_tcp.write_line(c, '');
rc := utl_tcp.write_line(c, msg_text); ----- text of
email message
rc := utl_tcp.write_line(c, '');
rc := utl_tcp.write_line(c, '-------secbound');
rc := utl_tcp.write_line(c, 'content-type: text/plain;'); ----- 2nd
body part.
rc := utl_tcp.write_line(c, ' name="test.txt"');
rc := utl_tcp.write_line(c, 'content-transfer_encoding: 8bit');
rc := utl_tcp.write_line(c, 'content-disposition: attachment;'); -----
indicates that this is an attachment
rc := utl_tcp.write_line(c, ' filename="test.txt"'); -----
suggested file name for attachment
rc := utl_tcp.write_line(c, '');
rc := utl_tcp.write_line(c, v_output1);
rc := utl_tcp.write_line(c, '-------secbound--');
rc := utl_tcp.write_line(c, '');
rc := utl_tcp.write_line(c, '.'); ----- email message body
end
dbms_output.put_line(utl_tcp.get_line(c, true));
rc := utl_tcp.write_line(c, 'quit'); ----- ends email
transaction
dbms_output.put_line(utl_tcp.get_line(c, true));
utl_tcp.close_connection(c); ----- close smtp port
connection
exception
when others then
raise_application_error(-20000, sqlerrm);
end;
/

-------------
rem -----------------------------------------------------------------------
rem filename: auditdll.sql
rem purpose: maintain an audit log of ddl changes (alter/ drop/ create)
rem within a schema
rem date: 15-feb-2002
rem author: frank naude, oracle faq
rem -----------------------------------------------------------------------

drop trigger audit_ddl_changes


/
drop table dll_audit_log
/

create table dll_audit_log (


stamp date,
username varchar2(30),
osuser varchar2(30),
machine varchar2(30),
terminal varchar2(30),
operation varchar2(30),
objtype varchar2(30),
objname varchar2(30))
/

create or replace trigger audit_ddl_changes


after create or drop or alter
on scott.schema -- change scott to your schema name!!!
-- on database
begin
insert into dll_audit_log values
(sysdate,
sys_context('userenv', 'session_user'),
sys_context('userenv', 'os_user'),
sys_context('userenv', 'host'),
sys_context('userenv', 'terminal'),
ora_sysevent,
ora_dict_obj_type,
ora_dict_obj_name
);
end;
/
show errors

-- now, let's test it


create table my_test_table (col1 date)
/
drop table my_test_table
/
set pages 50000
select * from dll_audit_log
/
------------
rem -----------------------------------------------------------------------
rem filename: strreplace.sql
rem purpose: replace all occurences of a substring with another substring
rem date: 28-jul-2003
rem author: frank naude, oracle faq
rem -----------------------------------------------------------------------

create or replace function strreplace(str varchar2, from_str varchar2, to_str


varchar2)
return varchar2
as
str_temp varchar2(4000);
str_pos number := instr(str, from_str);
begin
str_temp := str;
while ( str_pos > 0 ) loop
str_temp := substr(str_temp, 0, str_pos-1) || to_str ||
substr(str_temp, str_pos + length(from_str));
str_pos := instr(str_temp, from_str);
end loop;
return str_temp;
end;
/
show errors

-- examples

select strreplace('this is a beautiful day!', 'beautiful', 'horrible')


from dual
/

select 'mv '||name||' '||strreplace(name, 'oldsid', 'newsid')


from v$datafile
/

-----------
rem -----------------------------------------------------------------------
rem filename: indicheq.sql
rem purpose: this procedure will convert numbers to chars for printing
rem cheques amount in indian style. it will print amount from
rem rs1 to rs.989999999.
rem note: in order to see your output in sql*plus, set serverout on
rem date: 22-feb-2003
rem author: birender kumar, bir_canada@yahoo.com
rem updateded: 04-aug-2003
rem updated by: marine, marine00072003@yahoo.com
rem -----------------------------------------------------------------------

set serveroutput on;

create or replace procedure cheq(n number)


as
l number := 0;
output varchar2(2000) := '';
x varchar2(2000) := '';
x1 varchar2(2000) := '';
c1 varchar2(2000) := '';
begin
l := length(n);

if n < 0 or n > 999999999 then


dbms_output.put_line('invalid amount');
else

if ( n = 0 ) then
x := 'zero ';
elsif ( n <= 99999 ) then
x := to_char(to_date(n,'j'),'jsp') || ' ';
else

if ( to_number(substr(n, l - 5 + 1)) = 0 ) then


x := '';
else
x := to_char(to_date(to_number(substr(n, l - 5 + 1)),'j'),'jsp') || '
';
end if;

if ( l = 6 ) then
x1 := to_char(to_date(to_number(substr(n, 1, l - 5)),'j'),'jsp') || '
lakh ';
else
if ( to_number(substr(n, l - 5 -1, 2)) = 0 ) then
x1 := '';
else
x1 := to_char(to_date(to_number(substr(n, l - 5 - 1,
2)),'j'),'jsp') || ' lakh ';
end if;

if ( l >= 8 ) then
c1 := to_char(to_date(to_number(substr(n, 1, l-7)),'j'),'jsp')||'
crore ';
end if;
end if;
end if;

if ( n = 0 or n = 1 ) then
dbms_output.put_line(n||' => '||x||'rupee only');
else
dbms_output.put_line(n||' => '||c1||x1||x||'rupees only');
end if;
end if;
end cheq;
/
show errors

-----------------
rem -----------------------------------------------------------------------
rem filename: logintrig.sql
rem purpose: audit user logins and enable sql tracing for selected users
rem date: 09-jul-2005
rem author: frank naude, oracle faq
rem -----------------------------------------------------------------------

connect / as sysdba

drop table user_login_audit;

create table user_login_audit (


login_time date,
username varchar2(30),
machine varchar2(30),
command varchar2(128)
);

create or replace trigger user_login_trig


after logon on scott.schema
declare
v_username sys.v_$session.username%type;
v_machine sys.v_$session.machine%type;
v_command sys.v_$session.command%type;
begin
select username, machine, command
into v_username, v_machine, v_command
from sys.v_$session
where audsid = userenv('sessionid')
and audsid != 0 -- don't check sys connections
and rownum = 1; -- parallel processes will have the same audsid's

insert into sys.user_login_audit


values (sysdate, v_username, v_machine, v_command);

if upper(v_machine) like '%pc1%' then -- start sql trace for users from
pc1
dbms_session.set_sql_trace(true);
end if;
end;
/
show errors

connect scott/tiger

connect / as sysdba

select * from sys.user_login_audit;

-------------

save blob data into file system with java language (oracle 9ir2 bug: 2546782!!)
-- if necessary, please modify
-- user: plpdf
-- directory: c:\ll\
--

create or replace java source named "blobhandler" as


import java.lang.*;
import java.sql.*;
import oracle.sql.*;
import java.io.*;

public class blobhandler


{
public static void exportblob(string myfile, blob myblob) throws exception
{
// bind the object to the database object
// open streams for the output file and the blob
file binaryfile = new file(myfile);
fileoutputstream outstream = new fileoutputstream(binaryfile);
inputstream instream = myblob.getbinarystream();

// get the optimum buffer size and use this to create the read/write buffer
int size = myblob.getbuffersize();
byte[] buffer = new byte[size];
int length = -1;

// transfer the data


while ((length = instream.read(buffer)) != -1)
{
outstream.write(buffer, 0, length);
outstream.flush();
}
// close everything down
instream.close();
outstream.close();
}
};
/

alter java source "blobhandler" compile;


show errors java source "blobhandler"

create or replace procedure exportblob (p_file in varchar2,


p_blob in blob)
as language java
name 'blobhandler.exportblob(java.lang.string, oracle.sql.blob)';
/

exec dbms_java.grant_permission('plpdf', 'sys:java.io.filepermission', 'c:\ll\*',


'read,write,execute,delete');

exec
dbms_java.grant_permission('plpdf','sys:java.lang.runtimepermission','writefiledes
criptor', null);
exec
dbms_java.grant_permission('plpdf','sys:java.lang.runtimepermission','readfiledesc
riptor', null);
exec
dbms_java.grant_permission('plpdf','sys:java.util.propertypermission','c:\ll\*','r
ead,write');
-- usage
declare
v_blob blob;
cursor c1 is select blob_file from store_blob;
begin
open c1;
fetch c1 into v_blob;
exportblob('c:\ll\test2.pdf',v_blob);
close c1;

end;
/
----------------------
this file shows one possible way that you can utilize
dynamic pl/sql. the first version of process_lineitem
relies on an extremely long if statement to determine
which of the line item-specific procedures should be
executed.

this is, by the way, a "real world" example. the


process_lineitem procedure was so large that it often
would not even compile.

the second process_lineitem utilizes dbms_sql to


squeeze the program down to a mere 3 executable statements.

version 1. help!

procedure process_lineitem (line_in in integer)


is
begin
if line_in = 1
then
process_line1; end if;

if line_in = 2
then
process_line2; end if;
...
if line_in = 2045
then
process_line2045;
end if;
end;

2. version 2: well, at least let's use the right conditional


statement

procedure process_lineitem (line_in in integer)


is
begin
if line_in = 1
then
process_line1;

elsif line_in = 2
then
process_line2;
...
elsif line_in = 2045
then
process_line2045;
end if;
end;

3. dynamic version using dbms_sql

procedure process_lineitem (line_in in integer)


is
cur pls_integer := dbms_sql.open_cursor;
fdbk pls_integer;
begin
dbms_sql.parse (
cur,
'begin process_line' || line_in || '; end;',
dbms_sql.native
);

fdbk := dbms_sql.execute (cur);

dbms_sql.close_cursor (cur);
end;

3. dynamic version using nds

procedure process_lineitem (line_in in integer)


is
begin
execute immediate
'begin process_line '|| line_in ||'; end';
end;
-----------------
parameterised table_name and where caluse
drop table nasty_data;

drop procedure backdoor;

rem this program is left wide-open to code injection through the


rem dynamic where clause.

create or replace procedure get_rows (


table_in in varchar2, where_in in varchar2
)
is
l_block varchar2(32767) :=
'declare l_row ' || table_in || '%rowtype;' ||
'begin' ||
' select * into l_row ' ||
'from ' || table_in || ' where ' || where_in || ';' ||
'/*process_data (l_row);*/ ' ||
'end;';
begin
execute immediate l_block;
exception
when others
then
dbms_output.put_line( dbms_utility.format_error_stack );
dbms_output.put_line ( l_block );
raise;
end get_rows;
/

-- intended usage
begin
get_rows ('employee', 'employee_id=101');
end;
/

begin
get_rows ('employee'
,'employee_id=101;
execute immediate ''create table nasty_data (mycol number)''',sysdate );
end;
/

begin
get_rows ('employee'
,'employee_id=101;
execute immediate
''create procedure backdoor (str varchar2)
as begin execute immediate str; end;''' );
end;
/

rem one way to minimize the danger of injection is to avoid the


rem completely generic where clause and instead code for
rem specific, anticipated variations.

create or replace procedure get_rows (


table_in in varchar2, value1_in in varchar2, value2_in in date
)
is
l_where varchar2(32767);
begin
if table_in = 'employee'
then
l_where := 'last_name = :name and hire_date < :hdate';
elsif table_in = 'department'
then
l_where := 'name like :name and incorporation_date = :hdate';
else
raise_application_error (-20000, 'invalid table name for get_rows: ' ||
table_in);
end if;

execute immediate
'declare l_row ' || table_in || '%rowtype;' ||
'begin ' ||
' select * into l_row ' ||
'from ' || table_in || ' where ' || l_where || ';' ||
'end;'
using value1_in, value2_in;
end get_rows;
/

--------
send mail from oracle
# package to create and send email using send mail.
# creates flat file read by a cron job.
# last modified 09/28/1999 bob rudolf
#

create or replace package sndmail is


/**********************************************************/
/* different communication procedures */
/**********************************************************/
/* validation procedure assert */
procedure assert
(bool_in in boolean,
stg_in in varchar2 default null);

/* procedure to send the e-mail message */


-- parameters:
-- p_to - e-mail address of the receiver. it can be a list of
-- adresses separated with one blank. must be supplied!
-- p_subject - subject of the message, can be null
-- p_text - text of the message - maximum 32767 bytes, required!
-- example: wisdm.sndmail.send_mail(
-- 'myaddress@mail.sbic.co.za suljo@mail.sbic.co.za',
-- 'this is the subject',
-- 'this is the text of the message');
procedure send_mail
(p_to in varchar2, p_subject in varchar2, p_text in varchar2);

/* procedure to send the sms */


-- parameters:
-- p_tel_no - phone number or list of numbers
-- separated with one blank
-- p_text - text of the message - maximum 140 bytes
--
-- example: wisdm.sndmail.send_sms(
-- '0832789012 0824441234',
-- 'this is the text of the message');
procedure send_sms
(p_tel_no in varchar2,
p_text in varchar2);

end;
/
create or replace package body sndmail is
/**********************************************************/
/* different communication procedures */
/**********************************************************/
/* constants */
mtn_code constant varchar2(3) := '083';
vodacom_code constant varchar2(3) := '082';
mtn_address constant varchar2(30) := '@sms.co.za';
vodacom_address constant varchar2(30) := 'sms@yebo.co.za';

procedure assert
(bool_in in boolean,
stg_in in varchar2 default null)
is
begin
if not bool_in or bool_in is null
then
if stg_in is not null
then
dbms_output.put_line(stg_in);
end if;
raise value_error;
end if;
end;

/* procedure to send the e-mail message */


-- parameters:
-- p_to - e-mail address of the receiver. it can be a list of
-- adresses separated with blank
-- p_subject - subject of the message
-- p_text - text of the message - maximum 32767 bytes
-- example: wisdm.sndmail.send_mail(
-- 'myaddress@mail.sbic.co.za suljo@mail.sbic.co.za',
-- 'this is the subject',
-- 'this is the text of the message');
procedure send_mail
(p_to in varchar2,
p_subject in varchar2,
p_text in varchar2)
is
v_subject varchar2(100);
v_text varchar2(32767);
file_handle utl_file.file_type;
v_dir varchar2(100);
v_file varchar2(100);
v_dat_file varchar2(100);
v_start_text varchar2(1000);
v_txt_len number;
v_loop_cnt number;
seq_no varchar2(6);
dat_file_ind boolean := false;

begin

-- check input
assert (p_to is not null,
'please supply recipient');
assert (p_text is not null,
'please supply text');
assert (nvl(length(p_subject),0) < 101,
'subject to long - maximum 100 bytes');
assert ((length(p_to) + length(p_subject) ) < 1000,
'recipient to long - send 2 or more messages');
if (length(p_to) + length(v_subject) + length(p_text)) > 999
then
dat_file_ind := true;
end if;

/* set up directory and file name, usig sequence */


select to_char(wisdm.send_mail_file.nextval),
decode(p_subject,null,null,'-s '||
wisdm.utility.quoteme(p_subject))
into seq_no,
v_subject
from dual;

v_dir := '/udd001/home/dmaint/wisdm_alert';
v_file := 'mail'||seq_no||'.sh';
v_dat_file := 'mail'||seq_no||'.dat';

file_handle := utl_file.fopen(v_dir,v_file,'w');
if dat_file_ind
then
v_start_text := 'more '||v_dat_file;
else
v_start_text := 'echo '||wisdm.utility.quoteme(p_text);
end if;

utl_file.put_line(file_handle,
v_start_text||
' | mailx '|| v_subject ||' '||
wisdm.utility.quoteme(p_to));
if utl_file.is_open(file_handle)
then
utl_file.fclose(file_handle);
end if;

-- send .dat file if message was to long


if dat_file_ind
then
-- v_text := p_text;
-- v_txt_len := length(v_text);

v_txt_len := length(p_text);

v_loop_cnt := 1;
file_handle := utl_file.fopen(v_dir,v_dat_file,'w');
loop
exit when v_loop_cnt > v_txt_len;
utl_file.put_line(file_handle,
substr(p_text,v_loop_cnt,80));
v_loop_cnt := v_loop_cnt + 80;
end loop;

if utl_file.is_open(file_handle)
then
utl_file.fclose(file_handle);
end if;
end if;

exception
when utl_file.invalid_path
then dbms_output.put_line('inv path');
raise;
when utl_file.invalid_mode
then dbms_output.put_line('invalid_mode');
raise;
when utl_file.invalid_filehandle
then dbms_output.put_line('invalid_filehandle');
raise;
when utl_file.invalid_operation
then dbms_output.put_line('invalid_operation');
raise;
when utl_file.write_error
then dbms_output.put_line('write_error');
raise;

when utl_file.read_error
then dbms_output.put_line('read_error');
raise;

when utl_file.internal_error
then dbms_output.put_line('internal_error');
raise;

when others
then dbms_output.put_line(sqlerrm);
raise;
end;

/* procedure to send the sms */


-- at the moment available only for mtn subscribers
-- parameters:
-- p_tel_no - cell phone number or list of numbers
-- separated with blank
-- p_text - text of the message - maximum 140 bytes
-- example: wisdm.sndmail.send_sms(
-- '0832789012 0834441234',
-- 'this is the subject',
-- 'this is the text of the message');
procedure send_sms
(p_tel_no in varchar2,
p_text in varchar2)
is
type tel_type is table of varchar2(15)
index by binary_integer;
tel_tab tel_type;
j integer;
k integer;
pos integer;
v_code varchar2(3);
v_tel_no varchar2(2000);
begin
assert (length(p_text) < 140,
'message to long');
v_tel_no := rtrim(ltrim(p_tel_no));
assert (v_tel_no is not null,
'at least one telefon number must be supplied');

pos := 1;
k := 0;
loop
j := instr(v_tel_no,' ',pos);
exit when j=0;
k := k +1;
tel_tab(k) := substr(v_tel_no,pos,j-pos);
pos := j + 1;
end loop;
k := k +1;
tel_tab(k) := substr(v_tel_no,pos);

for i in 1 .. k
loop
v_code := substr(tel_tab(i),1,3);
if v_code = mtn_code
then
send_mail('++27'||substr(tel_tab(i),2)||
mtn_address,
null,p_text);
elsif v_code = vodacom_code
then
send_mail(vodacom_address,tel_tab(i),p_text);
else
dbms_output.put_line('wrong provider code');
raise value_error;
end if;
end loop;

end;

end;
/
---------------------------------------------
-----------------------------------------------
-- unix job which runs with crontab
---------------------------------------------------

#####################################################################
# step 1 #
# get a list of all the mail sh files that are going to be executed #
# get a list of all dat files so that we can remove these later #
#####################################################################
cd /udd001/home/dmaint/wisdm_alert
rm job_log
ls mail*.sh > all_sh_files
ls mail*.dat > all_dat_files
#####################################################################
# step 2 #
# loop through the sh file list and execute them #
#####################################################################
echo "the following jobs have been executed" > job_log
for sendmailx in `cat all_sh_files`
do
chmod 744 $sendmailx
$sendmailx
wait
echo "sh file " $sendmailx " has been executed" >> job_log
done
#####################################################################
# step 3 #
# generate and run remove script to rm all the sh and dat files #
#####################################################################
cat all_sh_files | awk '{print "rm "$1}' > rm_all_old_sh_+_dat
cat all_dat_files | awk '{print "rm "$1}' >> rm_all_old_sh_+_dat
echo "the following file have been removed" >> job_log
cat rm_all_old_sh_+_dat >> job_log
chmod 744 rm_all_old_sh_+_dat
rm_all_old_sh_+_dat
rm rm_all_old_sh_+_dat
rm all_sh_files all_dat_files
________________

S-ar putea să vă placă și