Sql 如何避免循环引用情况
关于SQL表、循环引用和外键的建议 我对SQL非常陌生(大约一个月左右),所以请原谅我后来的任何不幸幼稚。 我正在做一个关于故事的项目,其中一个用户可以开始一个故事,另一个用户可以添加到该故事中。 目前,我的两个主要表格是故事和段落。 故事由段落组成。段落只是一段文字。 故事模式如下所示:Sql 如何避免循环引用情况,sql,database,postgresql,circular-dependency,Sql,Database,Postgresql,Circular Dependency,关于SQL表、循环引用和外键的建议 我对SQL非常陌生(大约一个月左右),所以请原谅我后来的任何不幸幼稚。 我正在做一个关于故事的项目,其中一个用户可以开始一个故事,另一个用户可以添加到该故事中。 目前,我的两个主要表格是故事和段落。 故事由段落组成。段落只是一段文字。 故事模式如下所示: stid varchar not null primary key, title text not null, description text, created_at timestamptz DEFAULT
stid varchar not null primary key,
title text not null,
description text,
created_at timestamptz DEFAULT now()
prid bigint not null primary key,
story varchar not null REFERENCES stories(stid),
maintext text,
writer text not null REFERENCES users(username),
parentpr bigint, //the previous paragraph
childpr bigint, //the next paragraph
created_at timestamptz DEFAULT now()
CREATE TABLE paragraph (
paragraph_id SERIAL PRIMARY KEY,
story_id INTEGER NOT NULL REFERENCES stories (story_id),
position INTEGER NOT NULL,
-- Other columns
created_at TIMESTAMPTZ DEFAULT now()
)
段落模式如下所示:
stid varchar not null primary key,
title text not null,
description text,
created_at timestamptz DEFAULT now()
prid bigint not null primary key,
story varchar not null REFERENCES stories(stid),
maintext text,
writer text not null REFERENCES users(username),
parentpr bigint, //the previous paragraph
childpr bigint, //the next paragraph
created_at timestamptz DEFAULT now()
CREATE TABLE paragraph (
paragraph_id SERIAL PRIMARY KEY,
story_id INTEGER NOT NULL REFERENCES stories (story_id),
position INTEGER NOT NULL,
-- Other columns
created_at TIMESTAMPTZ DEFAULT now()
)
我正在考虑在故事模式中添加一个headpara和lastpara列(使用ALTER),这样我就可以轻松访问第一段和最后一段,但这会造成循环引用的情况,因为故事将引用段落,反之亦然。这样行吗?当我开始处理大量的数据和查询时,它会变得更加复杂吗
我想到了一个解决方案,其中我有另一个表:
故事段落分配。模式:
ID primary key
story REFERENCES stories(stid),
headpara REFERENCES paragraph(prid),
lastpara REFERENCES paragraph(prid)
出于某种原因,我不相信这种解决办法。我觉得这是多余的。这不是一个多对多的情况。但是段落需要引用故事,我需要能够访问故事的第一段和最后一段
另一种可能的解决方案是在段落模式中有两个布尔列,称为head和tail,这样第一个段落就可以用
WHERE story == stID AND head == True.
想法?当我的段落表非常大时,这个解决方案似乎会成为一个问题。非常感谢。您可以用任何一种方法来解决问题。如果你知道头一段和最后一段是非常重要的,那么在故事中引用它们就可以了 在这两种情况下,维护关系完整性都有一点挑战。大概,您希望标题和最后几段在同一个故事中。为此,您需要一个复合键。您需要使用单独的
altertable
语句添加键。因此:
alter table paragraph add constraint unq_paragraph_story_prid unique (story, prid);
alter table stories add constraint fk_stories_headpara
foreign key (stid, headpara) references paragraph(story, prid);
alter table stories add constraint fk_stories_lastpara
foreign key (stid, lastpara) references paragraph(story, prid);
类似地,如果使用标志,则需要确保每个类型集只有一个标志。更新时可能会有点痛苦。该约束看起来像:
create unique index unq_paragraph_headpara paragraph(story) where head = 1;
create unique index unq_paragraph_lastpara paragraph(story) where last = 1;
有关命名和其他事项的注释:
s应该是数字,如果可以的话。这简化了外键引用id
- id的名称应完整拼写(
或paragraphId
)或简单地paragraphId
。如果使用id
,可能会与另一个表混淆prid
- 并非所有数据库都支持筛选的唯一索引。在这些情况下,您需要使用触发器或其他机制