【问题标题】:Connecting One table to Many tables连接一个表到多个表
【发布时间】:2011-05-07 06:42:42
【问题描述】:

我正在构建一个评论系统,人们可以在其中评论上传的文件、消息和待办事项。将注释表连接到其他各种表的最佳方法是什么?
可能的解决方案
解决方案一 - 使用两个字段的外键。

CREATE TABLE `comments`(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
foreign_key INT NOT NULL,
table_name enum('files','messages','to-do'),
user_id INT NOT NULL,
comment TEXT NOT NULL);

解决方案二 - 每个表都有一个数据库唯一的主键。所以我会使用 php 的 uniqid($prefix) 作为每个表的主键。

CREATE TABLE `comments`(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
foreign_key char(23) NOT NULL,
table_name enum('files','messages','to-do'),
user_id INT NOT NULL,
comment TEXT NOT NULL);

解决方案三 - 注释表中有多个外键

CREATE TABLE `comments`(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
files_id INT NOT NULL,
messages_id INT NOT NULL,
to_do_id INT NOT NULL,
user_id INT NOT NULL,
comment TEXT NOT NULL);

什么是最好的解决方案?感谢您的意见,如果我能澄清任何事情,请告诉我

EDIT解决方案三 中删除了 table_name,因为它是一个 copy_paste 错误 关于乔的回应

假设: 1)所有数据都已经转义。我们真的需要看到吗?
2) $fileId = "146"。
3) $userId = "432"。
4) $comment = "Stackoverflow 太棒了!"

插入

$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
 mysql_select_db('mydb');
 mysql_query("INSERT INTO `comments` (user_id,comment) VALUES($userId,$comment)");
 $commentId = mysql_insert_id();
 mysql_query("INSERT INTO `comments_files_xref` (file_id,comment_id)         VALUES($fileId,$commentId)");

【问题讨论】:

    标签: php mysql database-design foreign-keys foreign-key-relationship


    【解决方案1】:

    就个人而言,我会更加规范化设计。可能是这样的:

    【讨论】:

    • 感谢一位真正的 DBA 很高兴收到您的来信。我将采用您的解决方案。我过去做过类似的事情。我将编辑我的帖子以向人们展示如何为此模式执行插入/更新。如果他们不在基地,请告诉我,再次感谢
    【解决方案2】:

    多个备注:

    • 您不应该调用外键foreign_key,因为外键是一个约束,在某种程度上不是一个字段。它将表中的一个字段引用到另一个表上的索引,调用它的方式与您在引用的表上调用 PK 的方式相同,或者其他可识别的名称。
    • 外键约束仅适用于 innodb,如果您使用 MyISAM,请忘记它们并使用 PHP 进行大量检查。
    • 阅读http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html
    • 您应该在数据库中绘制您想要的内容的草图,或者使用mysql workbench(免费)等工具来帮助更好地查看架构。

    当我看到你的问题并且如果你想在这里使用约束,我将使用一个或另一个解决方案:

    1-

    CREATE TABLE `comments`(
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, // Which is your comment index
    idTable INT NOT NULL, // ID of the message
    table_name enum('files','messages','to-do'), // which it comes from
    user_id INT NOT NULL, // etc...
    comment TEXT NOT NULL);
    

    但有条件:

    • 文件消息_to-do_的PK必须具有相同的格式(INT)
    • 如果你想添加一个模块(files, messages _to-do_)会很困难

    2- 创建连接 cmets 和其他表的表:

    CREATE TABLE `comments`(
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, // Which is your comment index
    user_id INT NOT NULL, // etc...
    comment TEXT NOT NULL);
    
    CREATE TABLE `comments-files`(
    id_comments INT NOT NULL PRIMARY KEY,
    id_files INT NOT NULL PRIMARY KEY);
    

    等等。希望你能看到这里的重点。如果需要,您可以通过 http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html 添加约束。

    【讨论】:

      【解决方案3】:

      我刚刚在我现在的公司学习 Ruby on Rails,解决方案 1 是首选,因为 RoR 的 Active Record 可以将其处理为多态关系。

      回到主题,您使用的是 PHP,我更喜欢方案 1 或方案 3。如果将来有可能将注释表用于其他表,则方案 1 更可取。

      请注意,在解决方案 3 中,我认为不需要 table_name 列。您可以通过使用 id 填充 files_idmessages_idto_do_id 来确定评论是针对哪个表,然后将 2 个其他外键设置为 0。

      【讨论】:

        【解决方案4】:

        我会为每个可以评论的东西创建一个连接表,所以一个 files_cmets 表和一个 todo_cmets 表。但解决方案 1 将是一个替代方案。我会避免使用两个或三个解决方案……如果未来发生变化,可能会变得一团糟。

        【讨论】:

        • 创建多个评论表似乎维护起来很麻烦
        • @John,我不是在谈论多个评论表,而是在谈论多个联接表。连接表只有两个字段,其中一个是文件(或待办事项或其他)表的外键,另一个是连接表的外键。
        猜你喜欢
        • 2018-12-19
        • 1970-01-01
        • 2011-06-15
        • 2018-07-06
        • 2012-04-12
        • 1970-01-01
        • 2022-01-08
        • 1970-01-01
        相关资源
        最近更新 更多