Il 0% ha trovato utile questo documento (0 voti)
3 visualizzazioni

Corso_SQL_oracle

Notes from a Oracle course (italian)
Copyright
© © All Rights Reserved
Formati disponibili
Scarica in formato DOC, PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
3 visualizzazioni

Corso_SQL_oracle

Notes from a Oracle course (italian)
Copyright
© © All Rights Reserved
Formati disponibili
Scarica in formato DOC, PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 38

LEZ.

1: SELECT

Mostra tutta la tabella DEPARTMENTS

SELECT * from DEPARTMENTS;

Mostra solo due colonne della tabella DEPARTMENTS

SELECT department_id, location_id


FROM deparments;

Mostra una colonna a partire da una esistente eseguendo un'operazione aritmetica (mostra
ma non crea!)

SELECT last_name, salary, salary *12


FROM employees;

Creare alias come etichetta di tabella per maggiore leggibilità, prima sintassi base, poi
esempio

SELECT column1 alias1, column2 "alias 2" , column3 alias3


FROM table;

SELECT last_name Name, salary, salary * 12 "Annual Salary"


FROM employees;

Concatenazione. Mostra colonna unica risultato della fusione delle due. Il risultato sarà tutto
attaccato poco leggibile

SELECT last_name || job_id as "Employee Details"


FROM employees;

Concatenazione 2. Usando il termine ' is a' collega le due colonne con risultato DATO1 is a
DATO 2, per es. Carl is a CLERK

SELECT last_name || ' is a ' || job_id as "Employee Details"

DISTINCT per rimuovere duplicati, per esempio per vedere lista di tutti i department dalla
tabella employees che avrebbe di sicuro dei duplicati

SELECT DISTINCT department_id


FROM employees;

Come sopra ma chiedendolo per più di una colonna

SELECT DISTINCT department_id, job_id


FROM employees;

DESCRIBE per vedere struttura tabella. Mostra Nome colonna, se Null, eventuali constraint e
il tipo di dato associato alla colonna
DESCRIBE employees

ALCUNE REGOLE:
SQL non è case sensitive, se si necessita di utilizzare spazi o una dicitura case sensitive, va inserita
tra apici.
Il ; serve a terminare un comando. È necessario nel caso si invii più di un comando insieme,
altrimenti è opzionale.

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

LEZ. 2 : WHERE

Filtra i risultati dove il department_id è 90

SELECT employee_id, last_name,job_id, department_id


FROM employees
WHERE department_id = 90;

Filtrare con un dato alfanumerico o data (usare apici)

SELECT employee_id, last_name, job_id, department_id, hire_date


FROM employees
WHERE last_name = 'Rossi';

SELECT employee_id, last_name, job_id, department_id, hire_date


FROM employees
WHERE hire_date = '20-OCT-2016';

Fitrare con COMPARISON OPERATOR (comparison operator: >,<,=, BETWEEN..AND )

SELECT last_name, salary


FROM employees
WHERE salary >= 3000;

SELECT last_name, salary


FROM employees
WHERE salary BETWEEN 3500 AND 2500;

Comparison operator IN. Cerca solo dipendenti il cui manager ha id in quella lista

SELECT employee_id, last_name, manager_id


FROM employees
WHERE manager_id IN (100,101, 201) ;

Comparison operator LIKE . Comincia per una lettera:

SELECT first_name
FROM employees
WHERE first_name LIKE 'S%'
Comparison operator LIKE . Ha un carattere prima, la seconda lettera è s per es. Assante,
Esposito ecc...

SELECT first_name
FROM employees
WHERE first_name LIKE '_s%'

Comparison operator IS NULL, IS NOT NULL

SELECT last_name, job_id, commission_pct


FROM employees
WHERE commission_pct IS NULL;

Fitrare con LOGICAL OPERATOR

Logical operator AND. Mostra chi è manager e ha un salario > di 10000

SELECT employee_id, last_name,job_id, salary


FROM employees
WHERE salary >= 10000
AND job_id LIKE '%MAN%';
Logical operator OR. Mostra chi ha un salario > di 10000 e/o è un manager

SELECT employee_id, last_name,job_id, salary


FROM employees
WHERE salary >= 10000
OR job_id LIKE '%MAN%';
Logical operator NOT. Mostra solo chi non ha un determinato job_id in una lista

SELECT last_name, job_id


FROM employees
WHERE job_id NOT IN ('IT_PROG', 'ST_CLERK', 'SA_REP');

Rules of precedence: mostra i dipendenti con salario > di 10000 nel department_id 80 oppure i
dipendenti nel department_id 60

SELECT last_name, department_id, salary


FROM employees
WHERE department_id = 60
OR department_id = 80
AND salary > 10000;

Mostra i dipendenti con salario > di 10000 nel department_id 80 o nel department_id 60

SELECT last_name, department_id, salary


FROM employees
WHERE (department_id = 60
OR department_id = 80)
AND salary > 10000;
------------------------------------------------------------------------------------------------------------------------

LEZ. 3: SORTING DATA

Comando ORDER BY

SELECT last_name, job_id, department_id, hire_date


FROM employee
ORDER BY hire_date;

Sopra di default in ordine ascendente, di seguito discendente

SELECT last_name, job_id, department_id, hire_date


FROM employee
ORDER BY hire_date DESC;

Ordinare scrivendo il num di colonna anziché nome. Per es. qui ordina per department_id

SELECT last_name, job_id, department_id, hire_date


FROM employee
ORDER BY 3;

Selezionare le prime N righe, per es. qui 5

SELECT employee_id, first_name


FROM employees
ORDER BY employee_id
FETCH FIRST 5 ROWS ONLY;

Selezionare le successive N righe del comando sopra, per es. sempre 5


SELECT employee_id, first_name
FROM employees
ORDER BY employee_id
OFFSET 5 FETCH FIRST 5 ROWS ONLY;

User input, in questo caso si fa inserire employee_num con & come SUBSTITUTION
VARIABLE per cercare uno specifico employee_id

SELECT employee_id, first_name, last_name


FROM employees
WHERE employee_id = &employee_num ;

Come sopra ma con i caratteri anziché numeri

SELECT last_name, department_id, salary* 12


FROM employees
WHERE job_id = '&job_title' ;

Repeated substitution, per non dover far inserire più volte all' utente stessa variabile; si crea
con doppia &

SELECT employee_id, last_name, job_id, &&column_name


FROM employees
ORDER BY &column_name ;

Per togliere la repeated substitution dopo l'uso, utilizzare UNDEFINE

UNDEFINE column_name;

Si può definire prima della select il valore della substitution variable con il comando DEFINE

DEFINE employee_num;
SELECT employee_id, first_name, last_name
FROM employees
WHERE employee_id = &employee_num ;

Si può rimuovere il DEFINE con UNDEFINE cui sopra o chiudendo SQL DEVELOPER

Verificare i dati inseriti con DEFINE usando SET VERIFY ON

SET VERIFY ON
SELECT employee_id, last_name, salary
FROM employees
WHERE employee_id = &employee_num;

--------------------------------------------------------------------------------------------------------------
LEZ. 4: FUNZIONI COLONNA SINGOLA

* FUNZIONI sui caratteri, CASE-CONVERTION FUNCTIONS

LOWER sul where, cerca direttamente come tutto minuscolo, anche se nel DB non lo è

SELECT employee_id, last_name, salary


FROM employees
WHERE lower(last_name) = 'higgins';

Mostra in UPPERCASE nello schema e cerca con INITCAP (iniziali maiuscole)

SELECT employee_id, UPPER(last_name), salary


FROM employees
WHERE INITCAP(last_name) = 'higgins';

FUNZIONI sui caratteri, CHARACTER-MANIPULATION FUNCTIONS

Esempio con CONCAT in select, cercando i primi 4 caratteri in job_id

SELECT last_name, CONCAT('Job category is ', job_id)"Job"


FROM employees
WHERE SUBSTR(job_id, 4) = 'REP';

Esempio con CONCAT nome e cognome dando nome colonna NAME, con lunghezza
cognome, cerca presenza lettera 'a' nel cognome (nome colonna Contains 'a'), dove il cognome
finisce per 'n'

SELECT employee_id, CONCAT(first_name, last_name) NAME,LENGTH (last_name),


INSTR(last_name, 'a') "Contains 'a'?"
FROM employees
WHERE SUBSTR(last_name, -1, 1) = 'n' ;

NEST SINGLE ROW FUNCTIONS, esempio nesting CONCAT E SUBSTR con UPPER,
eseguendo prima le parentesi interne.
Stampa nome intero concatenato alle prime tre lettere cognome, tutto in maiuscolo.

SELECT first_name, last_name,


UPPER(CONCAT(first_name , SUBSTR(last_name,1,3)))
FROM employees
WHERE department_id = 60;

NUMERIC FUNCTIONS

Testare numeric function come ROUND e TRUNC nella tabella temp DUAL

SELECT ROUND(45.923,2), ROUND(45.923,0), ROUND(455.923, -2)


FROM DUAL;

--Risultato sopra: 45.92 , 45, 500--

SELECT TRUNC(45.923), TRUNC(45.923,2), TRUNC(45.923, -1)


FROM DUAL;

--Risultato sopra: 45, 45.92, 40--

Trovare numeri pari o dispari con MOD

SELECT employee_id as "Even Numbers", last_name


FROM employees
WHERE MOD(employee_id,2) = 0;
------------------------------------------------------------------------------------------------------------------------

LEZ. 5: DATE FUNCTIONS

Formato di default in visualizzazione: DD-Mon-RR, anche se in WHERE scrivo la data in


modo diverso

SELECT last_name, hire_date


FROM employees
WHERE hire_date < '01 FEB 2013';

Vedere la data di sistema (dove è ubicato il db)


SELECT SYSDATE
FROM DUAL;

Vedere la data di sistema nella propria time zone

SELECT SESSIONTIMEZONE, CURRENT_DATE


FROM DUAL;

Fare operazioni aritmetiche sulle date, per esempio per vedere le settimane di lavoro da oggi
alla data assunzione e mostrarlo in colonna weeks

SELECT last_name, (SYSDATE-hire_date)/7 AS WEEKS


FROM employees
WHERE department_id = 90;

DATE MANIPULATION FUNCTIONS, qui di seguito un esempio che ne racchiude alcune


mostrando i mesi tra data assunzione e oggi con nome colonna 'tenure', aggiunge 6 mesi alla
data assunzione e dà nome 'review 'alla colonna, il venerdì seguente alla data assunzione e l'
ultimo giorno del mese del mese di assunzione per gli impiegati da meno di 150 mesi

SELECT employee_id, hire_date, MONTHS_BETWEEN (SYSDATE, hire_date) TENURE,


ADD_MONTHS (hire_date, 6) REVIEW, NEXT_DAY (hire_date, 'FRIDAY'),
LAST_DAY(hire_date)
FROM employees
WHERE MONTHS_BETWEEN (SYSDATE, hire_date) < 150;
Altre funzioni sono ROUND e TRUNCATE:

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

LEZ. 6 : CONVERSION FUNCTIONS

Conversione da data a CHAR con formato da visualizzare specificato in SELECT

SELECT employee_id, TO_CHAR(hire_date, 'MM/YY') Month_Hired


FROM employees
WHERE last_name = 'Higgins';
Esempio simile, la data sarà per es. 15 March 2014

SELECT last_name
TO_CHAR(hire_date, 'fmDD Month YYYY')
AS hire_date
FROM employees;

Seventeenth of June 2011 12:00:00 AM

SELECT last_name
TO_CHAR(hire_date, 'fmDdspth "of" Month YYYY fmHH:MI:SS AM') HIREDATE
FROM employees;

Cerca una hire_date in un formato specifico con corrispondenza esatta (anche per gli spazi
vuoti!)

SELECT last_name, hire_date


FROM employees
WHERE hire_date = TO_DATE("May 24, 2015', 'fxMonth DD, YYYY');

Conversione da number a char TO_CHAR in SELECT, il risultato visualizzato di seguito sarà


per es. $2,500.00

SELECT TO_CHAR(salary, '$99,999.00') SALARY


FROM employees;

Documentazione:https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/
Format-Models.html#GUID-49B32A81-0904-433E-B7FE-51606672183A
------------------------------------------------------------------------------------------------------------------------

LEZ. 7: CONDITIONAL EXPRESSION

NVL permette di mostrare un' espressione alternativa a null: se la prima espr. è null, verrà
mostrata la seconda. Se la prima è non null, verrà mostrata la prima
Nell' esempio si calcola il guadagno annuale incluse le commissioni dove previste, altrimenti si
somma 0

SELECT last_name, salary, NVL(commission_pct, 0),


(salary*12) + (salary*12*NVL(commission_pct, 0)) AN_SAL
FROM employees;

NVL2 se la prima espr. è not null, viene mostrata la seconda. Se la prima espr. è null viene
mostrata la terza.
Nell' esempio viene mostrato nella colonna income se il gudagno dei dipendenti del dep 50 e 80
derivano solo dal salario o salario + commissioni

SELECT last_name, salary, commission_pct,


NVL2(commission_pct, 'SAL+ COMM', 'SAL') income
FROM employees
WHERE department_id IN (50, 80);

NULLIF compara due espressioni, restituisce null se sono uguali.


Nell' esempio si mostra in colonna expr1 e 2 la lunghezza di nome e cognome e poi si
confrontano in result: se lungh. cognome=nome compare null, altrimenti la lunghezza della
prima espr.(cioè il nome)

SELECT first_name, LENGTH(first_name) "expr1",


last_name, LENGTH(last_name) "expr2",
NULLIF(LENGTH(first_name), LENGTH(last_name)) result
FROM employees;

COALESCE restitusce la prima espressione not null nella lista.


Si vuole dare un aumento di 2000$ a chi non riceve commissioni.Se commission_pct è null la
prima espr. dà risultato null e perciò si va alla seconda espr. e si aumenta lo stipendio di
2000$. Se commission_pct è not null allora la prima espr. è not null e viene mostrata

SELECT last_name, salary, commission_pct,


COALESCE((salary+(commission_pct*salary)), salary+2000)"New Salary"
FROM employees;

IF-THEN-ELSE LOGIC: CASE EXPRESSION e DECODE FUNCTION

Si vuole aumentare lo stipendio per alcune categorie di dipendenti del 10, 15 o 20% in base al
ruolo; per le altre il salario rimane lo stesso. Risultato mostrato nella colonna
REVISED_SALARY

SELECT last_name, job_id, salary,


CASE job_id WHEN 'IT-PROG' THEN 1.10*salary
WHEN 'ST_CLERK' THEN 1.15*salary
WHEN 'SA_REP' THEN 1.20*salary
ELSE salary END "REVISED_SALARY"
FROM employees;

Si categorizza lo stipendio in base al suo ammontare. Se non è presente nelle varie fasce, allora
è eccellente

SELECT last_name, salary,


(CASE job_id WHEN salary<5000 THEN 'Low'
WHEN salary<10000 THEN 'Medium'
WHEN salary<20000 THEN 'Good'
ELSE 'Excellent'
END) qualified_salary
FROM employees;

Il primo esempio si può fare anche con la funzione DECODE, che è specifica della sintassi
Oracle

SELECT last_name, job_id, salary,


DECODE(job_id, 'IT-PROG', 1.10*salary,
'ST_CLERK', 1.15*salary,
'SA_REP', 1.20*salary,
salary)
REVISED_SALARY
FROM employees;
Esempio fine anno finanziario e si vuole mostrare le tasse applicabili sullo stipendio dei
dipendenti del dep 80 in base al range salary/2000 con 0 cifre decimali

SELECT last_name, salary,


DECODE (TRUNC(salary/2000, 0),
0, 0.00,
1, 0.09,
2, 0.20,
3, 0.30,
4, 0.40,
5, 0.42,
6, 0.44,
0.45) TAX_RATE
FROM employees
WHERE department_id = 80;

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

LEZ.8: FUNZIONI DI GRUPPO

Esempio con media, massimo, minimo e somma. Si può anche aggiungere DISTINCT prima
della colonna per togliere duplicati, se serve

SELECT AVG(salary), MAX(salary),


MIN(salary), SUM(salary)
FROM employees
WHERE job_id LIKE '%REP%';

Documentazione:https://docs.oracle.com/cd/E11882_01/server.112/e41084/
functions003.htm#SQLRF20035

COUNT. Sapere il numero di dipendenti nel dep. 80 che guadagna delle commissioni
SELECT COUNT(commission_pct)
FROM employees
WHERE department_id = 80;

Genera report con il numero di dipartimenti che hanno almeno un impiegato, quindi
escludendo quelli che non ne hanno (COUNT e DISTINCT)

SELECT COUNT(DISTINCT department_id)


FROM employees;

Le funzioni di gruppo IGNORANO I VALORI NULL. Per inserirli, usare NVL. Nell'
esempio, nel conteggio i null sono 0 e partecipano alla media. Senza NVL è 0.2125, con 0.0425

SELECT AVG(NVL(commission_pct, 0))


FROM employees;

Clausola GROUP BY: calcolare la media del salario per ogni dipartimento, ovvero la media di
tutti i salari nel gruppo specificato nella clausola GROUP BY

SELECT department_id, AVG(salary)


FROM employees
GROUP BY department_id;

Visualizzare risultati di gruppi all' interno di altri gruppi. Nell' esempio,prima si divide per
department_id poi ogni gruppo per job_id, quindi vedremo la somma dei salari di ogni
dipartimento per ogni tipo di lavoro (per es dep 110, AC_ACCOUNT, 8300)

SELECT department_id, job_id, sum(salary)


FROM employees
GROUP BY department_id, job_id;

CLAUSOLE GROUP BY:


1) Tutte le colonne presenti nella lista select che non sono nella funzione di gruppo, devono essere
incluse nella clausola group by;
2) Usando where si possono escludere righe prima di dividerle in gruppi;
3) Non si possono usare alias di colonna nella clausola group by.

Restringere gruppi che sono risultato del group by: HAVING clause (simile a WHERE ma di
gruppo)
Nell' esempio, si vuole trovare il salario massimo in ciascun dipartimento. Il salario massimo
deve essere > 10.000. Bisogna quindi trovare il max sal di ogni dep. raggruppando ogni
department_id con group by, e poi restringere i gruppi a chi ha come max sal > 10.000

SELECT department_id, MAX(salary)


FROM employees
GROUP BY department_id
HAVING MAX(salary) > 10.000;

ANNIDARE FUNZIONI DI GRUPPO. Nell' esempio di calcola il salario medio per ogni
dipartimento e si mostra il salario medio massimo. La clausola GROUP BY è obbligatoria con
le funzioni di gruppo annidate.

SELECT MAX(AVG(salary))
FROM employees
GROUP BY department_id;

NOTA BENE: chiedere a Ugo come mai dopo SELECT non c'è department_id

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

LEZ. 9: OTTENERE RISULTATI DA PIÙ TABELLE: JOIN

NATURAL JOIN (EQUIJOIN)

Nell' esempio si vuole ottenere le informazioni di tutti i dipendenti (employee_id) dei loro
lavori (job_id e job_title) che però sono in due tabelle diverse cioè employees e jobs. Si usa la
colonna job_id, l' unica in comune, per unire le due tabelle

SELECT employee_id, first_name, last_name, job_title


FROM employees NATURAL JOIN jobs;
CLAUSOLA USING. Nell' es. si vuole trovare i nomi dei dipartimenti dove lavora ciascun
impiegato; le tabelle hanno due colonne in comune ma a noi interessa solo department_id

SELECT employee_id, last_name,


department_name, department_id
FROM employees JOIN deparments
USING (department_id);

PREFISSI DI TABELLA per risolvere l'ambiguità di della colonna comune a più tabelle e
velocizzare l'esecuzione. Non si può usare nella clausola WHERE se la colonna è stata prima
usata in USING. Si ottiene con letteraTabella.nomeColonna come nell' esempio sotto

SELECT l.city, d.department_name, d.manager_id


FROM location l JOIN departments d
USING (location_id)
WHERE location_id = 1400;

N.B.: non si può quindi fare WHERE l.location_id!!

Si può usare la clausola ON anziché USING, così si possono specificare le colonne da unire

SELECT e.employee_id, e.last_name, e.department_id,


d.department_id, d.location_id
FROM employees e JOIN departments d
ON (e.department_id = d.department_id);

THREE-WAY JOIN, JOIN di tre tabelle. Nell' es. report di tutti i dipendenti, i loro
dipartimenti e le cità dove sono localizzati.

SELECT employee_id, city, department_name


FROM employee e JOIN departments d
ON d.department_id = e.department_id
JOIN locations l
ON d.location_id = l.location_id;

Come sopra ma con USING

SELECT e.employee_id, l.city, d.department_name


FROM employee e JOIN deparments d
USING (department_id)
JOIN locations l
USING (location_id);

AND clause: report delle location_id di tutti i dipendenti sotto il manager_id 149

SELECT e.employee_id, e.last_name, e.department_id,


d.department_id, d.location_id
FROM employees e JOIN departments d
ON (e.department_id = d.department_id)
AND e.manager_id = 149;

Come sopra, stesso risultato con WHERE


SELECT e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
FROM employees e JOIN departments d
ON (e.department_id = d.department_id)
WHERE e.manager_id = 149;

-----------------------------------------------------------------------------------------
LEZ. 10: SELF JOINS, OUTER JOINS, CROSS JOINS

SELF JOIN Nell'esempio si vuole sapere il nome del manager di ogni dipendente.Nella tabella
employees si sa il manager_id che corrisponde all' employee_id del manager. Si cerca quindi
prima per ogni employee_id il corrispondente manager_id, poi si cerca il manager_id come
employee_id, con relativo last_name. Worker e manager sono alias di tabella

SELECT worker.last_name emp, manager.last_name manager


FROM employees worker JOIN employees manager
ON (worker.manager_id = manager.employee_id);

Simile a sopra, preso dalla doc oracle https://docs.oracle.com/en/database/oracle/oracle-


database/19/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__I2066611

SELECT e1.last_name||' works for '||e2.last_name


"Employees and Their Managers"
FROM employees e1, employees e2
WHERE e1.manager_id = e2.employee_id
AND e1.last_name LIKE 'R%'
ORDER BY e1.last_name;

/* risultato:
Employees and Their Managers
-
Rajs works for Mourgos
Raphaely works for King
Rogers works for Kaufling
Russell works for King
*/

NONEQUIJOIN l' operatore utilizzato non è = (per es. employee_id di manager e employee).
Nell'esempio si vuole sapere il livello di lavoro di ciascun dipendente (dato dal suo salario) da
tabella employees e job_grades. In job grades ci sono range di stipendio LOWEST_SAL E
HIGHEST_SAL

SELECT e.last_name, e.salary, j.grade_level


FROM employees e JOIN job_grades j
ON e.salary
BETWEEN j.lowest_sal AND j.hi ghest_sal;

OUTER JOIN permette di mostrare quei risultati non visibili in equijoin in quanto non hanno
un valore assegnato (per es. un dipartimento senza dipendenti o viceversa)
LEFT OUTER JOIN mostra tutte le righe che soddisfano una data condizione e le righe che
non hanno corrispondenza nella tabella a sinistra
Nell' es. si vuole mostrare tutte le informazioni dei dipendenti e i loro dipartimenti
indipendentemente dal fatto che un dipendente sia assegnato o meno a un dipartimento.
Grant non appartiene a nessun dep. quindi ha null in department_id e department_name

SELECT e.last_name, e.department_id, d.department_name


FROM employees e LEFT OUTER JOIN departments d
ON (e.department_id = d.department_id);

RIGHT OUTER JOIN mostra tutte le righe che soddisfano una data condizione e le righe che
non hanno corrispondenza nella tabella a destra.
Nell' es. si vuole mostrare tutte le informazioni dei dipendenti e i loro dipartimenti
indipendentemente dal fatto che un dipartimento abbia o meno almeno un impiegato. il
dipartimento 190 non ha dipendenti e mostra null alla colonna last_name

SELECT e.last_name, e.department_id, d.department_name


FROM employees e RIGHT OUTER JOIN departments d
ON (e.department_id = d.department_id);

FULL OUTER JOIN mostra tutte le righe che soddisfano una data condizione e anche quelle
che non lo fanno, unendo LEFT e OUTER JOIN
Nell' esempio otterremo sia i dipartimenti con null in last_name perché non hanno dipendenti,
che null in department_id e _name dove un dipendente non è stato assegnato a un
dipartimento.

SELECT e.last_name, e.department_id, d.department_name


FROM employees e FULL OUTER JOIN departments d
ON (e.department_id = d.department_id);

CROSS JOIN nei casi dove si fa una join senza porre una condizione, viene creata una tabella
che è un prodotto cartesiano, ovvero a ogni riga di una tabella viene assegnata ciascuna riga
dell' altra. Raramente utile.
Nell' esempio si uniscono tutte le 20 righe dei dipendenti con tutte le 8 righe dei dipartimenti,
creando una tabella di 160 righe.

SELECT last_name, department_name


FROM employees
CROSS JOIN departments;

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

LEZ. 11: SUBQUERY


SINGLE-ROW SUBQUERY Query che restituiscono un singolo valore per ciascuna subquery
Nell'es. report di tutti i dipendenti assunti dopo Davies (query principale), non sapendo la
data di assunzione di quest'ultimo (subquery)

SELECT last_name, hire_date


FROM employees
WHERE hire_date > (SELECT hire_date
FROM employees
WHERE last_name = 'Davies');

Report di tutti i dipendenti che hanno lo stesso impiego di Taylor e che hanno uno stipendio
maggiore di Taylor

SELECT last_name, job_id, salary


FROM employees
WHERE job_id = (SELECT job_id
FROM employees
WHERE last_name = 'Taylor')
AND salary > (SELECT salary
FROM employees
WHERE last_name = 'Taylor');

Utilizzo di funzioni di gruppo sulle single-row subquery. Nell' esempio mostra il dipendente
pagato meno di tutti

SELECT last_name, job_id, salary


FROM employees
WHERE salary = (SELECT MIN(salary)
FROM employees);

Subquery con HAVING clause. Nell' esempio lista di tutti i dip. che hanno salario minimo
maggiore rispetto al salario minimo del dip. 50

SELECT department_id, MIN(salary)


FROM employees
GROUP BY department_id
HAVING MIN(salary) > (SELECT MIN(salary)
FROM employees
WHERE department_id = 50);

Single-Row con due tabelle. Si vuole mostrare tutti i dipendenti che sono architetti. Se non ce
ne sono, la subquery dà risultato null e la query principale quando fa il confronto restituisce
null e quindi riga vuota (anche se in employees ci fosse un job_id null, perché il paragone di
due null dà null

SELECT last_name, job_id


FROM employees
WHERE job_id = (SELECT job_id
FROM jobs
WHERE job_title = 'Architect');
----------------------------------------------------------------------------------------------------------------

LEZ. 12: MULTIPLE-ROW/COLUMN SUBQUERY

Le MULTIPLE-ROW SUBQUERY restituiscono più valori (righe) come risultato.


Nell' esempio si vuole mostrare i dipendenti con il salario = al salario minimo di ogni dip. Nel
WHERE va messo IN (che si aspetta uno o più risultati),come segue, e non = (che è un
operatore single row, quindi si aspetta un solo risultato)

SELECT employee_id, last_name


FROM employees
WHERE salary IN (SELECT MIN(salary)
FROM employees
GROUP BY department_id);

Report di tutti i dipendenti non IT Programmers e con il salario minore di qualsiasi IT


Programmers. < ANY significa meno del massimo, > ANY più del minimo

SELECT employee_id, last_name, job_id, salary


FROM employees
WHERE salary < ANY (SELECT salary
FROM employees
WHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';

Report di tutti i dipendenti non IT Programmers e con il salario inferiore dal minimo
guadagnato da IT Programmers. > ALL più che il massimo, < ALL meno che del minimo

SELECT employee_id, last_name, job_id, salary


FROM employees
WHERE salary < ALL (SELECT salary
FROM employees
WHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';

N.B. l' operatore NOT può essere usato con IN, ANY e ALL

MULTIPLE-COLUMN SUBQUERY la subquery restituisce come risultato più di una


colonna.
Nell' esempio, si crea un report di tutti i dipendenti con il salario minimo per ciascun
dipartimento

SELECT first_name, department_id, salary


FROM employees
WHERE (salary, department_id) IN
(SELECT MIN(salary), department_id
FROM employees
GROUP BY department_id)
ORDER BY department_id;

NOT IN operator, equivalente di <> ALL. Non va usato se si sospetta che possa esserci un
valore null nella subquery, in tal caso avremmo una colonna vuota (vedere single-row con due
tabelle per spiegazione).
Nell' esempio vogliamo vedere tutti i dipendenti che non sono manager. Potremmo avere
valori null quindi si aggiunge nella subquery WHERE... IS NOT NULL come sotto

SELECT last_name FROM employees


WHERE employee_id NOT IN (SELECT manager_id
FROM employees
WHERE manager_id IS NOT NULL);
Modo sbagliato di scrivere query sopra, darebbe tabella vuota per valori null

SELECT emp.last_name
FROM employees emp
WHERE emp.employee_id NOT IN (SELECT manager_id
FROM employees mgr);

Mostrare tutti i dipendenti che sono manager. Usando l' operatore IN non ci sono problemi
con i valori null perché è equivalente di =ANY

SELECT emp.last_name
FROM employees emp
WHERE emp.employee_id IN (SELECT manager_id
FROM employees mgr);

---------------------------------------------------------------------------------------------------------------
LEZ. 13: INSERT

Inserire un record alla volta, nell' esempio un nuovo dip. Se non si specificano le colonne,
bisogna mantenere l'ordine di default della tab nella parte VALUES

INSERT INTO departments(department_id,department_name, manager_id, location_id)


VALUES (70, 'Public Relations', 100, 1700);

Inserire valori NULL se non si conoscono, per aggiornarli dopo con update. Prima sincerarsi i
campi non siano NOT NULL con DESCRIBE nomeTabella. Se possono essere null basta non
dichiarare e aggiornare le colonne dal dato sconosciuto(metodo implicito)

INSERT INTO departments (department_id, department_name)


VALUES (30, 'Purchasing');

Come sopra, ma inserendo NULL in VALUES (metodo esplicito)

INSERT INTO departments


VALUES (100, 'Finance', NULL, NULL);

È possibile inserire SYSDATE come data e USER per inserire l' username in utilizzo.
Nell'esempio (ridotto) di seguito, utilizzo di SYSDATE. N.B. inseritO [...] per i dati non di
interesse, per brevità di esempio

INSERT INTO employees ([...], hire_date, [...])


VALUES ([...], SYSDATE, [...]);

INSERIRE PIÙ RIGHE:


1) Metodo con SUBSTITUION VARIABLE: chiede all' utente di inserire le variabili ogni
volta che si esegue la query, senza scrivere ogni volta una query INSERT

INSERT INTO departments (department_id, department_name, location_id)


VALUES (&department_id, '&department_name', &location);
2) PRENDENDO DATI DA UN'ALTRA TABELLA CON UNA SUBQUERY Esempio
inserendo nella tabella separata di rappresentanti alle vendite sales_reps copiando le righe
dalla tabella employees con tutti i dipendenti. Num di colonne e tipo di data della clausola

INSERT devono coincidere con quelle della subquery (SELECT)


INSERT INTO sales_reps(id, name, salary, commission_pct)
SELECT employee_id, last_name, salary, commission_pct
FROM employees
WHERE job_id LIKE '%REP%';

N.B.: testare query sopra o chiedere come mai manca VALUES prima della subquery

3)COPIA ESATTA di una tabella su un'altra già esistente (per es. per un backup)

INSERT INTO copy_emp


SELECT *
FROM employees;

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

LEZ. 14: Modificare dati in una tabella: UPDATE e DELETE

UPDATE: Nell' es. si spostano dei dipendenti dal dipartimento 60 all' 80. Importante la
clausola WHERE, se omessa viene cambiato a 80 il dipartimento per tutti

UPDATE employees
SET department_id = 80
WHERE department_id = 60;

Altro esempio, dipendente che cambia mansione da SA_REP a IT_PROG

UPDATE employees
SET job_id = 'IT_PROG', commission_pct = NULL
WHERE employee_id = 113;

UPDATE con SUBQUERY si vuole aggiornare job_id e salario del dipendente 103 con quelli
del 205, senza conoscere job_id e salario di quest'ultimo

UPDATE employees
SET (job_id, salary) = (SELECT job_id, salary
FROM employees
WHERE employee_id = 205)
WHERE employee_id = 103;

Come sopra funziona anche prendendo i dati da un'altra tabella

UPDATE copy_emp
SET department_id = (SELECT department_id
FROM employees
WHERE employee_id = 100)
WHERE job_id = (SELECT job_id
FROM employees
WHERE employee_id = 200);

DELETE per rimuovere righe da una tabella. Nell' esempio si vuole togliere il dipartimento
'Contracting'

DELETE FROM departments


WHERE department_name = 'Contracting';

Rimuovere tutte le righe di una tabella: basta omettere la clausola WHERE

DELETE from copy_emp;

Rimuovere righe con una SUBQUERY. Nell' esempio si vogliono cancellare da employees i
dipendenti del dipartimento che ha un nome che contiene Public nella tabella departments
(colonna department_id in comune)

DELETE FROM employees


WHERE department_id IN
(SELECT department_id
FROM departments
WHERE department_name LIKE '%Public%');

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

LEZ. 15: CREARE TABELLE

Creare tabella dept definendo nome colonna e corrispettivo data type. Si utilizza anche l'
espressione DEFAULT per create_date, che viene inserita se non viene specificata
diversamente dall' utente in fase di inserimento dati

CREATE TABLE dept


(deptno NUMBER(2),
dname VARCHAR2(14),
loc VARCHAR2(13),
create_date DATE DEFAULT SYSDATE);

DESCRIBE per verificare la corretta creazione della tabella (vedere lez.1 SELECT)

DESCRIBE dept
Inserire dei vincoli (CONSTRAINTS) a livello di colonna o tabella in fase creazione tabella o dopo
la sua creazione, come ad esempio NOT NULL dove serve che ci sia sempre un dato inserito (nell'
es. sopra potrebbe essere deptno). NOT NULL è solo a livello di colonna. È buona norma attribuire
un nome al vincolo, anziché lasciare che oracle ne crei uno di dafault. I vincoli sono inseriti tutti nel
data dictionary. Verranno spiegati nella lezione sotto

-------------------------------------------------------------------------------------------------------------------
LEZ. 16: CREATE TABLE CONSTRAINT

Definizione della Primary Key creando la tabella dept2 a livello di colonna. La primary key è
inoltre NOT NULL e deve essere una sola in tutta la tabella

CREATE TABLE dept2


(deptno NUMBER(2) CONSTRAINT dept_id_pk PRIMARY KEY,
dname VARCHAR2(14),
loc VARCHAR2(13),
create_date DATE DEFAULT SYSDATE);

Definizione della Primary Key creando la tabella dept2 a livello di tabella

CREATE TABLE dept


(deptno NUMBER(2),
dname VARCHAR2(14),
loc VARCHAR2(13),
create_date DATE DEFAULT SYSDATE
CONSTRAINT dept_id_pk PRIMARY KEY (deptno));

La FOREIGN KEY collega una colonna a un'altra della stessa o altra tabella. Se provo a inserire
un dato nella tabella1 colonna1 con la foreign key che non è presente nella tabella2 colonna2
collegata, avrò un errore. Può essere definita a livello di tabella o a livello di colonna. Non si può
cancellare una riga ricercandola per colonna con foreign key (nell' es. department_id) se ci sono dati
al suo interno. Se per es. provo a cancellare un department_id senza dipendenti, funzionerà. Se ci
sono dipendenti, invece darà errore.

CHECK controlla che non venga inserito un dato che non rispetta un certo vincolo, per es. salary
>0

NOT NULL come da nome, forza l' inserimento di un dato

UNIQUE impone che quel dato non abbia un duplicato nella colonna o colonne specificate. Utile
per es. in email o num tel personale

ESEMPIO con tutti i vincoli sopra spiegati:

CREATE TABLE teach_emp(


employee_id NUMBER(6)
CONSTRAINT teach_emp_id_pk PRIMARY KEY,
last_name VARCHAR2(25) NOT NULL,
email VARCHAR2(25),
salary NUMBER(8,2)
CONSTRAINT empl_salary_min
CHECK (salary > 0),
commission_pct NUMBER(2,2),
hire_date DATE NOT NULL,
department_id NUMBER(4),
CONSTRAINT empl_dept_fk FOREIGN KEY (department_id)
REFERENCES departments(department_id),
CONSTRAINT empl_email_uk UNIQUE(email));
Come sopra ma con Foreign Key a livello colonna
CREATE TABLE teach_emp(
employee_id NUMBER(6)
CONSTRAINT teach_emp_id_pk PRIMARY KEY,
last_name VARCHAR2(25) NOT NULL,
email VARCHAR2(25),
salary NUMBER(8,2)
CONSTRAINT empl_salary_min
CHECK (salary > 0),
commission_pct NUMBER(2,2),
hire_date DATE NOT NULL,
department_id NUMBER(4) CONSTRAINT empl_deptid_fk
REFERENCES departments(department_id),
CONSTRAINT empl_email_uk UNIQUE(email));

CREARE TABELLA CON SUBQUERY. Nell' esempio si crea una tabella separata per i
SA_REP a partire da employees. Si ereditano i vincoli NOT NULL, ma non altri vincoli e la
primary key non ha il vincolo NOT NULL implicito

CREATE TABLE dept80 AS


SELECT employee_id, last_name, salary *12 ANNSAL, hire_date
FROM employees
WHERE department_id = 80;

Si possono inserire vincoli nella definizione delle colonne

CREATE TABLE dept80_copy(emp_id PRIMARY KEY, name, ANNSAL, DOJ) AS


SELECT employee_id, last_name, salary *12, hire_date
FROM employees
WHERE department_id = 80;

N.B. è necessario inserire un alias di colonna dove c'è un'espressione (qui salary*12 ANNSAL),
altrimenti avremo un errore.

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

LEZ. 17: ALTER TABLE: DDL STATEMENTS

ADD per aggiungere una colonna. Il valore è "null" almeno che non si inserisca un valore
default

ALTER TABLE dept80


ADD (job_id VARCHAR(9));

Come sopra, con valore di default inserito

ALTER TABLE dept80


ADD (job_id VARCHAR(9) DEFAULT 'Undefined');

MODIFY per modificare le caratteristiche di una colonna, nell'esempio si porta il limite di


last_name da 25 a 30. È possibile modificare anche datatype e valore di default
ALTER TABLE dept80
MODIFY (last_name VARCHAR(30));

DROP per cancellare una colonna. Non si può fare se è una primary key, almeno che non sia
stata attivata la funzione 'cascade'

ALTER TABLE dept80


DROP (job_id);

Come sopra con CASCADE,cancella anche se è una primary key. Cancella anche le colonne
che vi fanno riferimento

ALTER TABLE dept80


DROP (job_id) CASCADE CONSTRAINTS;

UNUSED per cancellare successivamente una colonna con molti dati, dove la cancellazione
richiederebbe molto tempo, una volta scollegati gli utenti

ALTER TABLE dept80


SET UNUSED (job_id);

Dopo UNUSED la colonna si cancella così:

ALTER TABLE dept80


DROP UNUSED COLUMNS;

N.B. cerca/chiedi se non è uguale aspettare che non ci siano utenti e basta, qual'è il vantaggio
effettivo di unused

READ ONLY per mettere la tabella in sola lettura ed evitare che un utente inserisca dei dati
mentre si eseguono query DDL. In questa modalità si può solo eseguire DROP, QUERY,
RENAME e MOVE

ALTER TABLE dept80 READ ONLY;

Dopo rimettere in READ WRITE

ALTER TABLE dept80 READ WRITE;

RENAME per rinominare una tabella, nell' esempio da dept80 a sales_emp

RENAME dept80 to sales_emp;

DROP TABLE per cancellare una tabella. Si cancellano i dati ma non lo spazio utilizzato.

DROP TABLE dept80;

PURGE per rimuove completamente una tabella dal DB e liberare lo spazio

DROP TABLE dept80 PURGE;


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

LEZ. 18: TRANSACTIONS:DML STATEMENTS

Una transazione comincia con un SELECT/UPDATE/DELETE e termina quando viene


eseguito un COMMIT/ROLLBACK, o viene eseguito un comando DDL (il commit è
automatico per quei comandi), o viene chiuso l' editor sql oppure il sistema va in crash.

COMMIT chiude la transazione corrente e rende le modifiche permanenti.

SAVEPOINT permette di creare dei punti dove tornare indietro con un rollback.

ROLLBACK chiude la transazione corrente annullando tutte le modifiche in coda, ROLLBACK


TO SAVEPOINT torna al savepoint annullando le modifiche fino a quel punto.

Esempio di SAVEPOINT e ROLLBACK to SAVEPOINT, impostando un savepoint di nome


save_1 e COMMIT finale per confermare le modifiche

[...query precedenti...]
SAVEPOINT save_1;
[... query da cancellare...]
ROLLBACK to save_1;
[...query corrette...]
COMMIT;

----------------------------------------------------------------------------------------------------------------------
LEZ. 19: UTENTI e PRIVILEGI

DOC
ORACLE:https://docs.oracle.com/database/121/SQLRF/statements_9014.htm#SQLRF01603

SYSTEM PRIVILEGE:

CREATE USER per creare un user come DBA (DataBase Administrator).


Nell' esempio si crea un utente demo che deve loggarsi con la password, in questo caso
demo_pwd. L' utente al momento non ha privilegi, gli vanno assegnati dopo.

CREATE USER demo


IDENTIFIED BY demo_pwd;

GRANT per assegnare privilegi di sistema a un utente (vedere schermata


"System_Privilege"), in questo es. si riprende l' utente demo. Se voglio assegnarlo a tutti gli
utenti, invece di demo scrivo PUBLIC

GRANT create session, create table, create sequence, create view


TO demo;
ROLE è un set predefinito di privilegi che posso assegnare/revocare ad un user, utile per
modifiche su gruppi o sulla totalità di utenti, anziché farne uno per uno. Vedere esempio di
seguito sul singolo utente demo
--Crea un ruolo--
CREATE ROLE manager;
--Assegna i privilegi al ruolo--
GRANT create table, create view TO manager;
--Assegna il ruolo all' user--
GRANT manager TO demo;

ALTER USER per modificare la password.Nell'esempio, l' user demo cambia la sua password
in 12345. Lo può fare se ha il privilegio "alter user"

ALTER USER demo


IDENTIFIED BY 12345;

OBJECT PRIVILEGE attribuire a un utente la possibilità di accedere ed eseguire query su


un oggetto come una tabella specifica. Si può fare se si è il proprietario dell' oggetto, l'oggetto
è nel proprio schema, se si è DBA o se siamo stati abilitati con WITH GRANT OPTIONS
Nell' esempio si attribuisce all' utente demo il privilegio di fare select sulla tabella employees e
di poter attribuire lo stesso privilegio ad altri utenti (WITH GRANT OPTION).Per attribuire
a tutti, al posto di TO demo, scrivere TO PUBLIC

GRANT select
ON employees
TO demo
WITH GRANT OPTION;

Nell' esempio si dà il privilegio update su alcune colonne di departments sia all' utente demo
che al ruolo manager

GRANT update (department_name, location_id)


ON departments
TO demo, manager;

REVOKE per rimuovere privilegi ad altri utenti, nell' esempio il privilegio select su
employees per l' utente demo. Se demo ha dato il privilegio ad altri utenti, anche per loro
viene revocato.
REVOKE select
ON employees
FROM demo;

In fondo, dopo FROM ... si può aggiungere CASCADE CONSTRAINTS,che serve per
rimuovere ogni vincolo di integrità referenziale creato nell' oggetto con il privilegio
REFERENCES.
Un REFERENCE privilege è un object privilege che permette a utente di definire un vincolo di
integrità referenziale:è necessario per definire una Foreign Key

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

LEZ. 20: DATA DICTIONARY

Il data dictionary è un set di viste solo lettura che permette, tramite query, di vedere varie
informazioni sui vari oggetti, come proprietari, user, vincoli ecc.. Una vista è una tabella logica
basata su una o più tabelle.

Vista DICTIONARY contiene nome e descrizione breve di ogni vista del data dictionary alle
quali si ha accesso. Per vederle tutte, bisogna avere il privilegio SELECT ANY DICTIONARY
Per visualizzare come è fatta la vista, è utile usare DESCRIBE, anche per le prossime viste
come USER_TABLE ecc

DESCRIBE dictionary;

Nell' esempio si chiede di visulizzare nome ed eventuali commenti sulla tabella


'USER_OBJECTS'

SELECT *
FROM dictionary
WHERE table_name = 'USER_OBJECTS';

USER_TABLE per accedere alle informazioni di tutte le proprie tabelle; nell' esempio si vuole
sapere il nome di tutte le proprie tabelle

SELECT table_name
FROM user_tables;

ALL_TABLES per vedere una lista di tutte le tabelle alle quali si ha accesso

USER_TAB_COLUMNS mostra i nomi di colonna, data type, lunghezza dei dati dove ci sono
null ecc.. delle proprie tabelle (https://docs.oracle.com/database/121/REFRN/GUID-
F218205C-7D76-4A83-8691-BFD2AD372B63.htm#REFRN20277 )

Nell' esempio una query per visualizzare alcune informazioni sulle colonne della propria
tabella employees (simile all' output del comando DESCRIBE)

SELECT column_name, data_type, data_length, data_precision, data_scale, nullable


FROM user_tab_columns
WHERE table_name = 'EMPLOYEES';

USER_CONSTRAINTS per vedere i tipi di constraint creati nelle proprie tabelle.


Vedere https://docs.oracle.com/database/121/REFRN/GUID-9C96DA92-CFE0-4A3F-9061-
C5ED17B43EFE.htm#REFRN20047

Nell' esempio si vedono alcune informazioni su tutti i vincoli creati per la tabella employees.
r_constraint_name è il nome dell' unico vincolo al quale fa riferimento la foreign key, e deletion
rule è la regola per la cancellazione della foreign key : CASCADE quando il record padre
viene cancellato, viene cancellato anche il figlio, SET NULL il figlio viene impostato come
NULL anziché cancellato, NO ACTION il record padre può essere cancellato solo se non c'è
un record figlio.
Constraint_type può essere c per "check constraint on a table” o NOT NULL, P primary key,
U unique key, R referencial integrity

SELECT constraint_name, constraint_type, search_condition, r_constraint_name, delete_rule,


status
FROM user_constraints
WHERE table_name = ' EMPLOYEES';

USER_CONS_COLUMNS per sapere informazioni sulle colonne alle quali si applica un


vincolo, come nome della tabella, proprietario, nome della colonna, nome del vincolo,
propierario e posizione della colonna o attributo nella definizione dell' oggetto
Nell' esempio si mostra il nome del vincolo e il nome della colonna (o colonne) al quale si
applica per la tabella employees

SELECT constraint_name, column_name


FROM user_cons_columns
WHERE table_name = 'EMPLOYEES';

COMMENT statements per inserire una breve descrizione di max 4000 caratteri della tabella
e/o delle sue colonne per una migliore manutenzione e lavoro in team
COMMENT ON TABLE employees
IS 'Employee Information';

COMMENT ON COLUMN employees.first_name


IS 'First name of the employee';

Per vedere i commenti delle tabelle/colonne ci sono diverse query, vedere immagine
View_Comment
Nell' esempio si usa USER_TAB_COMMENTS per vedere i commenti di tutte le proprie
tabelle

SELECT *
FROM user_tab_comments;

Potrebbero piacerti anche