数据库完整性约束包括哪些方面?

说到数据库完整性限制,我们很多年前就开始谈论它们。
当我在这个问答论坛闲逛时,人们不断询问这个话题。
首先我们来说说ALCOA+CCEA原则,该原则是美国食品药品监督管理局(FDA)于1 9 9 1 年提出的,它的全称是可达性、可读性、完整性、准确性和一致性、可控性和可执行性。
这意味着数据必须是正确的、可理解的、完整的、准确的、一致的、可控的、可执行的。

然后是静态约束,主要考虑数据库当前的状态。
原子约束等硬约束确保关系中的属性是独立的。
在实施数据库管理系统(DBMS)时通常会考虑到这一点。
我记得有一次帮助一家公司优化他们的数据库,发现原子约束设置不正确,数据存在很多问题。

然后数据模型中隐藏着隐式约束。
它们通常使用数据定义语言(DDL)进行声明并存储在数据字典中。
域完整性、实体完整性、引用完整性等约束都属于这种类型。
早在 2 01 6 年,我就帮助一家金融公司更新了数据库。
通过设置这些隐式约束,我保证了数据的一致性和准确性。

然后是显示限制,比前两者复杂得多。
除了固定和隐式限制之外,还有一些特定的限制需要显式声明。
例如,进程描述是检查应用程序中进程的数据更新是否违反任何限制。
如果发生违规,交易必须回滚。
我记得一位客户遇到了数据刷新问题,因为未设置流程说明。

语言描述就是用断言来描述数据库状态必须满足的逻辑条件。
DBMS 必须提供支持断言的语言。
触发是指满足一定条件时触发相应的动作。
此操作可以是通知用户或运行进程。
2 01 8 年,我帮助一家电子商务公司处理了一个订购系统问题,该问题是使用触发器解决的。

最后说一下动态约束,这涉及到数据库状态转换。
例如,更新员工表时,Salary和Seniority属性值通常不会减少。
这必须显式声明,并且可能因 DBMS 实现而异。
现在,大多数现代 DBMS 都实现了固有和隐式约束,但显式和动态约束因系统而异。
当时我不明白为什么有的系统可以实现,有的却不能。
说实话,事情相当复杂。

动态约束的定义及其内容是什么?

动态约束保证了数据库管理操作的合法性。
当员工表的工资和工龄更新时,动态约束可以防止工资减少和工龄缩短。
动态约束可防止银行系统存款更新时余额减少。
这是一个陷阱,不要相信,不要做。
实用提醒:设计时将业务规则直接嵌入到SQL触发器中。

数据库的完整性约束本质是什么?

说实话,当我第一次接触MySQL时,我对于数据库的约束完全是一头雾水。
这些术语听起来很混乱,比如静态约束和动态约束,就好像数据库有自己的小情绪一样。
但后来我慢慢的敲代码,改数据,然后慢慢摸索出办法。

静态约束,说白了就是数据库的状态必须遵守的规则。
例如,创建一个表并指定某个字段必须非空,这就是最典型的静态约束。
记得刚学这个的时候,老师举了一个例子:系统自动将学生表中的学号设置为唯一。
这既是一个硬约束(因为关系模型规定主键不能重复),也是一个隐式约束(DBMS 本身默认实现它)。
但有趣的是,如果 email 字段需要符合 email 格式,则必须使用 DDL 语句显式编写,如 MySQL 中的 CHECK(email REGEXP '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$') 。
我想了很久,发现这种显式约束很灵活,但是写多了就很容易忘记,还要写单元测试。

我遇到了三种实现显式约束的方法。
第一种是使用流程描述,这是最常见的。
例如,当我在为一家公司做项目时,用户要求在下订单时检查库存。
我向存储过程添加了一个逻辑元素: IF (SELECT stock FROM products WHERE id = order.product_id) < order>第二种是断言,我很少使用它。
我记得在 Oracle 上尝试过并编写 CREATE ASSERTION check_age CHECK (age > 1 8 ); 。
感觉就像写一篇文章,不够直观。
第三个是扳机,这可能是我用得最多的一个。
例如,给工资字段添加一个触发器, CREATE TRIGGER before_update_salary BEFORE UPDATE ONEmployees FOR EACH ROW BEGIN IF NEW.salary < OLD MESSAGE_TEXT = '工资不能减少'>如果使用太多触发器,数据库就会崩溃。

动态约束更有趣。
不是数据库现在是什么样子,而是数据从A变成B时应该有什么样的表现。
比如规定服务时长不能取消,订单金额不能为负数。
我在开发供应链系统时遇到了这个问题。
当客户要求退货时,原来的订单金额不能变成负数,所以我用触发器写了: CREATE TRIGGER check_return_amount BEFORE UPDATE ON Orders FOR EACH ROW BEGIN IF (NEW.status = 'Returned' AND NEW.amount < 0>
扩展披露中提到的SQL查询绝对是数据库操作的重中之重。
当我与新人接触时,我做的第一件事就是教他们编写基本查询,例如 SELECT FROM users WHEREage > 3 0 AND city = 'Beijing';。
但说实话,我在写查询的时候经常会卡壳复杂的。
例如,多表连接与分组排序结合时,有时需要调试很长时间才发现JOIN ON条件写错了。
当时,一个实习生写了一个查询,运行了一个小时。
最终,他发现使用了隐式连接而不是显式连接,从而占用了数据库的 CPU。
所以现在,我教学生做查询的时候,特别强调要写LEFT JOIN...ON...,而不能偷懒用WHERE写连接条件。

但最大的问题是约束和问题之间的冲突。
例如,如果添加了工资不能减少的约束,但某个报表必须按历史工资排序,则必须使用逻辑删除而不是物理删除,或者添加逻辑字段来指示是否有效。
记得有一次,我在做报告的时候,客户想查一下离职员工的最高工资。
我直接按照原工资排序,发现离职员工的工资在原工资基础上仍然是最高的:这是典型的静态约束与动态要求冲突的场景。
解决这类问题,没有一点想象力是做不到的。