【发布时间】:2019-01-09 01:56:11
【问题描述】:
我有以下业务规则:
- 一个帐户可以有零个或多个许可证。
- 每个许可证都有一个唯一的 guid。
- 每个许可证都预先分配给给定帐户。
- 所有安装都属于给定帐户。
- 所有商业安装都需要许可证。
- 任何两个商业安装都不能使用同一个许可证。
- 可以删除商业安装,然后可以将许可证用于新的商业安装。
- commercial_installation 只能使用已分配给安装帐户的许可证。
我如何执行最后一条规则? 商业安装只能使用已分配给安装帐户的许可证。 或者换句话说,对于给定的 guid要存储在commercial_installations 中,licenses.accounts_id 必须等于installations.accounts_id。请参阅底部的示例数据。
CREATE TABLE IF NOT EXISTS accounts (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(45) NOT NULL,
otherData VARCHAR(45) NULL,
PRIMARY KEY (id))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS licenses (
guid CHAR(36) NOT NULL,
accounts_id INT NOT NULL,
otherData VARCHAR(45) NULL,
PRIMARY KEY (guid),
INDEX fk_licenses_accounts1_idx (accounts_id ASC),
CONSTRAINT fk_licenses_accounts1
FOREIGN KEY (accounts_id)
REFERENCES accounts (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS installations (
id INT NOT NULL AUTO_INCREMENT,
accounts_id INT NOT NULL,
otherData VARCHAR(45) NULL,
PRIMARY KEY (id),
INDEX fk_installations_accounts1_idx (accounts_id ASC),
CONSTRAINT fk_installations_accounts1
FOREIGN KEY (accounts_id)
REFERENCES accounts (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS open_installations (
installations_id INT NOT NULL,
otherData VARCHAR(45) NULL,
PRIMARY KEY (installations_id),
CONSTRAINT fk_open_installations_installations1
FOREIGN KEY (installations_id)
REFERENCES installations (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS commercial_installations (
installations_id INT NOT NULL,
licenses_guid CHAR(36) NOT NULL,
otherData VARCHAR(45) NULL,
PRIMARY KEY (installations_id),
UNIQUE INDEX fk_commercial_installations_licenses1_idx (licenses_guid ASC),
CONSTRAINT fk_commercial_installations_installations1
FOREIGN KEY (installations_id)
REFERENCES installations (id)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_commercial_installations_licenses1
FOREIGN KEY (licenses_guid)
REFERENCES licenses (guid)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
给定以下示例数据:
-
b5060518-f87e-4acc-82c8-adb5750685a9和d6f23460-0d77-400e-ae96-13f436e40245只能存在于commercial_installations中,其中commercial_installations.id是1或2。 - 同样,
8739ef62-7fff-4913-81de-3d00e8f50ecb对应于3。 - 同样,
36cc0787-5cb9-4c3a-b79d-1dcfb83d2794对应于4。
帐户
+----+-----------+
| id | name |
+----+-----------+
| 1 | Account 1 |
| 2 | Account 2 |
| 3 | Account 3 |
| 4 | Account 4 |
+----+-----------+
许可证
+--------------------------------------+-------------+
| guid | accounts_id |
+--------------------------------------+-------------+
| b5060518-f87e-4acc-82c8-adb5750685a9 | 1 |
| d6f23460-0d77-400e-ae96-13f436e40245 | 1 |
| 36cc0787-5cb9-4c3a-b79d-1dcfb83d2794 | 2 |
| 8739ef62-7fff-4913-81de-3d00e8f50ecb | 3 |
+--------------------------------------+-------------+
安装
+----+-------------+
| id | accounts_id |
+----+-------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 3 |
| 4 | 2 |
+----+-------------+
【问题讨论】:
-
@RaymondNijland 我目前这样做,但仅限
guid。我可以创建licenses主键组合guid-accounts_id或添加第二个约束commercial_installations.accounts_id引用accounts.id。但是如果我这样做了,则不会强制执行commercial_installations.accounts_id与installations.accounts_id相同,并且我不能添加这样的约束,因为installations.accounts_id已经引用了acccounts.id。我绕了一圈又一圈…… -
"但是如果我这样做了,
commercial_installations.accounts_id与installations.accounts_id相同,我无法添加这样的约束,因为 installations.accounts_id 已经引用了 acccounts.id。周围和周围我去“真的,现在我看起来更好了......我认为你需要使用 BEFORE INSERT 触发器来检查commercial_installations.accounts_id是否与installations.accounts_id相同,方法是选择许可证和帐户。你能添加一些表的示例记录? -
@RaymondNijland 我添加了示例数据。我在想一个触发器。我犹豫不决,因为每当我这样做时,我都需要让它抛出一些自定义异常,无论我记录得多么好,我都会忘记它并让自己有很大的机会。如果是触发器,您建议如何实施?谢谢
-
在深入了解您的数据模型之后。我还想知道为什么有一个看起来不需要的
commercial_installations表。除了“商业”对我来说听起来更像是一种元数据(类型)。使用元数据作为表名或多或少是一种 SQL 反模式。我将删除commercial_installations表并将installation_id字段添加到许可证表中,也无需存储两次 guid。除非表 @987654356 @ 表示从表installations到坏 MySQL 的继承不像 PostgreSQL 那样支持继承 -
@RaymondNijland - “在我看来,除了“商业”之外,它更像是一种元数据(类型)。使用元数据作为表名或多或少是一种 SQL 反模式。” hmmm ,在多个子表之间有一个具有外键弧的建模子类型的完善约定,在我看来,安装类型的实现符合这种模式。这必须比具有复杂检查约束的单个表更好,这些约束针对不同类型的安装执行规则。正如你确实承认你提到了继承。
标签: mysql sql database-design foreign-keys