1
Fork 0
mirror of https://github.com/Steffo99/alexandria.git synced 2024-10-16 13:37:27 +00:00

Finisci quasi tutto

This commit is contained in:
Steffo 2020-06-05 18:59:14 +02:00
parent 9666ae9b93
commit 5f873a6759
Signed by: steffo
GPG key ID: 896A80F55F7C97F0
5 changed files with 53 additions and 52 deletions

View file

@ -71,6 +71,7 @@ Di seguito si riporta l'intero schema logico dopo aver effettuato tutte le trasf
- _Provenienza_
### Recensione (libro)
- **ID** → [Elemento (libro)](#elemento-libro)
- Commento
- Valutazione

View file

@ -35,18 +35,21 @@ Si riportano solo le tabelle con qualche particolarità; le tabelle per la quale
```sql
CREATE TABLE public.audiolibro_edizione (
isbn integer NOT NULL,
isbn character(13) NOT NULL,
titolo character varying NOT NULL,
durata interval,
immagine bytea,
relativa_a integer NOT NULL
relativa_a integer NOT NULL,
CONSTRAINT durata_check CHECK ((date_part('epoch'::text, durata) >= (0)::double precision))
);
ALTER TABLE ONLY public.audiolibro_edizione
ADD CONSTRAINT audiolibro_edizione_pkey PRIMARY KEY (isbn);
```
L'immagine relativa all'audiolibro è archiviata nella base di dati come un blob binario di dati.
La durata delle edizioni degli audiolibri è di tipo _interval_, che rappresenta un intervallo di tempo con la precisione di centesimi di secondo; l'immagine dell'audiolibro ha invece tipo _bytea_, e sarà salvata nel database come un blob binario di dati.
Inoltre, la durata è dotata di un _CHECK_ che impedisce che essa sia minore di 0, convertendo l'_interval_ in secondi e controllando che essi siano maggiori di 0.
### `audiolibro_recensione`
@ -55,17 +58,23 @@ CREATE TABLE public.audiolibro_recensione (
id bigint NOT NULL,
commento text NOT NULL,
valutazione smallint NOT NULL,
data timestamp without time zone NOT NULL,
data timestamp without time zone DEFAULT now() NOT NULL,
CONSTRAINT audiolibro_recensione_valutazione_check CHECK (((valutazione >= 0) AND (valutazione <= 100)))
);
ALTER TABLE ONLY public.audiolibro_recensione
ADD CONSTRAINT audiolibro_recensione_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.audiolibro_recensione
ADD CONSTRAINT id FOREIGN KEY (id) REFERENCES public.audiolibro_elemento(id);
```
La valutazione delle recensioni deve essere obbligatoriamente tra 0 e 100: a tale scopo, è stato introdotto un _CHECK_ sulla tabella.
Per minimizzare valori nulli, si è tradotta l'associazione binaria 1 a 1 `relativa a` in due tabelle separate, usando in una delle due una chiave esterna come chiave primaria.
Si notino dunque i due _CONSTRAINT_ `audiolibro_recensione_pkey` e `id`.
La data di pubblicazione è rappresentata da un _timestamp_.
La valutazione delle recensioni deve essere obbligatoriamente tra 0 e 100: a tale scopo, è stato introdotto un _CHECK_ sulla tabella che verifichi questa condizione.
La data di pubblicazione è rappresentata da un _timestamp_, tipo che rappresenta un istante specifico di tempo con precisione fino ai secondi.
### `film`
@ -75,19 +84,17 @@ CREATE TABLE public.film (
titolo character varying NOT NULL,
sinossi text,
locandina bytea,
durata integer,
CONSTRAINT film_durata_check CHECK ((durata >= 0))
durata interval,
CONSTRAINT durata_check CHECK ((date_part('epoch'::text, durata) > (0)::double precision))
);
ALTER TABLE ONLY public.film
ADD CONSTRAINT film_pkey PRIMARY KEY (eidr);
```
I film hanno un _CHECK_ che impedisce alla loro durata di essere minore di 0 minuti, nel caso essa sia definita.
Nella tabella `film` compare nuovamente il _CHECK_ utilizzato nelle `audiolibro_edizioni` per la durata, e lo stesso tipo _bytea_ per la locandina.
Il loro `eidr` è una stringa di lunghezza costante _char_, in quanto gli EIDR sono sempre lunghi 34 caratteri.
Inoltre, come per gli audiolibri, la loro locandina è immagazzinata nel database come _bytea_.
Si può notare nella tabella compare il tipo _char(34)_: essendo gli EIDR sempre lunghi 34 caratteri, si è scelto si minimizzare lo spazio di archiviazione utilizzato rendendo il campo a lunghezza non variabile.
### `film_correlazioni`
@ -133,7 +140,7 @@ ALTER TABLE ONLY public.film_vi_ha_preso_parte
ADD CONSTRAINT id_ruolo FOREIGN KEY (id_ruolo) REFERENCES public.film_ruolo(id);
```
L'associazione ternaria è stata realizzata con una **tabella ponte**, con una **chiave primaria composta** e tre chiavi esterne separate.
L'associazione ternaria è stata realizzata con un'altra **tabella ponte**, avente una **chiave primaria composta** e tre chiavi esterne separate.
### `elemento_id_seq`
@ -148,9 +155,9 @@ CREATE SEQUENCE public.elemento_id_seq
Si è deciso di rendere **univoci** gli `id` di **tutti gli elementi**, qualsiasi fosse il loro tipo.
Per realizzare l'unicità si è creata una unica _SEQUENCE_, che viene usata da tutte le tabelle `*_elemento`.
Per realizzare ciò si è creata una _SEQUENCE_ unica che viene poi usata da tutte le tabelle `*_elemento` per generare i nuovi id.
### `gioco_stato` e `gioco_provenienza`
### Stato e provenienza
```sql
CREATE TYPE public.gioco_provenienza AS ENUM (
@ -171,7 +178,7 @@ CREATE TYPE public.gioco_stato AS ENUM (
);
```
Gli stati e le provenienze degli elementi sono state realizzate tramite _ENUM_ contenenti tutte le possibili opzioni selezionabili dall'utente.
Gli stati e le provenienze dei vari elementi sono state realizzate creando _ENUM_ contenenti tutte le possibili opzioni selezionabili dall'utente, e utilizzandoli come tipo delle relative colonne; in questo modo, si impedisce l'immissione di valori non validi nelle colonne.
### `gioco_elemento`
@ -195,53 +202,46 @@ ALTER TABLE ONLY public.gioco_elemento
CREATE FUNCTION public.update_n_giochi() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
AS $$BEGIN
IF (TG_OP = 'DELETE') THEN
UPDATE utente
SET gioco_elementi_posseduti = gioco_elementi_posseduti - 1
FROM gioco_elemento
WHERE utente.username = old.appartiene_a;
RETURN old;
ELSIF (TG_OP = 'INSERT') THEN
UPDATE utente
SET gioco_elementi_posseduti = gioco_elementi_posseduti + 1
FROM gioco_elemento
WHERE utente.username = new.appartiene_a;
RETURN new;
END IF;
END;
$$;
CREATE TRIGGER numero_giochi_trigger
BEFORE INSERT OR DELETE
CREATE TRIGGER numero_giochi_trigger BEFORE INSERT OR DELETE
ON public.gioco_elemento
FOR EACH ROW EXECUTE PROCEDURE public.update_n_giochi();
```
Le tabelle degli elementi hanno due colonne `stato` e `provenienza` di tipo `*_stato` e `*_provenienza` rispettivamente: sono gli _ENUM_ creati in precedenza, che impediscono che vengano inseriti valori non consentiti nella tabella.
Le colonne `stato` e `provenienza` utilizzano il relativo _ENUM_ creato in precedenza.
La colonna `id` invece ha un valore di _DEFAULT_ particolare: `nextval('public.elemento_id_seq'::regclass)`.
Significa che, se non viene specificato un `id` durante un _INSERT_, alla riga verrà assegnato automaticamente il valore corrente della _SEQUENCE_, e il valore della sequenza sarà aumentato, garantendo l'**unicità** degli `id` anche attraverso tabelle diverse.
La colonna `id` ha un valore di _DEFAULT_ particolare: `nextval('public.elemento_id_seq'::regclass)`.
Ciò significa che, se non viene specificato un `id` durante un inserimento, alla riga verrà assegnato automaticamente il valore corrente della _SEQUENCE_ `public.elemento_id_seq` descritta in precedenza, aumentandone inoltre il valore di 1.
Inoltre, nella tabella è presente un _TRIGGER_, che incrementa o decrementa il conteggio dei giochi di un utente quando egli rispettivamente crea o elimina nuovi elementi.
Nella tabella è presente anche un _TRIGGER_, che incrementa o decrementa il conteggio degli elementi dell'utente a cui essi appartengono quando uno o più elementi vengono inseriti o rimossi.
### `libro_edizione`
```sql
create function is_numeric(text character varying) returns boolean
strict
language plpgsql
as
$$
DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
$$;
CREATE FUNCTION public.is_numeric(text character varying) RETURNS boolean
LANGUAGE plpgsql STRICT
AS $_$DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;$_$;
CREATE TABLE public.libro_edizione (
isbn character(13) NOT NULL,
@ -260,7 +260,9 @@ ALTER TABLE ONLY public.libro_edizione
ADD CONSTRAINT relativa_a FOREIGN KEY (relativa_a) REFERENCES public.libro(id);
```
La tabella delle edizioni di un libro include due _CHECK_: uno che controlla che le pagine, se specificate, siano un numero positivo, e un'altro che controlla che gli ISBN siano in un formato valido, assicurandosi che tutti i caratteri siano numerici e permettendo anche una `X` sull'ultimo.
La tabella delle edizioni di un libro include due _CHECK_: uno che controlla che le pagine, se specificate, siano un numero positivo, e un'altro che controlla che gli ISBN siano in un formato valido.
In particolare, per quest'ultimo, è stata creata una funzione di utilità `is_numeric`, che verifica che tutti i caratteri di una stringa siano numerici: questa funzione viene poi usata per controllare che tutti i caratteri dell'ISBN siano numeri, permettendo però anche una `X` in ultima posizione.
### `utente`
@ -286,3 +288,4 @@ La password, essendo un [hash](https://it.wikipedia.org/wiki/Funzione_di_hash),
Le colonne `is_admin` e `is_banned` hanno un valore di default di _false_, in quanto alla creazione gli utenti non saranno amministratori o bannati.
Le colonne `*_elementi_posseduti` sono i dati derivati che rappresentano quanti elementi di ogni tipo possiede un dato utente: per i nuovi utenti, questo valore sarà 0.
Queste colonne saranno poi incrementate dai trigger presenti nelle quattro tabelle `*_elemento`.

View file

@ -224,7 +224,8 @@ CREATE TABLE public.audiolibro_edizione (
titolo character varying NOT NULL,
durata interval,
immagine bytea,
relativa_a integer NOT NULL
relativa_a integer NOT NULL,
CONSTRAINT durata_check CHECK ((date_part('epoch'::text, durata) >= (0)::double precision))
);
@ -307,8 +308,8 @@ CREATE TABLE public.film (
titolo character varying NOT NULL,
sinossi text,
locandina bytea,
durata integer,
CONSTRAINT film_durata_check CHECK ((durata >= 0))
durata interval,
CONSTRAINT durata_check CHECK ((date_part('epoch'::text, durata) >= (0)::double precision))
);
@ -894,13 +895,13 @@ COPY public.audiolibro_recensione (id, commento, valutazione, data) FROM stdin;
--
COPY public.film (eidr, titolo, sinossi, locandina, durata) FROM stdin;
10.5240/29E6-2D4B-B704-2B69-441F-8 Titanic \N \N 195
10.5240/29E6-2D4B-B704-2B69-441F-8 Titanic \N \N 03:15:00
10.5240/E030-107B-C08A-BF93-AC79-B The Lord of the Rings: The Fellowship of the Ring \N \N \N
10.5240/598E-D2AE-1B7D-67EB-3F75-6 The Lord of the Rings: The Two Towers \N \N \N
10.5240/B07E-E305-8057-CD37-0887-E The Lord of the Rings: The Return of the King \N \N \N
10.5240/0EF3-54F9-2642-0B49-6829-R Inception \N \N 148
10.5240/0EF3-54F9-2642-0B49-6829-R Inception \N \N 02:28:00
10.5240/3CB5-4D3B-BC77-8A4E-78D4-9 La vita è bella \N \N \N
10.5240/E73C-4D4C-4F90-781B-B62F-K Shining \N \N 146
10.5240/E73C-4D4C-4F90-781B-B62F-K Shining \N \N 02:26:00
10.5240/09A3-1F6E-3538-DF46-5C6F-I Back to the Future \N \N \N
10.5240/5DA5-C386-2911-7E2B-1782-L Back to the Future Part II \N \N \N
\.

View file

@ -73,7 +73,7 @@ FROM gioco_recensione gr
JOIN gioco_elemento gel on gr.id = gel.id
JOIN gioco_edizione ge on gel.istanza_di = ge.id
JOIN gioco g on ge.relativa_a = g.id
WHERE g = $id_gioco;
WHERE g.id = $id_gioco;
```
## Visualizzazione di tutte le edizioni di un dato editore

View file

@ -4,8 +4,6 @@ Un database per un ipotetico sito web di gestione libreria multimediale
Realizzato in collaborazione tra [@Steffo99](https://github.com/Steffo99/) e [@Cookie-CHR](https://github.com/Cookie-CHR) per l'esame di [Basi di Dati](http://personale.unimore.it/rubrica/contenutiad/rmartoglia/2019/58030/N0/N0/9999) dell'[Unimore](https://www.unimore.it/).
> Questo progetto non è ancora terminato. Molte cose possono ancora variare!
## Specifiche
Le specifiche di questo progetto sono disponibili nel file [`spec.pdf`](0-spec.pdf).
@ -22,9 +20,7 @@ Le specifiche di questo progetto sono disponibili nel file [`spec.pdf`](0-spec.p
4. **Progettazione logica**
1. [Eliminazione delle gerarchie](4-1-eliminazione-gerarchie.md)
2. [Eliminazione delle chiavi esterne](4-2-eliminazione-chiavi-esterne.md)
<!--La selezione delle chiavi primarie la abbiamo già fatta in 3-4, la dobbiamo spostare qui?-->
3. [Trasformazione degli attributi composti](4-3-trasformazione-degli-attributi-composti.md)
<!--Bisogna finire dati daerviati!-->
4. [Dati derivati](4-4-dati-derivati.md)
5. [Schema logico](4-5-schema-logico.md)
6. [Verifica di normalizzazione](4-6-normalizzazione.md)