Database Postgresql中的约束

Database Postgresql中的约束,database,postgresql,foreign-keys,constraints,Database,Postgresql,Foreign Keys,Constraints,所以,我想解决这个问题。我有一个数据库,我需要添加一个约束。我不知道我是否正确地解决了这个问题,因为我对这个问题还不熟悉,我正在尝试自学,但在搜索之后,我得出结论,可能是使用了外键约束 以下是我的数据库中此问题的相关表格: MusicGroup(idG, name, city, country, year) Edition(idG, titleE, year, editor) idG : FK(MusicGroup) Music(idG, titleM, length) idG : FK(M

所以,我想解决这个问题。我有一个数据库,我需要添加一个约束。我不知道我是否正确地解决了这个问题,因为我对这个问题还不熟悉,我正在尝试自学,但在搜索之后,我得出结论,可能是使用了外键约束

以下是我的数据库中此问题的相关表格:

MusicGroup(idG, name, city, country, year)

Edition(idG, titleE, year, editor)
idG : FK(MusicGroup)

Music(idG, titleM, length)
idG : FK(MusicGroup)

Album(idG, titleE)
idG, titleE : FK(Edition)

Track(idG, titleE, number, titleM)
idG, titleE : FK(Album)
idG, titleM : FK(Music)

Single(idG, titleE, titleM)
idG, titleE : FK(Edition)
idG, titleM : FK(Music)
以下是创建数据库的说明(也是我自己制作的):

我必须添加以下约束:专辑的标题必须是该专辑中某首曲目的标题,并且该曲目必须已作为单曲发布

所以我试着用这种方法来解决:

alter table Album
add foreign key (idG, titleE, titleE) references Track(idG, titleE, titleM)

alter table Track
add foreign key (idG, titleE, titleM) references Single(idG, titleE, titleM)
我不得不说,第一个外键似乎不太好,但正如我所说的,我对它还不熟悉


提前非常感谢您的帮助:)

我认为外键不是声明约束的最佳方式。我肯定会为此添加一个触发器。

首先:

  • 我希望每个表都有一个字段(非复合)主键。(这将导致需要另一个约束:一张专辑或一个版本不能包含来自多个艺术家的片段)我也感觉到强烈的腾腾性,可以使这些代理ID成为数字
  • 您使许多实体的名称都是唯一的。这可能不会持续(“最成功的作品”)
  • 一些命名:大多数人强烈建议不要在表名中混用大小写(它迫使你每次都引用标识符,这很难阅读,也可能会混淆DBMS,这可能与大小写无关,取决于月亮的相位)
  • 更多命名:我会称之为音乐
  • 我把艺术家叫做你们所说的音乐群
  • 我会将曲目重命名为“tracklist”或“album\u toc”(或Track\u album\u relation)
  • (也许)我会将单曲和专辑合并成一个实体(“zrecord”),并添加一个类型标签,这也允许单曲有反面,允许EP等
  • 我不知道编辑的目的是什么。您甚至可能需要一个类似的机制(“版本”,remasterings)来处理各个曲目

…接下来还有更多内容。

使用这组表定义,SQL FK不是一条可行之路。您需要的FK目标是曲目和单曲之间的连接(以表达专辑标题必须被称为该专辑上的曲目且必须被称为单曲的概念)

在SQL中,除了降低设计的NF级别并引入冗余之外,没有其他方法可以做到这一点(即使这样,我也不确定在这种特殊情况下它是否足够)

你说这是一本书的练习。那本书也涵盖了检查约束吗?如果是,练习的目的可能是让你写一个合适的检查约束。如果不是,我真的无法想象作者想到了什么样的解决方案


请注意,虽然SQL标准允许您在检查约束中编写几乎所有内容,但许多实现只提供了完整“理论”约束的非常有限的子集“由标准定义的功能。

您必须做的第一件事是获得一个可以引用的唯一约束,因为您允许对cd上的曲目使用重复标题,因此您必须更改此项:

ALTER TABLE album ADD named_after_track int not null;

ALTER TABLE album 
ADD FOREIGN KEY (idG, titleE, titleE, named_after_track)
REFERENCES track (idg, titleE, titleM, number)
DEFERRABLE INITIALLY DEFERRED;

希望这有帮助。请注意,延迟键将在提交时强制执行,因为在此之前我们不知道它是否有效。

我想我不理解您的符号(这个idG字段是什么?)。您能添加真实的表格定义吗?@wildplasser:这些是真实的表格定义。idG是一个组的id,一个识别字符串,类似于国家公民的身份证(只是做一个真实的比较,以便你能更好地理解)。@wildplasser:谢谢你试图帮助我。所有表上都有复合主键吗?我的意思是:如果你为这些东西添加实际的“CREATETABLE”语句,那将为你以外的人节省大量(猜测)工作。@wildplasser:我已经在我的帖子中添加了这些信息,希望能有所帮助。但是,在我编写解决方案时,我不知道它是否完全正确:\n我不认为这本书的作者打算使用触发器,因为这是在引用约束部分,下一部分是带有触发器的部分(我还没有达到这一部分):\但是非常感谢您尝试帮助我。我已经开始阅读触发器部分,它让我有兴趣了解您将如何在触发器中执行此操作。你建议采取什么步骤?触发部分有点混乱。问题是关于一个约束,但你根本没有解决这个问题。好吧:真正的根本问题是“约束最小化”:一个好的数据设计应该有最小数量(和复杂性)的约束。(我真的不明白为什么我会被否决,而你基本上说的是相同或更少,但我不在乎投票。)此外:这是家庭作业。@wildplasser:我认为你是对的,但表格已经在练习中描述过了,正如我写的,这不是一篇我应该发现应该创建什么的文本。我必须告诉你这不是家庭作业,因为我没有这方面的课程。我说我在自学。此外,如果我在这样一个班级,问老师我的疑问会容易得多。谢谢你试着帮助我。是的,它确实涵盖了检查限制。是否类似于
alter table Album add constraint titleAlbum\u is\u Track\u in\u Single check(idG,titleE)in(select idG,titleM from Single)
No,您仍然需要指定表示某个标题既是相关专辑上的曲目标题又是单个标题的连接:类似于CHECK(idG,titleE)IN((选择idG,titleE FROM track WHERE titleE=titleM)JOIN(选择idG,titleM)FROM single WHERE…)。或者像支票。。。在中,从轨道中选择轨道,然后。。。在中,从单个中选择。或两个不同的检查约束,每个约束表示一个
ALTER TABLE album ADD named_after_track int not null;

ALTER TABLE album 
ADD FOREIGN KEY (idG, titleE, titleE, named_after_track)
REFERENCES track (idg, titleE, titleM, number)
DEFERRABLE INITIALLY DEFERRED;