【发布时间】:2019-03-26 13:31:25
【问题描述】:
除了声明列类型之外,应该如何强制域完整性?
ENUM() 是一个选项,但是从 SQL 角度和 Doctrine 角度来看,它都有缺点。
作为替代方案,在使用 ORM 之前设计数据库时,我会改为使用自然键和外部约束。虽然我的time_unit 表有一个名称和秒列,但它唯一真正的意义是将其他表中的值限制为time_unit.unit 的值。
MariaDB [tracker]> select * from time_unit;
+------+-----------+----------+
| unit | name | seconds |
+------+-----------+----------+
| d | Days | 86400 |
| h | Hours | 3600 |
| i | Minutes | 60 |
| m | Month | 2592000 |
| q | Quarter | 10368000 |
| s | Seconds | 1 |
| w | Week | 604800 |
| y | Year | 31536000 |
+------+-----------+----------+
8 rows in set (0.01 sec)
MariaDB [tracker]> select * from sign;
+------+
| sign |
+------+
| -1 |
| 1 |
+------+
2 rows in set (0.00 sec)
CREATE TABLE `agenda` (
`id` int(11) NOT NULL,
`time_value` smallint(6) DEFAULT NULL,
`time_unit` varchar(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`sign` smallint(6) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_agenda_time_unit1_idx` (`time_unit`),
KEY `fk_agenda_sign1_idx` (`sign`),
CONSTRAINT `FK_5A9C89CF7106057E` FOREIGN KEY (`time_unit`) REFERENCES `time_unit` (`unit`),
CONSTRAINT `FK_22ACC67D9F7E91FE` FOREIGN KEY (`sign`) REFERENCES `sign` (`sign`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
但这在使用 ORM 时会出现问题。首先,为每个对象创建一个对象,这似乎过多并使序列化变得痛苦。其次,我read 表示,在使用 ORM 时,不应该使用外键,而是使用关联的对象。
在数据库级别,表示实体之间的关系 通过外键。但是有了 Doctrine,你将永远不必(也永远不会 应该)直接使用外键。你应该只与 通过自己的身份表示外键的对象。
为了强制域完整性,是否应该使用 ENUM()、自然键的外部约束或其他方法?
【问题讨论】:
-
“域完整性”是什么意思?可能这些规则过于复杂,无法在 SQL 的微薄功能中实现,即使使用触发器、FK、数据类型、约束等。在您的客户端代码中执行。
-
@RickJames 我指的是确保给定的列值必须在一组指定的可能值中。 FK 通常工作得很好,但是 Doctrine 会尝试为其创建一个不需要的对象。
-
<snide-remark>有时,第 3 方软件的障碍多于帮助。</snide-remark>
标签: mysql database-design orm doctrine-orm