【问题标题】:SQL and relations between tablesSQL和表之间的关系
【发布时间】:2015-07-20 10:58:54
【问题描述】:

有好几次,我一直在重新理解数据库关系理论,但我仍然没有成功。我再试一次。

假设我有两张桌子: 动物:

CREATE TABLE animals (id INTEGER PRIMARY KEY, name TEXT);

和食物:

CREATE TABLE food (id INTEGER PRIMARY KEY, food TEXT);

我需要将这两个表连接起来。例如,我想从 animals 表中选择“猪”,并从 food 表中接收猪可以吃的所有东西。 我只是不明白如何将它们联系起来。我相信我可以在 food 表中添加一个外键,该外键将链接到 animal 表的主键,但有一个问题我无法弄清楚:

如果我从例如网络表单中输入数据库中的条目会怎样,我在其中输入动物名称和它吃的产品。动物名称转到第一个表并自动收到一个 id。它只是自动增量。所以,为了使它成为第二个表的关系,我必须从第一个表中选择新的 ID!所以我们得到了三个 sql 请求:

1) INSERT INTO animals (name) VALUES ('pig);

2) SELECT id FROM animals WHERE name='pig';(我们将其存储在一个变量中,暂时不重要)

3)INSERT INTO food (product, animal_id) VALUES ('something', 'id of a pig');

我只是觉得这是错误的。 或者我的大脑无法理解如此复杂的抽象。

请指教。

【问题讨论】:

  • 您使用的是哪个 DBMS? Postgres?
  • 嗯,Postgress 可以放入数组,这会容易得多,但我想要的是,嗯,通用的方式,适用于所有数据库 MS。

标签: sql postgresql


【解决方案1】:

您需要一个与AnimalsFood 相关的联结表。这看起来像:

CREATE TABLE AnimalFoods (
    id INTEGER PRIMARY KEY,
    AnimalId int references Animal(id),
    FoodId int references Food(id)
);

然后您可以使用这些表之间的各种连接来回答您的问题。

【讨论】:

    【解决方案2】:

    这就是你实现这种多对多关系的方式:

    您可以使用data-modifying CTE单个查询来完成您描述的任务:

    WITH ins AS (
       INSERT INTO animals (name) VALUES ('pig')
       RETURNING animal_id  -- return generated ID immediately
       )
    INSERT INTO animal_food (food_id, animal_id)  -- m:m link table
    SELECT food_id, animal_id  -- food_id passed as 2nd param
    FROM   ins;
    

    假设我们使用已知存在的食物进行操作(就像从下拉菜单中选择它一样。否则您需要多一步来查找食物,或者可能还需要在INSERT 那里查找一行:

    ...仍然是单个查询。

    链接的答案提供了一些关于并发事务竞争条件的更棘手问题的一些见解。

    【讨论】:

      【解决方案3】:

      动物可以吃多种食物吗?如果没有,那么您可以让animal 成为food 餐桌上的主键。如果animal 可以有多种食物,那么您可以在food 表中拥有一个自动增量ID(就像animal 表中的那个)。正如 jWeaver 所指出的,在 food 表中有一个 parentID 作为引用 animal 表的外键。

      【讨论】:

        【解决方案4】:

        使用parentId 创建一个animal 表,然后在您的food 表中使用该parentId 列进行引用。

        示例:

        Animal(ParentId integer, NAME TEXT);
        

        Food(FoodId integer, ParentId integer, Name Text);
        

        就是这样。确保您在food 表中使用相同的ParentId 来为特定动物推荐食物。

        希望,这对你有意义。

        【讨论】:

        • 但是当我向数据库添加条目时如何生成这个 ParentID?
        • 您使用的是哪个 RDBMS?
        • sqlite、mysql 等等。
        【解决方案5】:

        如果不同的动物吃同一种食物,你应该用两个相关表的外键定义一个表:

        CREATE TABLE animals (id INTEGER PRIMARY KEY, name TEXT);
        CREATE TABLE food (id INTEGER PRIMARY KEY, food TEXT);
        CREATE TABLE eat (animal_id INTEGER, food_id INTEGER,
             FOREIGN KEY (animal_id) REFERENCES animals(id),
             FOREIGN KEY (food_id) REFERENCES food(id));
        

        【讨论】:

          【解决方案6】:

          假设一只动物会吃多种食物,而多种动物可以吃同样的食物。您需要与动物和食物建立多对多关联。

          Animal(id integer, name Text)
          Food(id integer, name TEXT)
          AnimalFood(animalId integer,foodId integer)
          
          CREATE TABLE animals (id int(11) not null auto_increment primary key, name text);
          CREATE TABLE foods (id int(11) not null auto_increment primary key, name text);
          CREATE TABLE animal_foods (animal_id int(11) not null, food_id (11) not null);
          

          【讨论】:

            猜你喜欢
            • 2013-12-05
            • 1970-01-01
            • 2017-01-29
            • 2020-04-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-03
            相关资源
            最近更新 更多