当用户的电子邮件确认后,mysql 时间戳值会更新,并且其值不应等于“1970-01-01 00:00:01”(默认值)。我正在尝试创建一个 mysql 约束来强制执行此操作。因此,如果用户有以下内容:
confirmed=1
email_confirmed_time='1970-01-01 00:00:01'
...则违反了该约束。但如果 confirmed=0且时间戳相同,则表示该消息被接受。
下面的表格命令有什么问题?如果我插入以下内容,它会告诉我CHK_emailConfirmedTime_when_confirmed存在违规:
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'))
);
CHECK
MySQL 会针对插入的行独立评估每个已定义的约束。让我们在以下上下文中检查一下每个原始约束:1. CONSTRAINT CHK_confirmed CHECK (`confirmed`=0 OR `confirmed`=1)
对于插入的行,
confirmed
为 0。条件
0 = 0 OR 0 = 1
计算结果为TRUE
(因为0 = 0
是真的)。因此,该约束得到满足。
2. CONSTRAINT CHK_approved CHECK (`approved`=0 OR `approved`=1)
对于插入的行,
approved
为 0。条件
0 = 0 OR 0 = 1
计算结果为TRUE
。因此,该约束得到满足。
3.
CONSTRAINT CHK_emailConfirmedTime_when_notConfirmed CHECK (`confirmed`=0 AND `email_confirmed_time`=TIMESTAMP('1970-01-01 00:00:01'))
对于插入的行,
confirmed
为 0,email_confirmed_time
默认为“1970-01-01 00:00:01”。条件
0 = 0 AND '1970-01-01 00:00:01' = TIMESTAMP('1970-01-01 00:00:01')
计算结果为TRUE
(两个部分都AND
为真)。因此,这个约束也是满足的。
4.
CONSTRAINT CHK_emailConfirmedTime_when_confirmed CHECK (`confirmed`=1 AND `email_confirmed_time`>TIMESTAMP('1970-01-01 00:00:01'))
对于插入的行,
confirmed
为 0,email_confirmed_time
为“1970-01-01 00:00:01”。条件
0 = 1 AND '1970-01-01 00:00:01' > TIMESTAMP('1970-01-01 00:00:01')
计算结果为FALSE
(因为0 = 1
为假,导致整个AND
条件为假)。因此,该约束不满足。
一个解决方法是将两个检查结合起来,如下所示
这确保了仅当两者都为真时才会违反约束。
现在,当您插入一行带有
confirmed = 0
默认值的行时,中的email_confirmed_time
条件将为假,从而使整个条件为假。然后,运算符将使约束计算为真,插入将成功。confirmed=1
AND
AND
NOT
当
confirmed
为 1 且email_confirmed_time
为默认值时,AND
条件为真,NOT
运算符将使约束计算结果为假,从而阻止插入或更新。我建议将默认值设置为
email_confirmed_time
而NULL
不是1970-01-01 00:00:01
,然后相应地更新约束。检查条件应完全满足。
因此,当
confirmed=1
AND时email_confirmed_time`>TIMESTAMP('1970-01-01 00:00:01')
,两个条件都应该成立。此条件禁止插入任何包含confirmed<>1
and 的 行email_confirmed_time`<=TIMESTAMP('1970-01-01 00:00:01')
可能将您的 2 个 CHECK 合并为一个
并可能删除 CONSTRAINT CHK_confirmed CHECK (
confirmed
=0 ORconfirmed
=1)小提琴