Quando o e-mail de um usuário é confirmado, um valor de TIMESTAMP do MySQL é atualizado e seu valor não deve ser igual a '1970-01-01 00:00:01' (PADRÃO). Estou tentando criar uma restrição do MySQL que imponha isso. Portanto, se o usuário tiver o seguinte:
confirmed=1
email_confirmed_time='1970-01-01 00:00:01'
... então a restrição é violada. Mas se confirmed=0 com o mesmo TIMESTAMP, então ela é aceita.
O que há de errado com o meu comando table abaixo? Ele me informa que há uma violação em CHK_emailConfirmedTime_when_confirmed se eu inserir o seguinte:
insert into user (username, `password`, first_name, last_name, `role`, `group`, logged_in, confirmed, approved, email_confirmed_time) values
("0", "0", "joe", "dill", "{admin, user, guest}", "{create, read, update, delete}", 0, 0, 0, DEFAULT)
;
CREATE TABLE IF NOT EXISTS user (
`id` SERIAL PRIMARY KEY,
`username` varchar(75) NOT NULL,
`password` varchar(100) NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`role` varchar(25) NOT NULL DEFAULT "{guest}",
`group` varchar(50) NOT NULL DEFAULT "{read}",
`logged_in` int NOT NULL DEFAULT 0,
`confirmed` INTEGER NOT NULL DEFAULT 0,
`approved` INTEGER NOT NULL DEFAULT 0,
`email_confirmed_time` TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:01',
CONSTRAINT CHK_confirmed CHECK (`confirmed`=0 OR `confirmed`=1),
CONSTRAINT CHK_approved CHECK (`approved`=0 OR `approved`=1),
CONSTRAINT CHK_emailConfirmedTime_when_notConfirmed CHECK (`confirmed`=0 AND `email_confirmed_time`=TIMESTAMP('1970-01-01 00:00:01')),
CONSTRAINT CHK_emailConfirmedTime_when_confirmed CHECK (`confirmed`=1 AND `email_confirmed_time`>TIMESTAMP('1970-01-01 00:00:01'))
);
O MySQL avalia cada uma das
CHECK
restrições definidas independentemente para a linha que está sendo inserida. Vamos examinar cada uma das suas restrições originais neste contexto:1. CONSTRAINT CHK_confirmed CHECK (`confirmed`=0 OR `confirmed`=1)
Para a linha inserida,
confirmed
é 0.A condição
0 = 0 OR 0 = 1
é avaliada comoTRUE
(porque0 = 0
é verdadeira).Portanto, essa restrição é satisfeita.
2. CONSTRAINT CHK_approved CHECK (`approved`=0 OR `approved`=1)
Para a linha inserida,
approved
é 0.A condição
0 = 0 OR 0 = 1
é avaliada comoTRUE
.Portanto, essa restrição é satisfeita.
3.
CONSTRAINT CHK_emailConfirmedTime_when_notConfirmed CHECK (`confirmed`=0 AND `email_confirmed_time`=TIMESTAMP('1970-01-01 00:00:01'))
Para a linha inserida,
confirmed
é 0 eemail_confirmed_time
o padrão é '1970-01-01 00:00:01'.A condição
0 = 0 AND '1970-01-01 00:00:01' = TIMESTAMP('1970-01-01 00:00:01')
é avaliada comoTRUE
(ambas as partes deAND
são verdadeiras).Portanto, essa restrição também é satisfeita.
4.
CONSTRAINT CHK_emailConfirmedTime_when_confirmed CHECK (`confirmed`=1 AND `email_confirmed_time`>TIMESTAMP('1970-01-01 00:00:01'))
Para a linha inserida,
confirmed
é 0 eemail_confirmed_time
é '1970-01-01 00:00:01'.A condição
0 = 1 AND '1970-01-01 00:00:01' > TIMESTAMP('1970-01-01 00:00:01')
é avaliada comoFALSE
(porque0 = 1
é falsa, tornando toda aAND
condição falsa).Portanto, essa restrição não é satisfeita .
Uma solução poderia ser combinar as duas verificações conforme abaixo
Isso garante que a restrição seja violada somente quando ambas forem verdadeiras.
Agora, ao inserir uma linha com
confirmed = 0
e o padrãoemail_confirmed_time
, a condiçãoconfirmed=1
dentro doAND
será falsa, tornando toda aAND
condição falsa. ONOT
operador fará com que a restrição seja avaliada como verdadeira, e a inserção será bem-sucedida.Quando
confirmed
for 1 eemail_confirmed_time
for o valor padrão, aAND
condição será verdadeira e oNOT
operador fará com que a restrição seja avaliada como falsa, impedindo assim a inserção ou atualização.Eu recomendaria definir o valor padrão de
email_confirmed_time
paraNULL
em vez de1970-01-01 00:00:01
e, então, atualizar as restrições adequadamente.As condições de verificação devem ser totalmente satisfeitas.
Portanto, quando
confirmed=1
ANDemail_confirmed_time`>TIMESTAMP('1970-01-01 00:00:01')
, ambas as condições devem ser verdadeiras. Essas condições proíbem a inserção de qualquer linha comconfirmed<>1
AND.email_confirmed_time`<=TIMESTAMP('1970-01-01 00:00:01')
Possível juntar seus 2 CHEQUES em um
E pode remover CONSTRAINT CHK_confirmed CHECK (
confirmed
=0 OUconfirmed
=1)violino