[英]Two postgresql tables referencing each other
问题可能是基本的,我对数据库没有任何经验。
我有一个带有一些表的 postgres 数据库。 其中两个是dates
和accounts
。
date
表有一个account_id
字段引用account
表中的一个id
表和一个balance
字段,该字段表示该帐户在该日期的余额。 因此,许多date
实体可以引用一个account
实体,多对一,好吧。
但是account
表也有一个actual_date
字段,它必须引用date
实体,以及该帐户的实际余额。 一个account
实体可以引用一个实际date
实体,但date
实体可以有一个或零个account
实体引用它。 如果它确实有一个帐户用它的actual_date
引用它,它总是同一个帐户, date
本身用account_id
引用。
这是一种什么样的关系? 甚至有可能实施吗? 如果是,我该怎么做?
我想出了这段代码,但我不知道它是否符合我的想法。
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users,
actual_date_id DATE UNIQUE REFERENCES dates
);
CREATE TABLE dates (
id SERIAL PRIMARY KEY,
account_id INT REFERENCES accounts,
date DATE,
balance INT,
unconfirmed_balance INT
);
PS 我使用 init.sql 创建表,但使用 sqlalchemy 与它们一起工作,如果有人也能展示如何用它定义这样的 model,那就太好了。
正如所写的 SQL 脚本将永远无法工作,原因有两个:
外键只能引用表的主键,不能引用其中的任意列。 因此 actual_date_id 应该是integer
以便能够引用dates
表的主键。
您不能引用尚未创建的表,因此必须在创建两个表之后创建帐户和日期之间的外键。
使用循环外键通常更容易将它们中的至少一个定义为可延迟的,这样您就可以插入它们而无需例如中间 NULL 值。
所以类似的东西(假设users
已经存在)
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users,
actual_date_id integer UNIQUE -- note the data type
);
CREATE TABLE dates (
id SERIAL PRIMARY KEY,
account_id INT REFERENCES accounts,
date DATE,
balance INT,
unconfirmed_balance INT
);
-- now we can add the foreign key from accounts to dates
alter table accounts
add foreign key (actual_date_id)
references dates (id)
deferrable initially deferred;
一开始最好避免循环引用。 由于您想确保每个帐户仅存在一个“当前余额”,因此可以通过在日期表中添加一个标志并删除帐户表中的实际日期actual_date_id
来实现。
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users
);
CREATE TABLE dates (
id SERIAL PRIMARY KEY,
account_id INT REFERENCES accounts,
is_current_balance boolean not null default false,
date DATE,
balance INT,
unconfirmed_balance INT
);
-- this ensures that there is exactly one row with "is_current_balance = true"
-- for each account
create unique index only_one_current_balance
on dates (account_id)
where is_current_balance;
在将dates
中的一行更改为“当前行”之前,您需要将现有行重置为false
。
无关,但是:
对于现代 Postgres 版本, 建议使用identity
列而不是serial
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.