基于附加列强制外键约束

sg2wtvxw  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(321)

我有以下业务规则:
一个帐户可以有零个或多个许可证。
每个许可证都有一个唯一的guid。
每个许可证都预先分配给一个给定的帐户。
所有安装都属于给定的帐户。
所有商业安装都需要许可证。
没有两个商业安装可以使用同一个许可证。
可以删除商业\u安装,然后可以在新的商业\u安装上使用许可证。
商业安装只能使用已分配给安装帐户的许可证。
如何执行最后一条规则?商业安装只能使用已分配给安装帐户的许可证。或者换句话说,对于要存储在 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.id1 或者 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 |
+----+-------------+
kmpatx3s

kmpatx3s1#

简单传播 account_IDcommercial_installations . 它还需要一些更独特的约束,标记为sk(superkey,密钥的超集)作为模型中fks的目标。

accounts {account_ID, account_name}
      PK {account_ID}

licenses {license_ID, account_ID}
      PK {license_ID}
      SK {license_ID, account_ID}     
      FK {account_ID} REFERENCES accounts {account_ID}

installations {installation_ID, account_ID, installation_TYPE}
      PK {installation_ID}
      SK {installation_ID, account_ID}     
      FK {account_ID} REFERENCES accounts {account_ID}

open_installations {installation_ID}
      PK {installation_ID}
      FK {installation_ID} REFERENCES installations {installation_ID}

commercial_installations {installation_ID, account_ID, license_ID}
     PK {installation_ID}
     AK {license_ID}              

     FK1 {installation_ID, account_ID} 
         REFERENCES installations {installation_ID, account_ID}

     FK2 {license_ID, account_ID} 
         REFERENCES licenses {license_ID, account_ID}
Notes:

All attributes (columns) NOT NULL

PK = Primary Key
SK = Superkey      (Unique)
AK = Alternate Key (Unique)
FK = Foreign Key
ergxz8rk

ergxz8rk2#

当然,您可以在应用程序的逻辑中强制执行它,但我猜您希望在数据库级别执行它。
我在这里看到的唯一选择是为 INSERT , UPDATE ,和 DELETE 操作。普通外键不适合您。
我喜欢这个问题,因为我以前也遇到过这个问题,所以我没有花时间正式问这个问题。

相关问题