Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 使用ORM时如何确保域完整性_Mysql_Database Design_Orm_Doctrine Orm - Fatal编程技术网

Mysql 使用ORM时如何确保域完整性

Mysql 使用ORM时如何确保域完整性,mysql,database-design,orm,doctrine-orm,Mysql,Database Design,Orm,Doctrine Orm,除了声明列类型外,还应如何实施域完整性 ENUM()是一个选项,但是,从SQL角度以及从其他角度来看,它都有缺点 另外,在使用ORM之前设计数据库时,我会使用自然键和外部约束。虽然我的time\u unit表有一个name和seconds列,但它唯一的实际意义是将其他表中的值限制为time\u unit.unit MariaDB [tracker]> select * from time_unit; +------+-----------+----------+ | unit | name

除了声明列类型外,还应如何实施域完整性

ENUM()
是一个选项,但是,从SQL角度以及从其他角度来看,它都有缺点

另外,在使用ORM之前设计数据库时,我会使用自然键和外部约束。虽然我的
time\u unit
表有一个name和seconds列,但它唯一的实际意义是将其他表中的值限制为
time\u 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时会出现问题。首先,为每一个对象创建一个对象,这似乎是过度的,并且使序列化成为一种痛苦。第二,我知道在使用ORM时,不应该使用外键,而应该使用关联的对象

在数据库级别,表示实体之间的关系 用外键。但有了信条,你就永远不必(也永远不必) 应)直接使用外键。你应该只和我一起工作 通过其自身标识表示外键的对象

为了加强域完整性,应该使用ENUM()、对自然密钥的外部约束,还是使用其他方法

ENUM()是一个选项,但从SQL的角度来看,它有缺点 以及一个理论观点

要强制域完整性,应枚举()将外部约束 使用自然键还是其他方法

您可以替换MySQL/MariaDB的数据类型

ENUM('1', '2', '3'); 
用更理性的方法

    CREATE TABLE enum_data (
       position TINYINT
     , value CHAR(1)
    );

INSERT INTO enum_data (position, value) VALUES(1, '1');
INSERT INTO enum_data (position, value) VALUES(2, '2');
INSERT INTO enum_data (position, value) VALUES(3, '3');
把它放在你的桌子上

CREATE TABLE your_table (
   id INT ....
 , enum_data_id TINYINT
 ...
 ...
)
Offcource您还可以/应该使用
外键
,以使用rational方法确保数据完整性
另外,与
ENUM
相比,使用额外的表具有优势

如果要添加、编辑或从
ENUM
数据类型中删除,则必须使用
ALTER TABLE
,这在使用其他表时是不需要的

这主要是一个风格问题。在构建模式时,引用完整性是保证质量的一种方法。还有其他方法可以做到这一点——例如,单元测试可以保证系统不会接受除1和-1之外的“符号”值

因此,如果您有一个表,仅用于限制有效条目,如果没有其他属性,我建议您做最简单的事情,并将该逻辑放在应用程序层中,使用单元测试来验证所需的行为。只需将数据作为不带外键的整数存储在数据库中

如果您确实想让数据库验证条目,可以使用枚举,或者告诉ORM该列只是一个整数,但仍然要创建外键。这是否是一个好主意再次取决于风格。我更喜欢“干巴巴的”——不要重复你自己。如果您有逻辑来限制应用程序层中某个属性的有效选项,请将重点放在改进上,不要在数据库模式中重复该逻辑。但这并不是一成不变的——如果您认为人们会在您的应用程序之外访问数据库,那么使用外键或枚举是合理的

我认为您的
time\u单位
不仅仅是一组查找值,我猜“seconds”列用于单位之间的转换。这里有两个选项,但是再一次,我想依靠单元测试来验证转换逻辑,如果转换逻辑发生的话,您可以考虑将这些存储在应用程序代码中作为常量。然后,您可以将该单元作为char列存储在议程表中

这使您的持久性逻辑更容易、更快,但将验证行为的责任放在单元测试中,而不是放在模式中


我认为有关从不直接使用外键的引语旨在表明,使用ORM的“正常”行为是通过请求议程对象(
print agendaItem.time\u unit.name
)来访问时间单位,而不是明确请求外键并检索相关对象(
timeUnitID=agendaItem.timeUnitID;打印时间\u unit.findByID(timeUnitID
)。我不认为这是反对外键的全面建议。

谢谢雷蒙德。这不会导致创建
EnumData
对象吗?而且有点离题,但你会建议在使用ORM时只使用代理键吗?@user1032531我已经很长时间没有使用条令了。如果你应该,我也不能提出建议我不知道你的数据模型,也不知道你是否有自然密钥,不会再次使用。明白了。我只是好奇,但你在使用另一个ORM吗?我一直只是简单地使用SQL,并使用PHP执行,而这整件事花费的时间比我之前想象的要多“只是好奇,但你在用另一个ORM吗?”我已经构建并使用了我自己的抽象数据库层@user1032531,它支持对象关系映射、活动记录、直接查询和查询构建,以及跨数据库供应商的方法链接。它还支持优化事务中的查询。例如,多个更新查询将被重写为一个带有案例的更新查询感谢Neville,对于“sign”表,为什么不包括外键约束,以便DB只强制执行允许的值,而让ORM忽略sign表,这样它就不会创建
sign
对象?我更新了答案以反映这一点-我更喜欢“不要重复你自己”,但这是一个风格问题……你所说的“域完整性”是什么意思?这类规则可能太复杂,无法在SQL的有限功能中实现,即使使用触发器、FKs、数据类型、约束等。请在客户端代码中实现。@RickJames我指的是确保给定的列值必须在指定的可能值组中