两个相互引用的postgresql表

两个相互引用的postgresql表,sql,postgresql,sqlalchemy,foreign-keys,relationship,Sql,Postgresql,Sqlalchemy,Foreign Keys,Relationship,问题可能是基本的,我没有任何数据库方面的经验 我有一个postgres数据库和一些表。其中两个是日期和账户 日期表有一个账户id字段,该字段引用了账户表中的id表,还有一个余额字段,表示该账户在该日期的余额。因此,许多日期实体可能引用一个账户实体,多对一,好的 但是账户表也有一个实际_日期字段,该字段必须引用该账户的实际余额的日期实体。一个账户实体可以引用一个实际的日期实体,但是日期实体可以有一个或零个账户实体引用它。如果它确实有一个帐户引用了它的实际日期,它将始终是同一个帐户,日期本身引用了帐

问题可能是基本的,我没有任何数据库方面的经验

我有一个postgres数据库和一些表。其中两个是
日期
账户

日期
表有一个
账户id
字段,该字段引用了
账户
表中的
id
表,还有一个
余额
字段,表示该账户在该日期的余额。因此,许多
日期
实体可能引用一个
账户
实体,多对一,好的

但是
账户
表也有一个
实际_日期
字段,该字段必须引用该账户的实际余额的
日期
实体。一个
账户
实体可以引用一个实际的
日期
实体,但是
日期
实体可以有一个或零个
账户
实体引用它。如果它确实有一个帐户引用了它的
实际日期
,它将始终是同一个帐户,
日期
本身引用了
帐户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
);

另外,我用init.sql创建表,但用sqlalchemy处理它们,如果有人能演示如何用它定义这样的模型,那就太好了。

正如我写的那样,sql脚本永远不会工作,原因有二:

  • 外键只能引用表的主键,不能引用表中的任意列。因此,实际日期id应该是
    整数
    ,以便能够引用
    日期
    表的主键

  • 不能引用尚未创建的表,因此必须在创建两个表之后创建帐户和日期之间的外键

  • 对于循环外键,通常更容易将它们中的至少一个定义为可延迟的,这样您就可以插入它们,而不需要中间的空值

    因此,大致上是这样的(假设
    用户
    已经存在)


    一开始最好避免循环引用。由于您希望确保每个帐户只存在一个“当前余额”,因此可以通过在日期表中添加一个标志并删除帐户表中的
    actual\u date\u 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

    此语句的实际含义是什么:“日期实体可以有一个或零个帐户实体引用它”?此表中没有账户实体的记录代表什么?日期表中的记录将保留某个账户在某一天的余额。还有其他的桌子。事件表引用了日期,因此我可以跟踪事件发生的时间以及在特定日期发生的事件使用同一个表(日期)保存关于两个不同实体(余额和事件)的信息对我来说似乎不是一个好的设计决策。为什么不将“日期”表替换为“账户余额”表(如果您愿意,您可以为每个账户的当前余额添加一个标志),只需为您的事件添加一个日期属性?我认为某些账户可能会有几天没有交易,按天搜索事件可能更有效,而不是在所有事件中搜索。但我可能错了,正如我所说的,我对数据库没有过期性。为什么这是一个糟糕的设计?另外,我已经用flag is\u current\u balance作为一匹没有名字的马。这是一个非常好的答案,谢谢!但在帐户中保留对实际日期的引用不是比每次都搜索它更有效吗?或者约束还保留对当前余额的日期记录的引用?搜索当前余额是有效的,因为它将通过唯一索引完成,因此无论表的大小,它在时间上几乎是恒定的。
    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;