根据附加列

时间:2018-08-01 13:12:58

标签: mysql sql database-design foreign-keys

我有以下业务规则:

  1. 一个帐户可以拥有零个或多个许可证。
  2. 每个许可证都有一个唯一的Guid。
  3. 每个许可证都已预先分配给一个帐户。
  4. 所有安装都属于给定帐户。
  5. 所有商业安装都需要许可证。
  6. 没有两个commercial_installation可以使用相同的许可证。
  7. 可以删除commercial_installation,然后可以在新的commercial_installation上使用许可证。
  8. 商业安装只能使用已分配给安装帐户的许可证。

如何执行最后一条规则? 商业安装只能使用已分配给安装帐户的许可证。换句话说,对于给定的GUID要存储在commercial_installations中,licenses.accounts_id必须等于installations.accounts_id。请参阅底部的示例数据。

enter image description here

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-adb5750685a9d6f23460-0d77-400e-ae96-13f436e40245仅存在于commercial_installationscommercial_installations.id1的{​​{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 |
+--------------------------------------+-------------+

2 个答案:

答案 0 :(得分:0)

您当然可以在应用程序的逻辑中实施它,但是我想您想在数据库级别执行它。

我在这里看到的唯一选项是为INSERTUPDATEDELETE操作添加触发器。普通的外键不会帮您做到这一点。

我喜欢这个问题,因为我以前曾遇到过这个问题,所以并没有真正花时间在这里正式询问这个问题。

答案 1 :(得分:0)

只需将account_ID传播到commercial_installations。还需要其他几个唯一约束(标记为SK(超键,键的超集))用作模型中FK的目标。

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