Table inheritance in PostgreSQL

  • Di
  • 2023-05-25 - 4 minuti
banner

Il concetto di ereditarietà nella programmazione orientata agli oggetti è un qualcosa di piuttosto popolare: permette infatti di creare una relazione di dipendenza e gerarchia tra due entità, denominate -ad esempio- genitore e figlio.

Questo vuol dire che, a partire dall’entità genitore, sarà possibile ereditare tutte le caratteristiche: attributi, tipo di dati e, nel caso della programmazione, anche le funzioni.

Come possiamo implementare la stessa logica all’interno di PostgreSQL?

Tramite il concetto di table inheritance.

Definizione

L’ereditarietà delle tabelle consente alle tabelle figlie di ereditare tutte le colonne della tabella genitore.

Una tabella figlia può ovviamente avere campi aggiuntivi oltre alle colonne ereditate, ma non richiede la ricreazione di queste da zero.

Come funziona

Vediamo un esempio: la tabella animals definisce un caso abbastanza generico di rappresentazione degli animali, con un ID, un nome e un’età:

CREATE TABLE animals(id serial, age int, name varchar(100)) 

A seguito, potremmo voler declinare gli animali nelle diverse specie che ci vengono in mente: dogs, ad esempio, i quali hanno una propria razza, ed eventualmente un microchip. In questo caso, nell’istruzione di creazione della tabella, utilizziamo la parola inherits, che stabilisce da quale tabella ereditare le colonne. In questo caso, da animals:

CREATE TABLE dogs(breed varchar(100), microchip boolean) inherits(animals)

Inseriamo degli animali all’interno della tabella principale e di quella figlia:

INSERT INTO animals(age, name) VALUES(3, 'Zoe');
INSERT INTO animals(age, name) VALUES(7, 'Zach');
INSERT INTO animals(age, name) VALUES(1, 'Zed');

INSERT INTO dogs(age, name, breed, microchip) VALUES(1, 'Dom', 'Bernese mountain dog', true);
INSERT INTO dogs(age, name, breed, microchip) VALUES(1, 'Jack', 'Jack Russell', true);

Se usi pgAdmin come client per accedere al tuo database, questo è quello che vedrai nel menù di sinistra: due frecce accanto alle tabelle, dove la tabella animals riporta una freccia in uscita per indicare che ha delle tabelle che ereditano le sue proprietà, e al contrario dogs ne ha una in entrata:

Elenco

Finora, nulla di eccezionale. Vediamo però come cambiano le cose quando si usa questa tipologia di rappresentazione, e proviamo ad elencare tutti i record presenti nella tabella “principale”:

SELECT id, age, name
	FROM public.animals;
>>>
id  age name
1	3	"Zoe"
2	7	"Zach"
3	1	"Zed"
4	1	"Dom"
5	1	"Jack"

Vengono riportati 5 animali, e non 3, come quelli inseriti per la tabella animals: questo perché, di base, PostgreSQL andrà a restituire tutte le entità che afferiscono a quella tabella, comprese quelle “derivate”, come gli oggetti presenti in dogs.

Se volessimo però restringere il campo ai soli animali, potremmo usare un’istruzione speciale: only.

SELECT id, age, name
	FROM only public.animals;
>>>
id  age name
1	3	"Zoe"
2	7	"Zach"
3	1	"Zed"

La parola chiave “only” può essere usata per indicare che la query deve essere applicata solo a una particolare tabella e non a qualsiasi altra tabella.

Notare un aspetto interessante: in PostgreSQL, quando si eredita una colonna che ha come tipo di dato serial dalla tabella genitore, la sequenza è condivisa dalla tabella genitore e figlia.

Questo vuol dire che se inserissimo un nuovo animale nella tabella dogs, questo assumerebbe ID 7; se poi ne inserissimo uno nella tabella principale animals, questo avrebbe ID 8. Questo avviene anche per evitare che, nel rappresentare le diverse entità, gli ID delle due tabelle, vadano in conflitto.

Modifica

Chiaramente, questo vuol dire che qualsiasi aggiornamento o cancellazione della tabella dei genitori non ha effetto solo sui record della tabella dei figli, ma anche su quella principale. Un esempio come il seguente risulta nella modifica di tutti i record presenti, compresi quelli presenti in dogs, del campo age delle due tabelle:

UPDATE animals SET age=3

Per aggiornare solo i dati di una tabella, è sufficiente utilizzare l’operatore visto in precedenza:

UPDATE ONLY animals SET age=3

Cascade

E se provassimo a cancellare la tabella animals? Questo sarebbe il risultato:

DROP TABLE animals;

Questo perché il database tiene conto della relazione che c’è tra le tabelle e riporta che dogs dipende da animals, pertanto non è possibile procedere in questo modo alla cancellazione, se non cancellando prima le tabelle figlie.

Per procedere comunque ed eliminare tutte le tabelle, è possibile specificare di eseguire il DROP anche delle tabelle dipendenti, con l’istruzione CASCADE:

DROP TABLE animals CASCADE;

Risorse utili

Post correlati

Iscriviti al TheRedCode.it Corner

La tecnologia corre, e tu devi correre più veloce per rimanere sempre sul pezzo! 🚀

Riceverai una volta al mese (o anche meno) con codici sconto per partecipare agli eventi del settore, quiz per vincere dei gadget e i recap degli articoli più interessanti pubblicati sul blog

Ci sto!

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source
Logo di NgRome

Vuoi diventare #tech content writer? 🖊️

Se vuoi raccontare la tua sul mondo #tech con dei post a tema o vuoi condividere la tua esperienza con la community, sei nel posto giusto! 😉

Manda una mail a collaborazioni[at]theredcode.it con la tua proposta e diventa la prossima penna del blog!

Ma sì, facciamolo!