【问题标题】:Using part of a primary key as a foreign key使用主键的一部分作为外键
【发布时间】:2013-11-14 05:54:18
【问题描述】:

我正在构建一个小型 MYSQL 数据库,目前我的实体 HOME 存在问题。它的属性是 ROOM_NUM 和 BUILD_CODE。两者组成一个复合主键,外键 BUILD_CODE 引用它所在的建筑物。

我想知道是否可以让 BUILD_CODE 成为单个字符('a'、'b'、'c' 等),然后让 HOME 的主键类似于“A302”或“B205”。该主键的第一个字符将引用 BUILD_CODE,其余数字是房间号。然后我会有一个唯一的单值主键。我问的原因是我不必在我的 PERSON 表中有多个外键来引用 HOME。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    您可以使用代理键(序列)作为实体 HOME 的主键,并将其用作 PERSON 的外键。然后为BUILD_CODE和ROOM_NUM声明一个唯一的key来保持组合的唯一性。

    【讨论】:

      【解决方案2】:

      听起来 HOME 需要自己的单独标识符。 ID 是什么并不重要……只要它是唯一的。

      考虑以下几点:

      mysql> CREATE TABLE HOME (ID INTEGER NOT NULL auto_increment, ROOM_NUM INTEGER, BUILD_CODE VARCHAR(1), PRIMARY KEY(ID));
      Query OK, 0 rows affected (0.14 sec)
      
      mysql> CREATE TABLE PERSON(ID INTEGER NOT NULL auto_increment, NAME VARCHAR(255), HOME_ID INTEGER, PRIMARY KEY(ID), FOREIGN KEY(HOME_ID) REFERENCES HOME(ID));
      Query OK, 0 rows affected (0.14 sec)
      
      mysql> INSERT INTO HOME (ROOM_NUM, BUILD_CODE) VALUES (302, "A"), (205, "B");
      Query OK, 2 rows affected (0.06 sec)
      Records: 2  Duplicates: 0  Warnings: 0
      
      mysql> SELECT * FROM HOME;
      +----+----------+------------+
      | ID | ROOM_NUM | BUILD_CODE |
      +----+----------+------------+
      |  1 |      302 | A          |
      |  2 |      205 | B          |
      +----+----------+------------+
      2 rows in set (0.00 sec)
      
      mysql> INSERT INTO PERSON (NAME, HOME_ID) VALUES ("someone", 1);
      Query OK, 1 row affected (0.05 sec)
      
      mysql> SELECT * FROM PERSON;
      +----+---------+---------+
      | ID | NAME    | HOME_ID |
      +----+---------+---------+
      |  1 | someone |       1 |
      +----+---------+---------+
      1 row in set (0.00 sec)
      
      mysql> SELECT PERSON.NAME, HOME.BUILD_CODE, HOME.ROOM_NUM FROM HOME JOIN PERSON ON PERSON.HOME_ID = HOME.ID;
      +---------+------------+----------+
      | NAME    | BUILD_CODE | ROOM_NUM |
      +---------+------------+----------+
      | someone | A          |      302 |
      +---------+------------+----------+
      1 row in set (0.00 sec)
      

      你看,HOMEID 值并没有说明它的其余数据,这并不重要...... 你只是使用该字段作为工具将两者结合在一起

      当然,您也可以轻松地将INSERTed 将BUILD_CODEROOM_NUM 字段串联到ID 字段中......这也很好。但请记住,(a)字符串查找比整数查找使用更多的资源,并且(b)这只是您的应用程序需要维护的另一件事(例如:如果您从将房间号计算为 A302 开始会发生什么,但是在看到更大的房间号后,您决定选择 A00302?您必须检查整个表格 - 以及所有关联 - 并更新 ID。这不是非常理想)。

      【讨论】:

      • 这对我正在做的事情来说是完美的。该数据库主要用于测试我的团队正在构建的软件。如何从 BUILD_CODE 和 ROOM_NUM 中创建串联的主键?
      • 首先,您必须确保ID 字段是VARCHAR,而不是自动递增的INTEGER。然后你可以这样做:INSERT INTO HOME (ID, ROOM_NUM, BUILD_CODE) VALUES (CONCAT("A", 302), 302, "A");
      • 有没有办法让它自动从 ROOM_NUM 和 BUILD_CODE 派生 ID,或者我只需要为输入到表中的每个实体手动执行它?
      • 简短的回答:不。长答案是,有几种方法可以完成类似的事情,根据你真正想要完成的事情......(1)你可以再次让TRIGGER根据其他两个添加这个值价值观。 (2) 创建一个VIEW,它有点像SELECT 查询,其行为类似于一个表。 (您的VIEW 将具有ID 字段,因此您可以在上面使用JOIN。)(3)完全放弃ID 字段,并给PERSON 两列——一列用于ROOM_NUM,一个用于BUILD_CODE,然后JOIN 用于两个这些字段。
      • 我主要担心表 HOME 是多余的。如果它的键只是 ROOM_NUM 和 BUILD_CODE,它们是 PERSON 中的 FK,我还不如完全删除表,让 PERSON 直接与 BUILDING 相关。
      猜你喜欢
      • 2012-09-22
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 2010-10-22
      • 2018-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多