Oracle - PL/SQL
• Introduzione ad Oracle
• PL/SQL: Elementi di base
• Tecniche di programmazione
–
–
–
–
uso delle variabili
uso dei cursori
uso delle funzioni/procedure
I/O
Oracle: Prodotti
• SQL*Plus - Interprete di comandi come DDL,
DML.
• Developer/2000 and Developer. Suite di tool di
sviluppo
– Oracle*Forms - Data entry e manipulation a schermo
– Oracle*Reports - Tool di gestione dei report
– Oracle*Graphics - Tool grafico per la sintesi dei dati
(charts e grafici)
• Oracle*Book - Tool grafico per lo sviluppo online di documentazione ipertestuale
1
Oracle: Prodotti
• SQL*TextRetrieval and Oracle Context - Una
suite di strumenti e API per la ricerca
bibliografica.
• Programmer/2000 - include Pro * precompilatori
e librerie di procedure e programmi di utilita’ per
il linking ``C' ' , C++, FORTRAN, Java, ADA,
COBOL che garantiscono l’accesso agli Oracle
DB
Oracle: Utilities
• Enterprise Manager - Tool grafico di gestione di
una Base Dati.
• SQL*Loader - Caricatore di dati esternni (ASCII
o binary) in un Oracle DB.
2
Oracle: Connectivity e Middleware
• SQL*Net e Net8 - Driver di comunicazione che
supporta accesso client-server dei tool ad un
Oracle DB
• ORACLE Server - Parte di un DBMS Oracle che
e’ attivo su un database server: riceve richieste da
macchine client e le trasmette all’ Oracle RDBMS
e viceversa.
• Oracle ODBC Drivers - Open DataBase
Connectivity drivers per la connessione dei
database Oracle in accordo con lo standard
ODBC
Core Database Engine
– ORACLE RDBMS
• Oracle Web Applications Server - WWW (HTTP)
Server collegato all’Oracle RDBMS.
• Spatial Data Cartridge (GIS), Video Cartridge
• ConText Cartridge - Provides storage and retrieval
of text documents.
• OLAP Option - On-Line Analytical Processing
• Objects Option (OO features)
– Integrated Data Dictionary.
– SQL e PL/SQL
3
Oracle: Ambienti di sviluppo
• Sviluppo di applicazioni Oracle:
– Oracle RDBMS (o un Oracle RDBMS server),
– uno o piu’ tool di sviluppo.
– Tool di sviluppo esterni (PowerBuilder, Visual Basic
or Java Appl Dev).
• Sviluppo stand-alone (Personal Oracle o Personal
Oracle Lite RDBMS + Oracle Developer)
• Sviluppo Multi-user (in ambiente condiviso):
Oracle RDBMS server su macchina server, clienti
distribuiti su PCs.
PL/SQL: Elementi di Base
• Login
Host String:
per Personal Oracle8
beq-local.
4
PL/SQL: Elementi di Base
• Attivazione
PL/SQL:Obbiettivi
• Inserire, modificare, cercare ed invocare
comandi SQL
• Accedere alle definizioni di tabelle, colonne
e dati
• Formattare, effettuare calcoli, memorizzare
e stampare i risultati di interrogazioni
• Accedere e copiare dati tra Oracle DB
diversi
5
Comando CREATE
CREATE TABLE impiegato
(nome
VARCHAR2(8),
cognome
VARCHAR2(8),
cf
VARCHAR2(9) NOT NULL,
salary
NUMBER(7) NOT NULL,
supercf
VARCHAR2(9),
deptno
NUMBER(1) NOT NULL) ;
Domini, Tipi di Dato
• VARCHAR2
– caratteri , taglia variabile, max=4,000
• NUMBER
– Numerici, NUMBER(precision, scale) con
NUMBER(6,2) in [-999.99, 999.99].
• DATE
– data e ora, TO_DATE(), TO_CHAR().
• RAW - binary data. <=255 char, 1 solo attr
LARGE RAW (<= 2 Gb) per tabella
• LOB, BLOB e CLOB
6
Comando DESCRIBE
SQL> CREATE TABLE imp_dip_1
AS SELECT nome, cognome
FROM impiegato
WHERE deptno = 1 ;
Table created.
SQL> DESCRIBE imp_dip_1
Name
Null?
Type
-------------------------- -------- ---NOME
VARCHAR2(8)
COGNOME
VARCHAR2(2)
Ouput
• Formattazione dell’output
column <nome colonna> <opz 1> opz 2>
• Es.
column desc heading “Descrizione”
7
Formattazione
• FORMAT <formato>
• Formati
– A<n> fissa la ampiezza della colonna a n
caratteri
– 99,999.99 fissa la ampiezza ed i decimali di
un numero
Formattazione
• HEADING <text>
– fornisce il nome <text> per l’intestazione della
colonna
• NULL <text>
– fornisce il default <text> per la stampa dei
valori NULL
8
Formattazione
• COLUMN <nome colonna> CLEAR
– annulla la formattazione vigente sulla
colonna <nome colonna>
Report (0)
CREATE TABLE Prodotto(
Pid
integer,
Descrizione CHAR(120),
Fornitore
CHAR(20),
Costo
integer,
PRIMARY KEY (PId));
9
Report (1)
TTitle 'Tabella dei Prodotti - Esempio di Report'
BTitle 'by R. Basili'
Column PId heading 'CODE' format 999990
Column Descrizione Heading 'Descrizione' format
a20 word_wrapped
Column Fornitore Heading 'Prodotto '
format a10 trunc
Column Costo Heading 'Costo al Forn '
format 999990.99
Break on
Column Pr_Cons Heading 'Prezzo '
format 99999990.99
Report (2)
set pagesize 20
spool Report1.sql
select PID, Descrizione,
Fornitore, Costo,
(Costo * 2.5) as Pr_Cons
from Prodotto
order by Costo, PId;
10
Report (3)
Mer Nov 08
pagina
1
Tabella dei Prodotti - Esempio di Report
CODE
------3
1
Descrizione
-------------------Cravatta Uomo
Scarpe Mocassini
Uomo
2 Scarpe Mocassini
Donna
4 Giacca Uomo
Prodotto
Costo al Forn
Prezzo
---------- -------------- -----------Missoni
30000.00
75000.00
Valleverde
50000.00
125000.00
Valleverde
Armani
60000.00
150000.00
250000.00
625000.00
by R. Basili
PLSQL: Struttura di un blocco
[Header]
[DECLARE
<Costanti>
<Variabili>
<Cursori>
<Gestori di eccezioni/errori> ]
BEGIN
<Istruzioni PL/SQL>
[ EXCEPTIONS
<Gestione eccezioni/errori> ]
END
/
11
PLSQ: Dichiarazioni
DECLARE
Ricavo number (38);
counter number(9) := 0;
ProdID
De
Forn
Cst
Prd
Prodotto.PId%TYPE;
Prodotto.Descrizione%TYPE;
Prodotto.Fornitore%TYPE;
Prodotto.Costo%TYPE;
cname%ROWTYPE;
cursor cname( Thresh Prodotto.Costo%TYPE ) is
select *
from Prodotto
where Costo >= Thresh;
…
BEGIN
commit;
open cname(2000);
counter := 0;
loop
fetch cname into Prd;
exit when cname%NOTFOUND;
ProdId := Prd.PId;
Cst := Prd.Costo;
De := Prd.Descrizione;
Ricavo := Cst * 1.25;
counter := counter + 1;
end loop;
close cname;
END;
/
PLSQL: blocco
12
BEGIN
…
loop
PLSQL: Output
fetch cname into Prd;
exit when cname%NOTFOUND;
ProdId:=Prd.PId; Cst:=Prd.Costo; De:=Prd.Descrizione;
Ricavo := Cst * 1.25;
DBMS_OUTPUT.PUT_LINE('
Il Prodotto: '
|| De
|| ' ha un prezzo di ' || to_char(Ricavo) );
counter := counter + 1;
end loop;
close cname;
DBMS_OUTPUT.PUT_LINE('
Sono stati analizzati '
|| to_char(counter) || ' prodotti ' );
END;
/
Gestione dell’Input
PROMPT Seleziona il dipartimento
ACCEPT dpn NUMBER PROMPT
"Dipartimento n.:"
SELECT nome, cognome, deptno
FROM
impiegati
WHERE deptno = &dpn ;
13
Gestione dell’Input (2)
SQLprompt>
Seleziona il dipartimento
Dipartimento n.: 3
Nome
-------Mario
Massimo
...
COGNOME
DEPTNO
-------- --------ROSSI
3
BIANCHI
3
Gestione dell’Input (3)
PROMPT
ACCEPT
SELECT
FROM
WHERE
Digita Cognome
cgnme PROMPT ”Cognome Impiegato: "
Nome, Cognome, deptno
impiegati
UPPER(cognome) like UPPER('%&cgnme%');
14
Attivazione di un programma PL/SQL
• Dato un programma PL/SQL, memorizzato in un
file PLSQLprog.sql, la sua attivazione e' possibile
mediante il seguente comando SQLplus:
SQLplusPrompt> start PLSQLprog
PLSQL: Cursori Annidati
cursor cname( Thresh Prodotto.Costo%TYPE ) is
select *
from Prodotto
where Costo >= Thresh
ORDER BY Costo;
cursor Tutti_Prodotti is
select *
from Prodotto;
Prd1
cname%ROWTYPE;
Prd2
Tutti_Prodotti%ROWTYPE;
Cost_Diff number(10,2);
15
for Prd in cname(30000)
loop
Cst := Prd.Costo;
if Cst*1.25 > 50000 then
De := Prd.Descrizione;
Ricavo := Cst * 1.25;
ProdId := Prd.PId;
counter2 := 0;
for Prd2 in Tutti_Prod
loop
Cost_Diff := abs(Prd2.Costo - Cst)/Prd2.Costo;
if Cost_Diff <= 0.20 then
counter2 := counter2 + 1;
end if;
end loop; /* su Tutti_Prod */
end if;
counter := counter + 1;
end loop; /* su CNAME() */
PLSQL: Cursori Annidati
(2)
File I/O - Preliminari
FILE init.ora
…
utl_file = c:\Database\datiUtente
utl_file_dir = c:\Database\datiScambio
FILE ProvaFILE.sql
Outdir char(200);
Outfilename char(25);
Outf UTL_FILE.FILE_TYPE;
…
Outdir := 'C:\Documenti\Didattica\BasidiDati\Esempio';
Outfilename := 'Mio.dat';
DBMS_OUTPUT.PUT_LINE ('Trying to open <’ || Outdir ||
'/’ || Outfilename );
Outf := utl_file.fopen(Outdir, Outfilename,'w');
16
PLSQL: File I/O
…
Outf := utl_file.fopen(Outdir, Outfilename,'w');
DBMS_OUTPUT.PUT_LINE ('File Opened !!' );
loop
fetch cname into Prd;
exit when cname%NOTFOUND;
ProdId := Prd.PId;Cst := Prd.Costo;De := Prd.Descrizione;
Ricavo := Cst * 1.25;
utl_file.putf( Outf,
'Il prodotto %s ha un prezzo di %s\n',
trim(De), to_char(Ricavo));
utl_file.new_line(Outf);
counter := counter + 1;
end loop;
close cname;
utl_file.fflush(Outf); utl_file.fclose(Outf);
Triggers
CREATE OR REPLACE TRIGGER check_eta
BEFORE INSERT OR UPDATE ON impiegati
FOR EACH ROW
DECLARE
eta NUMBER;
error_msg CHAR(180);
BEGIN
eta := ( (sysdate - :new.nascita) / 365);
IF (eta < 16) THEN
error_msg := 'Attenzione: '||:new.fname||' '||
:new.lname || ' ha solo ' ||
TO_CHAR(eta, '99.9') || ' anni.';
RAISE_APPLICATION_ERROR ( -20601, error_msg);
END IF;
END;
/
17
Triggers (2)
• Compilazione OK
– trigger memorizzato nello schema utente
• Alcuni errori minori in BEGIN … END
– msg: “Trigger created with compilation errors”.
• Errori importanti (CREATE OR REPLACE TRIGGER)
– trigger e’ respinto e non memorizzato
SQL> SELECT trigger_name, trigger_body
FROM
user_triggers
WHERE trigger_name = 'CHECK_AGE';
Funzioni o Procedure
CREATE OR REPLACE PROCEDURE elimina_da_inventario (
locid_corr IN NUMBER,
prodid_corr IN VARCHAR,
quantita_da_eliminare IN NUMBER) AS
quantita_corr NUMBER;
error_msg CHAR(180);
BEGIN
quantita_corr := 0;
...
END;
/
18
Funzioni o Procedure (1)
BEGIN
quantita_corr := 0;
-- Cerca nella localizzazione
-- SE la quantita' corrente e' non sufficiente
attiva EXCEPTION
-- Altrimenti aggiorna
SELECT
INTO
FROM
WHERE
AND
quant
quantita_corr
inventario
inventario.locationid = locid_corr
inventario.productid = prodid_corr;
Funzioni o Procedure (2)
-- materiale in inventario sufficiente
IF (quantita_corr - quantita_da_eliminare > 0)
THEN
UPDATE inventario
SET
quant = quant - quantita_da_eliminare
WHERE inventario.locationid = locid_corr
AND inventario.productid = prodid_corr;
END IF;
19
Funzioni o Procedure (3)
-- materiale in inventario appena sufficente
IF (quantita_corr - quantita_da_eliminare = 0)
THEN
DELETE FROM inventario
WHERE inventario.locationid = locid_corr
AND inventario.productid = prodid_corr;
END IF;
Funzioni o Procedure (4)
-- poco materiale in inventario
IF (quantita_corr - quantita_da_eliminare < 0) THEN
error_msg := 'ERRORE: Quantita insufficiente !!';
RAISE_APPLICATION_ERROR (-20602, error_msg);
END IF;
20
Funzioni o Procedure (5)
EXCEPTION
-- nessun materiale in inventario
WHEN NO_DATA_FOUND THEN
BEGIN
error_msg := 'ERROR: Prodotto ' ||
prodid_corr ||
' non presente!!';
RAISE_APPLICATION_ERROR (-20603, error_msg);
END; -- fine eccezioni
END;
/
-- fine procedura elimina_da_inventario/3
Invocazione
• EXECUTE elimina_da_inventario(106,'P500', 10)
CREATE OR REPLACE FUNCTION data_nascita
(impid in number)
return date
as nascita
begin
… -- aggiorna nascita
return nascita;
end;
• if ( data_nascita(234)>01-GEN-98 ) then
21