【问题标题】:more flexible relationship between two tables in database?数据库中两个表之间更灵活的关系?
【发布时间】:2016-12-08 00:58:38
【问题描述】:

假设有两个表。(我做了示例表只是为了解释我的想法的概念,定义它会有一些错误。)

TableA“用户”

CREATE TABLE user
(
  id serial PRIMARY KEY
  name character varying(80) UNIQUE NOT NULL,
)

表B“历史”

CREATE TABLE history
(
  id serial PRIMARY KEY,
  action character varying(80) NOT NULL,
  CONSTRAINT history_action_key UNIQUE (name)
)

我认为有两种方法可以在两个表之间建立关系。

一种方式:在一个表中添加 ForeignKey 约束

CREATE TABLE user
    (
      id serial PRIMARY KEY,
      name character varying(80) NOT NULL UNIQUE,
      history_id integer REFERENCES history
    )

这意味着在用户表中还有一个名为history_id的字段用于指向与FK相关的历史记录。对吧?

第二种方式:您正在创建新表(比如说 TableC 'relationship')。 TableC 将只显示 TableA 和 TableB 之间的关系

CREATE TABLE relationship
(
  id serial PRIMARY KEY,
  user_id integer NOT NULL REFERENCES remann_users (id),
  history_id integer NOT NULL REFERENCES history,
)

所以我的问题

第二种在数据库中存储数据的方式更灵活吗?

我觉得第二种方式似乎更灵活 因为用户表和历史表在单独的表中完全分开。只是另一个表有数据来说明他们的关系。但第一种方式似乎用户表在其表中有一个字段“history_id”。所以我觉得它的方式更像是两个表之间的耦合。

我的想法对吗?


我想我首先对 manyTomany 关系感到困惑。

'user' 表有如下数据

包名

1 约翰

2 亚当

3 凯利

'history' 表有如下数据

PK 动作

1 打过篮球

玩过2个电子游戏

现在我想在用户和历史之间建立关系。

如果 John 打篮球,Adam 打篮球,Kelly 打电子游戏,我可以通过在 user 表中多放一列来建立关系。

'用户'表

pk 名称 fk

1 约翰 1

2 亚当 1

3 凯利 2

但如果有约翰打篮球同时打电子游戏的情况。这成了许多Tomany的关系。我需要像下面这样来显示这种关系。

'用户'表

pk 名称 第一个动作(fk) 第二个动作(fk)

1 约翰 1 2

2 亚当 1 空

3 凯利 2 NULL

但这是个坏主意,因为如果您想为某个特定用户添加更多操作,则必须更改架构。例如,用户打篮球、踢足球和玩视频游戏。您需要添加第三个操作(fk),其他用户行将具有空值。

因此您可以制作另一个表格来组合两个表格而不会出现此问题。这将是我上面解释的第二种方式。制作另一个表来显示两个表之间的关系只是在多对多情况下提高效率的方法。对吧?

这是我对您的回答感到困惑的地方。 “更灵活” 更灵活意味着如果您有第二种方式的桥接表,则显示 m2m 数据更灵活,或者只是 m2m 关系更灵活?我比什么更困惑?

【问题讨论】:

  • 我更新为使用更简洁的创建表语法。
  • 我认为上面有一些错误,不知道你想如何澄清它们,但我保持原样。
  • 还有几点,不要使用character varying(80) 代替name,使用text。另外,不要使用id,使用user_idid_user(我最喜欢的)。如果将所有 pkey 标记为id,则不能使用USINGNATURAL JOIN,这也会使您的查询更加混乱。
  • 谢谢,我只是想用示例表来解释我的问题的概念。我实际上并没有注意语法。那么你对我的问题有什么想法吗?我想知道用 FK 建立两个表之间关系的两种方法是否有区别,或者一种比另一种更灵活。

标签: database postgresql foreign-keys table-relationships


【解决方案1】:

这意味着在用户表中还有一个名为history_id的字段用于指向与FK相关的历史记录。对吧?

随便起个名字,不过是的。

我觉得第二种方式似乎更灵活,因为用户表和历史表在单独的表中完全分开。只是另一个表有数据来说明他们的关系。但第一种方式似乎用户表在其表中有一个字段“history_id”。所以我觉得它的方式更像是两个表之间的耦合。 ... 我的想法正确吗?

我的想法让我很兴奋。是的,你是对的。您所称的 relationship 表建立了数据库管理员所称的 Many-to-many 模型。

  • 更灵活。
  • 速度也较慢。
  • 查询更加困难。

问题是一个用户可以有多个历史,如果他们不能,你为什么要让你的所有查询更复杂来支持它?

在 PostgreSQL 的普通 M2M 表中,您会得到类似的东西,

CREATE TABLE user (
  user_id serial PRIMARY KEY,
  name    text   NOT NULL
);
CREATE TABLE history (
  history_id serial PRIMARY KEY,
  tz         timestamp DEFAULT NOW()
);
CREATE TABLE relationship (
  user_id int REFERENCES users,
  history_id integer REFERENCES history,
  PRIMARY KEY (user_id, history_id)
)
  • 如果一个用户有两个历史记录会怎样?

喜欢,

INSERT INTO relationship VALUES (1,1), (1,2);
  • 如果我们有两个历史相同的用户会怎样?

喜欢,

INSERT INTO relationship VALUES (1,1), (2,1);

如果这些在您的应用中不可行,请不要使用多对多。

【讨论】:

  • 这将是一个用户和许多历史之间的关系。实际上为此目的,我不必制作多对多模型。我知道这一点。但目前,数据库中的数据结构可能会在以后发生变化。我知道如果我建立多对多关系,检索数据和保存数据会更加困难。我认为最好将这些表分开保存并使其更灵活地适应未来的变化。因为 M2M 关系可以涵盖如何调用 oneToMany 关系(?)的功能,我用上述问题的第二种方式进行了解释。
  • 如果您有一个用户和多个历史记录,并且一个历史记录对多个用户是不可能的,那么只需将 FOREIGN KEY 存储在历史记录中。 CREATE TABLE history ( id SERIAL NOT NULL, user_id int REFERENCES user ); 现在您可以插入两个指向同一用户的历史记录。
  • 那么您的意见是,如果没有必要,最好不要使用M2M关系,必须尽可能使用M2M?我想知道 M2M 模型的这种灵活性对于将来的重构和修改可能会更好,即使你一开始会变得更难处理它。
  • 我的建议是在您需要多对多之前远离m2m。
  • 你能给我更明确的建议吗?这是因为性能(较慢)和处理难度(查询)比灵活性(更多)更关键?或者实际上这种灵活性对于那些较慢的性能和查询难度并没有太大的好处?我希望你能更详细地解释为什么 m2m 更灵活。 “更多”的定义似乎很模糊。如果你能举一些真实的例子,那就太棒了。
猜你喜欢
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多