![]() |
Sagra di Cimpello Pro Loco Cimpello 1998 |
Quello che è interessante, però, e che il parser è comunque quasi completo, e
quindi è possibile scrivere istruzioni in ``full-sql'', che in parte verranno
semplicemente ignorate (come per le direttive FOREIGN KEY nelle CREATE
TABLE).
Questa secondo me è una ``feature'' interessante e utile...
Ma questo mi impediva di conoscere il numero d'ordine, che mi serve in una
serie di inserimenti successivi.
Ho quindi optato per una soluzione che reputo semplice e robusta, overo una
semplice tabella definita come:
CREATE TABLE Progressivo ( Numero SMALLINT NOT NULL, PRIMARY KEY (Numero) )
da cui estraggo un identificatore unico con un algoritmo elementare:
while (``inserimento andato a male'') { SELECT MAX(Numero) AS Max FROM Progressivo; INSERT INTO Progressivo VALUES (Max+1); }
visto che l'istruzione INSERT INTO è atomica, se l'inserimento va a buon fine ho sicuramente ottenuto un identificativo (Max+1) unico.
CREATE TABLE Volontario ( IDVolontario CHAR(2) NOT NULL, Nome VARCHAR(20), Cognome VARCHAR(20), Servizio ENUM('C','A','V') NOT NULL, DataDiNascita DATE, Indirizzo VARCHAR(40), PRIMARY KEY (IDVolontario), INDEX Aux (Servizio) )
Per un maggiore controllo sull'input, ho utilizzato i tipi enumerati di MySQL, presenti in tutti i DBMS SQL moderni.
CREATE TABLE Piatto ( IDPiatto CHAR(2) NOT NULL, NomePiatto VARCHAR(20), Descrizione VARCHAR(50), Tipo ENUM('C','B') NOT NULL, Ord SMALLINT NOT NULL, Prezzo SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (IDPiatto), INDEX Aux (Tipo,Ord) )
CREATE TABLE Ordine ( Nordine SMALLINT NOT NULL, DataOrdine DATE NOT NULL, Stato ENUM('I','X','A','E','D') NOT NULL, PRIMARY KEY (Nordine,DataOrdine), INDEX Aux (Stato) )
CREATE TABLE Asporto ( Nordine SMALLINT NOT NULL, DataOrdine DATE NOT NULL, NomeCliente VARCHAR(20), PRIMARY KEY (Nordine,DataOrdine), FOREIGN KEY (Nordine,DataOrdine) REFERENCES Ordine (Nordine,DataOrdine) ON DELETE CASCADE )
È da notare la definizione (ignorata) di chiave esterna; è anche charo che una cancellazione del'ordine deve comportare la cancelazione delle informazioni sull'asporto.
CREATE TABLE Tavolo ( Nordine SMALLINT NOT NULL, DataOrdine DATE NOT NULL, Ntavolo SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (Nordine,DataOrdine), FOREIGN KEY (Nordine,DataOrdine) REFERENCES Ordine (Nordine,DataOrdine) ON DELETE CASCADE )
Stesse note di qui sopra.
CREATE TABLE Storia ( Nordine SMALLINT NOT NULL, DataOrdine DATE NOT NULL, IDVolontario CHAR(2) NOT NULL, Tstamp TIMESTAMP, PRIMARY KEY (Nordine,DataOrdine,IDVolontario), FOREIGN KEY (Nordine,DataOrdine) REFERENCES Ordine (Nordine,DataOrdine) ON DELETE CASCADE, \ FOREIGN KEY (IDVolontario) REFERENCES Volontario (IDVolontario) ON DELETE SET NULL )
Qui invece è da notare che se un identificativo di volontario viene eliminato dal database, le informazioni sulla storia degli ordini trattati da quel volontario non vanno cancellate (non vanno ignorate!!!); in questa maniera viene posto un riferimento a NULL.
CREATE TABLE Composizione ( Nordine SMALLINT NOT NULL, DataOrdine DATE NOT NULL, IDPiatto CHAR(2) NOT NULL, Qta SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (Nordine,DataOrdine,IDPiatto), FOREIGN KEY (Nordine,DataOrdine) REFERENCES Ordine (Nordine,DataOrdine) ON DELETE CASCADE, FOREIGN KEY (IDPiatto) REFERENCES Piatto (IDPiatto) ON DELETE SET NULL )
Si possono fare le stesse note di qui sopra.
In particolare:
SELECT Servizio, AVG(UNIX_TIMESTAMP(Tstamp)) AS Media FROM Ordine NATURAL LEFT JOIN Storia NATURAL LEFT JOIN Volontario,Tavolo WHERE (Ordine.Nordine=Tavolo.Nordine AND Ordine.DataOrdine=Tavolo.DataOrdine AND Stato = 'E') GROUP BY Servizio
Notare la condizione esplicita tra Ordine e Tavolo, questo perchè una join naturale ritornava un null in corrispondeza degli ordini non presenti in Tavolo; niente di grave, ma non mi piaceva! ;).
In teoria si dovrebbero controllare solo gli ordini evasi, e non quelli genericamente ``non cancellati''. Pur essendo questo metodo meno robusto, permette di utilizzare solo la gestione cassa di LinuxSagra ma contemporaneamente avere un totale affidabile.
SELECT Composizione.IDPiatto, SUM(Qta) AS Totale FROM Piatto NATURAL LEFT JOIN Composizione NATURAL LEFT JOIN Ordine NATURAL LEFT JOIN Storia NATURAL LEFT JOIN Volontario WHERE (Servizio = 'C' AND Stato <> 'D' AND ( ($TS2 - UNIX_TIMESTAMP(Tstamp)) < $diff)) GROUP BY IDPiatto ORDER BY Tipo,Ord
$TS2 contiene il limite inferiore dell'intervallo, mentre $diff contiene l'estensione dell'intervallo in cui calcolare i totali.
SELECT Ordine.Nordine, Ordine.DataOrdine, Stato,IDVolontario, UNIX_TIMESTAMP(Tstamp) AS UTstamp, Composizione.IDPiatto, Qta FROM Ordine NATURAL LEFT JOIN Storia NATURAL LEFT JOIN Composizione NATURAL LEFT JOIN Piatto WHERE ((Stato='X' OR Stato='A') AND Tipo = 'C') ORDER BY Ordine.DataOrdine, Ordine.Nordine, Tipo, Ord
SELECT IDPiatto, SUM(Qta) AS Qtot FROM Composizione NATURAL LEFT JOIN Ordine WHERE (Stato = 'A' OR Stato = 'X') GROUP BY IDPiatto
2 | 3 | 5 |
LinuxSagra v1.0.0 (C) Marco Gaiarin | 12:00:00 | Ritorna al Menu |