PROBLEMA [PostgreSQL]Definizione constraint

indisparte

Nuovo Utente
45
3
Salve ho una tabella Scontrino(IdScontrino, totale, DataEmissione, Stato, IdOperatore) e una tabella Impiegato(CF,IdOperatore,...).
Devo definire il seguente vincolo :"Un operatore non può avere più di uno scontrino attivo(stato) contemporaneamente al giorno. Questo è il mio vincolo:
ALTER TABLE Scontrino
ADD CONSTRAINT unicitàScontrinoAttivo
CHECK (NOT EXISTS (SELECT I.CF, S.Data, COUNT(S.IdScontrino) AS Conto
FROM Scontrino as S NATURAL JOIN Impiegato
WHERE S.Stato='Attivo'
GROUP BY I.CF, S.Data
HAVING Conto>1));
L'errore datomi riguarda il fatto che non può esistere una subquery .Questo constraint ho provato ad inserirlo nella tabella Scontrino cliccando su constraint e specificando nel check tutto quello scritto sopra.
)
 

cdtux

Utente Èlite
1,829
911
CPU
I7 3770
Scheda Madre
Asrock Z77 Extreme 4
HDD
Samsung 850 pro 250GB
RAM
Corsair Vengeance LP 16GB
GPU
Gigabyte GTX1060 6GB
Monitor
Dell U2412M
PSU
Seasonic Focus Plus 650
Case
Corsair Graphite 760T
OS
Debian / Ubuntu
A quanto ne so le CONSTRAINT CHECK non accettano subquery.
Se un operatore può avere SOLO uno scontrino attivo e uno passivo puoi utilizzare l'UNIQUE dei campi "DataEmissione", "Stato", "IdOperatore"
Altrimenti dai un'occhiata ai Partial Unique Index
 

indisparte

Nuovo Utente
45
3
A quanto ne so le CONSTRAINT CHECK non accettano subquery.
Se un operatore può avere SOLO uno scontrino attivo e uno passivo puoi utilizzare l'UNIQUE dei campi "DataEmissione", "Stato", "IdOperatore"
Altrimenti dai un'occhiata ai Partial Unique Index
Cioè nello stesso giorno ad esempio oggi 10/03 non posso avere 2 scontrini attivi contemporaneamente. Ne devo avere sempre uno attivo oppure non attivo, mai due contemporaneamente. Va bene lo stesso l'unique?
 

cdtux

Utente Èlite
1,829
911
CPU
I7 3770
Scheda Madre
Asrock Z77 Extreme 4
HDD
Samsung 850 pro 250GB
RAM
Corsair Vengeance LP 16GB
GPU
Gigabyte GTX1060 6GB
Monitor
Dell U2412M
PSU
Seasonic Focus Plus 650
Case
Corsair Graphite 760T
OS
Debian / Ubuntu
SI, però allo stesso modo non puoi avere più di due scontrini non attivi, solo uno attivo e uno non attivo
 

cdtux

Utente Èlite
1,829
911
CPU
I7 3770
Scheda Madre
Asrock Z77 Extreme 4
HDD
Samsung 850 pro 250GB
RAM
Corsair Vengeance LP 16GB
GPU
Gigabyte GTX1060 6GB
Monitor
Dell U2412M
PSU
Seasonic Focus Plus 650
Case
Corsair Graphite 760T
OS
Debian / Ubuntu
L'unique (nel caso di piu colonne) controlla che la combinazione delle n colonne sia unica nella tabella.
Nel tuo caso DataEmissione+Stato+idOperatore deve essere unica nella tabella.

Esempio:
Crei le due tabelle
Codice:
CREATE TABLE Scontrino(
   IdScontrino serial PRIMARY KEY,
   totale NUMERIC(12, 2),
   DataEmissione DATE NOT NULL,
   Stato VARCHAR(10) NOT NULL,
   IdOperatore INTEGER NOT NULL,
   UNIQUE (DataEmissione, Stato, IdOperatore)
);

CREATE TABLE Impiegato(
   id serial PRIMARY KEY,
   CF VARCHAR(11) NOT NULL
);

e inserisci dei valori
Codice:
INSERT INTO Impiegato (CF) VALUES ('AAAAAAAAAAA')

INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('10.99', '03/11/2020', 'terminato', 1 )
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('10.99', '03/11/2020', 'attivo', 1 )

Se provi ad inserire un altro scontrino attivo con la stessa data + id hai un errore
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'attivo', 1 )

ERROR:  duplicate key value violates unique constraint "scontrino_dataemissione_stato_idoperatore_key"

Stessa cosa se provi ad inserire un altro scontrino terminato con la stessa data + id hai un errore
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'terminato', 1 )

ERROR:  duplicate key value violates unique constraint "scontrino_dataemissione_stato_idoperatore_key"

Se invece vuoi inserire uno scontrino di un altro operatore o con data differente non ci sono problemi
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'attivo', 2 )
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/12/2020', 'attivo', 1 )

Con questo sistema puoi aggiungere per il medesimo operatore nella stessa data SOLO UNO scontrino attivo e SOLO UNO terminato.

Presta molta attenzione ai valori NULL che ti potrebbero creare problemi, quindi le colonne da rendere uniche è bene che siano tutte NOT NULL di default
 
  • Mi piace
Reazioni: indisparte

indisparte

Nuovo Utente
45
3
L'unique (nel caso di piu colonne) controlla che la combinazione delle n colonne sia unica nella tabella.
Nel tuo caso DataEmissione+Stato+idOperatore deve essere unica nella tabella.

Esempio:
Crei le due tabelle
Codice:
CREATE TABLE Scontrino(
   IdScontrino serial PRIMARY KEY,
   totale NUMERIC(12, 2),
   DataEmissione DATE NOT NULL,
   Stato VARCHAR(10) NOT NULL,
   IdOperatore INTEGER NOT NULL,
   UNIQUE (DataEmissione, Stato, IdOperatore)
);

CREATE TABLE Impiegato(
   id serial PRIMARY KEY,
   CF VARCHAR(11) NOT NULL
);

e inserisci dei valori
Codice:
INSERT INTO Impiegato (CF) VALUES ('AAAAAAAAAAA')

INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('10.99', '03/11/2020', 'terminato', 1 )
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('10.99', '03/11/2020', 'attivo', 1 )

Se provi ad inserire un altro scontrino attivo con la stessa data + id hai un errore
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'attivo', 1 )

ERROR:  duplicate key value violates unique constraint "scontrino_dataemissione_stato_idoperatore_key"

Stessa cosa se provi ad inserire un altro scontrino terminato con la stessa data + id hai un errore
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'terminato', 1 )

ERROR:  duplicate key value violates unique constraint "scontrino_dataemissione_stato_idoperatore_key"

Se invece vuoi inserire uno scontrino di un altro operatore o con data differente non ci sono problemi
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'attivo', 2 )
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/12/2020', 'attivo', 1 )

Con questo sistema puoi aggiungere per il medesimo operatore nella stessa data SOLO UNO scontrino attivo e SOLO UNO terminato.

Presta molta attenzione ai valori NULL che ti potrebbero creare problemi, quindi le colonne da rendere uniche è bene che siano tutte NOT NULL di default
Grazie è stata una risposta molto utile ed esaustiva!!grazie davvero però chiedevo che ad esempio un operatore se ha uno scontrino attivo non ne può avere due contemporaneamente, ne deve finire prima uno (TERMINATO)e poi poter iniziare un altro quindi può avere molti Terminati e solo uno per volta attivo.
Post unito automaticamente:

ho aggiornato la risposta
L'unique (nel caso di piu colonne) controlla che la combinazione delle n colonne sia unica nella tabella.
Nel tuo caso DataEmissione+Stato+idOperatore deve essere unica nella tabella.

Esempio:
Crei le due tabelle
Codice:
CREATE TABLE Scontrino(
   IdScontrino serial PRIMARY KEY,
   totale NUMERIC(12, 2),
   DataEmissione DATE NOT NULL,
   Stato VARCHAR(10) NOT NULL,
   IdOperatore INTEGER NOT NULL,
   UNIQUE (DataEmissione, Stato, IdOperatore)
);

CREATE TABLE Impiegato(
   id serial PRIMARY KEY,
   CF VARCHAR(11) NOT NULL
);

e inserisci dei valori
Codice:
INSERT INTO Impiegato (CF) VALUES ('AAAAAAAAAAA')

INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('10.99', '03/11/2020', 'terminato', 1 )
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('10.99', '03/11/2020', 'attivo', 1 )

Se provi ad inserire un altro scontrino attivo con la stessa data + id hai un errore
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'attivo', 1 )

ERROR:  duplicate key value violates unique constraint "scontrino_dataemissione_stato_idoperatore_key"

Stessa cosa se provi ad inserire un altro scontrino terminato con la stessa data + id hai un errore
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'terminato', 1 )

ERROR:  duplicate key value violates unique constraint "scontrino_dataemissione_stato_idoperatore_key"

Se invece vuoi inserire uno scontrino di un altro operatore o con data differente non ci sono problemi
Codice:
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/11/2020', 'attivo', 2 )
INSERT INTO Scontrino (totale, DataEmissione, Stato, IdOperatore) VALUES ('20.99', '03/12/2020', 'attivo', 1 )

Con questo sistema puoi aggiungere per il medesimo operatore nella stessa data SOLO UNO scontrino attivo e SOLO UNO terminato.

Presta molta attenzione ai valori NULL che ti potrebbero creare problemi, quindi le colonne da rendere uniche è bene che siano tutte NOT NULL di default
 
Ultima modifica:
  • Mi piace
Reazioni: cdtux

cdtux

Utente Èlite
1,829
911
CPU
I7 3770
Scheda Madre
Asrock Z77 Extreme 4
HDD
Samsung 850 pro 250GB
RAM
Corsair Vengeance LP 16GB
GPU
Gigabyte GTX1060 6GB
Monitor
Dell U2412M
PSU
Seasonic Focus Plus 650
Case
Corsair Graphite 760T
OS
Debian / Ubuntu
Grazie è stata una risposta molto utile ed esaustiva!!grazie davvero però chiedevo che ad esempio un operatore se ha uno scontrino attivo non ne può avere due contemporaneamente, ne deve finire prima uno (TERMINATO)e poi poter iniziare un altro quindi può avere molti Terminati e solo uno per volta attivo.

Allora devi usare i Partial Unique Index
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!