当前位置: 首页 > 面试题库 >

如何在PostgreSQL中实现多对多关系?

公孙宏远
2023-03-14
问题内容

我相信标题是不言而喻的。如何在PostgreSQL中创建表结构以建立多对多关系。

我的例子:

Product(name, price);
Bill(name, date, Products);

问题答案:

SQL DDL(数据定义语言)语句如下所示:

CREATE TABLE product (
  product_id serial PRIMARY KEY  -- implicit primary key constraint
, product    text NOT NULL
, price      numeric NOT NULL DEFAULT 0
);

CREATE TABLE bill (
  bill_id  serial PRIMARY KEY
, bill     text NOT NULL
, billdate date NOT NULL DEFAULT CURRENT_DATE
);

CREATE TABLE bill_product (
  bill_id    int REFERENCES bill (bill_id) ON UPDATE CASCADE ON DELETE CASCADE
, product_id int REFERENCES product (product_id) ON UPDATE CASCADE
, amount     numeric NOT NULL DEFAULT 1
, CONSTRAINT bill_product_pkey PRIMARY KEY (bill_id, product_id)  -- explicit pk
);

我强烈建议您这样做,因为产品名称几乎不是唯一的(不是很好的“自然键”)。此外,强制使用唯一性并在外键中引用该列通常比使用存储为或的字符串便宜(4字节integer(甚至8字节bigint))。text``varchar

  • 不要使用基本数据类型的名称date作为 标识符 。尽管这是可能的,但这是不好的样式,并导致令人困惑的错误和错误消息。使用合法的,小写的,未加引号的标识符。切勿使用保留字,并尽可能避免使用双引号混合大小写标识符。

  • “名字”不是一个好名字。我将表的列重命名productproductproduct_name或类似)。那是一个更好的 命名约定 。否则,当您在查询中联接几个表时(在关系数据库中做 很多事情) ,最终将得到多个名为“ name”的列,并且必须使用列别名来解决混乱情况。那没有帮助。另一个广泛使用的反模式将只是“ id”作为列名。
    我不确定a的名称是什么billbill_id在这种情况下可能就足够了。

  • price数据类型, numeric用于 精确 存储 所输入的 分数(任意精度类型,而不是浮点类型)。如果您只处理整数,则使integer。例如,您可以将 价格 另存 为美分

  • amount"Products"你的问题)进入连结表bill_product,是类型的numeric为好。同样,integer如果您只处理整数。

  • 您看到 外键bill_product吗?我创建了这两者,以级联更改:ON UPDATE CASCADE。如果aproduct_idbill_id应该更改,则更改将级联到其中的所有相关条目,bill_product并且没有中断。这些只是参考,没有意义。
    我也用ON DELETE CASCADEbill_id:如果法案被删除,它的细节与它死去。
    产品并非如此:您不想删除帐单中使用的产品。如果尝试这种方法,Postgres将抛出错误。您可以添加另一列来product标记过时的行(“软删除”)。

  • 这个基本示例中的所有列最终都为 NOT NULL ,因此NULL不允许使用值。(是的, 所有 列-主键列都是UNIQUE NOT NULL自动定义的。)这是因为NULL在任何列中值都没有意义。它使初学者的生活更加轻松。但是,您将无法轻松摆脱困境,无论如何您都需要了解NULL处理方法。其他列可能允许NULL值,函数和联接可以NULL在查询等中引入值。

  • 阅读CREATE TABLE手册中的章节。

  • 主键通过在键列上具有唯一 索引 来实现,从而可以快速查询带有PK列的条件。但是,键列的顺序与多列键有关。由于在我的示例中PK onbill_product是打开的(bill_id, product_id),因此您可能想在just上添加另一个索引,product_id或者(product_id, bill_id)如果您有查询在寻找给定product_id和no的查询bill_id



 类似资料:
  • 问题内容: 我正在制作一个具有多对多关系的SQLite数据库,并使用以下代码将其分解为两个一对多的关系 错误: 有谁知道我该如何解决这个错误? 问题答案: 查看文档; 它向您表明,如果您在字段定义本身上指定了外键,则不应使用关键字本身。此外,正如 CL 指出的那样,您使用了太多逗号 。 ,即使单独指定约束,外键名称也不应放在括号中。 该语句可以满足您的要求: 还要注意,如果MODULEID是表MO

  • 我正在做一个小型的laravel项目来实现雄辩的关系,我主要有多个模型(项目、任务、用户、文件等) 一个项目可以分配多个用户,附加多个文件,也可以有多个任务。一个任务可以分配多个用户,也可以分配多个文件,以及多个其他东西。我已经谷歌和实施了hasManyPass,和归属许多关系,但我对关系感到困惑很多。有什么帮助吗? Project.php Task.php User.php 我得到的错误是,当我

  • 最好的办法还是写一个真实的项目,从博客项目开始。 了解关系(1对1,1对多)在mongoose里如何实现 UserSchema = new Schema({ ... contacts:[] }); 了解关系(1对1,1对多,多对多)在mongoose里如何实现 ContactSchema = new Schema({ ... owner: { type

  • 我需要在Firestore上建立多对多关系模型。以下是对这些要求的总结。 > 一家公司可以为一个项目雇佣许多承包商。承包商可以在不同的时间为多家公司的不同项目工作。 承包商或公司的数量不应受到限制,即应使用集合或子集合。 承包商应能够按公司进行查询;反之亦然,公司应该能够通过承包商进行查询。例如,(1)承包商可能要求提供他/她工作过的公司的清单,并按项目排序 就公司而言,承包商可以改变状态,例如工

  • 我有一个单向关系,其中一个实体有另一个实体的列表(一对多)。 我已将级联类型设置为级联类型。所有的,我得到了错误 在这条线上 我想更新现有的用户条目。如果我将上面的行替换为 它会创建重复条目。有什么解决办法吗。请帮帮我。我的代码:

  • 问题内容: 任何人都可以解释在设计带有示例的表时如何实现一对一,一对多和多对多关系吗? 问题答案: 一对一: 使用外键访问被引用的表: 您还必须在外键列()上设置唯一约束,以防止子表()中的多行与引用表()中的同一行相关。 一对多 :在关系的许多方面使用外键链接回“一个”侧: 多对多 :使用联结表(例如): 查询示例: