Query Nidificate
Una “subquery” è una query inclusa in un’altra, ovveroun’interrogazione all’interno di altre interrogazioni.
Una subquery ritorna dei dati (tabelle o dati singoli) necessari all’esecuzione di query ad un livello più alto.
Una query situata a un livello più basso rispetto ad un’altra viene definita “child”,
al contrario la query situata ad un livello più alto rispetto alla child viene definita “parent”.
Le subquery possono essere usate sia nella clausola FROM sia nella clausola WHERE di una SELECT.
In quest’ultimo caso si parla di query nidificate e possiamo avere al massimo 255 livelli di nidificazione (“strati” di interrogazione).
Subquery a riga singola
Hanno la particolarità di restituire sempre una sola riga di dati.
ESEMPIO
Cerchiamo l’impiegato (tabella employees) con lo stipendio più alto.
SELECT last_name AS cognome, first_name AS nome, salary AS salario
FROM employees
WHERE salary = (SELECT MAX (salary) FROM employees);
-
La child query (2° livello) ritorna il massimo valore della colonna “salary” della tabella “employees”
-
La parent query (1° livello) cerca gli impiegati il cui salario corrisponde al valore restituito dalla child query.
RISULTATO
EMPLOYEES
ESEMPIO
Visualizziamo gli impiegati che lavorano nel dipartimento ‘Public Relations’. Il codice identificativo del dipartimento è 70, basta interrogare la colonna “department_id” della tabella “departments”, ma fingiamo di non conoscere il codice identificativo del dipartimento ‘Public Relations’ e scriviamo pertanto la seguente subquery:
SELECT last_name AS cognome, first_name AS nome, salary AS salario
FROM employees WHERE department_id =
(SELECT department_id FROM departments
WHERE department_name = 'Public Relations');
-
La subquery di 2° livello cercherà l’id del dipartimento ‘Public Relations’
-
La subquery di 1° livello cercherà tutti gli impiegati il cui dipartimento (colonna department_id) coincide con il valore restituito dalla child query.
Nota: Se la child query restituisse più di un risultato (ad esempio se più dipartimenti fossero memorizzati con lo stesso nome nella tabella departments) allora la query fallirebbe.
Subquery a riga multipla
Le subquery di questo tipo restituiscono più di una riga di risultati. È necessario usare operatori a riga multipla come IN, EXISTS, ANY e ALL.
ESEMPIO
Visualizziamo gli impiegati che lavorano nei dipartimenti ‘Administration’ e ‘Marketing’.
SELECT last_name AS cognome, first_name AS nome, salary AS salario
FROM employees WHERE department_id IN (SELECT department_id FROM departments
WHERE (department_name = 'Administration' OR
department_name = 'Marketing'));
-
La child query (2° livello) seleziona i codici dei dipartimenti ‘Administration’ e ‘Marketing’ formando un insieme di due valori;
-
La parent query (1° livello) seleziona gli impiegati che lavorano nel dipartimento il cui codice è contenuto tra i valori presenti nell’insieme restituito dalla child query.
Le subquery in altri statement DML
Possiamo usare le subquery anche nelle operazioni di inserimento, modifica e cancellazione di dati (INSERT, UPDATE, DELETE).
ESEMPIO
Inseriamo nella tabella “Padre” un nuovo nominativo. Alla colonna “idpadre” (PRIMARY KEY), sarà attribuito un nuovo valore utilizzando una subquery. Questa calcola il valore massimo presente nella colonna “idpadre” ed aggiunge un’unità per rispettare il vincolo di chiave primaria.
INSERT INTO padre
VALUES ((SELECT MAX (IDPADRE)+1 FROM padre),
'Ferraris Nicola', TO_DATE ('23/03/1954', 'DD/MM/YYYY'));
Ancora aggiorniamo, nella tabella “Padre”, la data di nascita del nominativo ‘Rominelli Giacomo’. Non conoscendo a priori il suo id, useremo la subquery per ottenere il relativo valore di “idpadre”.
UPDATE padre
SET DATANASCITA = TO_DATE ('25/11/1964', 'DD/MM/YYYY')
WHERE idpadre = (SELECT idpadre FROM padre
WHERE nominativo = 'Rominelli Giacomo');
Infine cancelliamo le righe della tabella “Padre” in cui il valore di “idpadre” è maggiore di 100.
DELETE FROM (SELECT * FROM padre WHERE idpadre > 100);