SQL和外键:如何正确链接这两个表?

SQL和外键:如何正确链接这两个表?,sql,firebird,Sql,Firebird,我正在为我的大学创建一个Delphi应用程序,现在我被卡住了。这个程序是关于数据库的,我使用FireBird 2.1作为数据库服务器。我的数据库和应用程序是关于Linux发行版的 我正在尝试链接Firebird数据库中的两个表。第一个表提供了有关发行版的信息,第二个表提供了有关桌面环境的信息。我想链接两个字段:Distributions表中的Default Desktop Environment和DEs表中的Desktop Environment Name 一个发行版只能有一个默认桌面环境,即安

我正在为我的大学创建一个Delphi应用程序,现在我被卡住了。这个程序是关于数据库的,我使用FireBird 2.1作为数据库服务器。我的数据库和应用程序是关于Linux发行版的

我正在尝试链接Firebird数据库中的两个表。第一个表提供了有关发行版的信息,第二个表提供了有关桌面环境的信息。我想链接两个字段:Distributions表中的Default Desktop Environment和DEs表中的Desktop Environment Name

一个发行版只能有一个默认桌面环境,即安装光盘上的环境(或用户在安装过程中选择的环境)。在DEs表中,有一个唯一的字段,描述了DE的名称,因此它应该链接到发行版的默认DE字段

但是,一个DE可以被多个发行版用作默认DE,这就是冲突所在:发行版表中的默认DE字段必须是唯一的,但不是唯一的。我试图达到的是引用完整性:使DEs表依赖

此外,我还尝试创建第三个表,该表只包含DISTR_NAME和ENV_NAME字段,但我使用该表的唯一目的是使第三个表依赖于DISTROS和DES表,但这是错误的。DES表应该依赖于DISTROS表,我不知道如何做到这一点。因此,任何帮助都将不胜感激!如何正确链接这两个表

所以我创建了这两个表:

CREATE TABLE DISTROS (
    DISTR_NAME  VARCHAR(50) NOT NULL,
    ARCHITECT   VARCHAR(50) NOT NULL,
    DEFAULT_DE  VARCHAR(50) NOT NULL,
    LASTSTABLE  VARCHAR(50) NOT NULL,
    PACKMANAGE  VARCHAR(50) NOT NULL
);

我不知道如何解决这个问题:distributions表必须是父表,DEs表必须是子表。distributions表应该有主键(Disr_NAME字段),而DEs表应该有外键(ENV_NAME字段,与distributions表的DE字段链接)


但我不能这样做,因为SQL要求distributions表的DE字段作为主键。主键必须是唯一的。然而,一个桌面环境可以被许多linux发行版使用,所以这个字段不可能是唯一的。我就是不知道如何正确地链接这两个表。

你所描述的听起来像是一种多对多的关系。而且听起来你几乎是一个人在那里。如您所述,M2M relationsihps中始终有第三个表。您的最终结构将如下所示

**DISTROS**
DISTR_NAME - PK/Unique

**DISTROS_TO_DES** (PK contains both fields which are collectively unique)
DISTR_NAME FK to Distros.DISTR_NAME 
ENV_NAME  FK to DES.ENV_NAME

**DES**
ENV_NAME  - PK/Unique
还有一点建议。您确实不希望主键值经常更改,因此varchar字段通常是一个糟糕的选择。我建议在DES和DISTROS表中添加一个自动递增(或标识)ID字段,用作PK。

正如您所描述的,发行版有一个默认的桌面环境。这意味着一个从
发行版
DES
的外键,但是您可以用另一种方式对外键进行建模。外键的目标需要
主键
唯一约束
,因此当前解决方案存在问题

解决方案是将外键从
DES
删除到
DISTROS
并替换为:

ALTER TABLE DISTROS 
   ADD CONSTRAINT FK_DISTROS_DES FOREIGN KEY (DE) REFERENCES DES (ENV_NAME);
我建议重新研究SQL和关系建模,因为这些是使用SQL和(关系)数据库时真正需要了解的基础知识


此外,我知道Firebird中标识符的31个字符限制可能是个问题,但您应该尝试使用更长的描述性名称(尤其是
DES
DE
)。

我删除了Delphi和IBExpert标记,因为这个问题与所使用的编程语言或数据库管理软件完全无关。这是一个严格意义上的Firebird SQL问题。我认为您的外键应该是从
发行版到
DES
,而不是相反。Mark Rotterveel,是的!对非常感谢你!非常感谢。这很有帮助,现在一切正常!谢谢大家!@我在我的评论基础上添加了一个答案,请接受。看来我必须更具体一些。事实上,为了简化我的工作,我将这个DE字段设置为类似于“Default DE”字段。。。例如,OpenSUSE中的默认DE是KDE,依此类推。所以它更像是一对多。还有一个问题:DES表应该依赖于distributions表,但是如果我使用这个结构(正如我前面提到的,我已经有一个类似的结构),DES表是不依赖的,DISTROS_TO_DES表依赖于它,但反之亦然。我不知道怎么做…我建议编辑你的问题,让它更清楚。要想深入了解你的实际问题是极其困难的。用英语解释你想做什么,而不是试图把它翻译成你的表格结构。我已经编辑了我的问题,并提供了我以前在评论中发布的附加信息。看来我已经描述了我能想到的一切。如果还不清楚,请告诉我你需要什么信息来让问题完全清楚,我会告诉你的。再次感谢。我对SQL的了解很糟糕,但那是因为我三年前才在大学里学的,但不是我自己学的。我唯一需要这些知识的就是我刚刚完成的这项工作。将来,如果我需要了解SQL来做一些事情,我会按照您的建议重新研究,但我现在不需要。
ALTER TABLE DISTROS 
   ADD CONSTRAINT FK_DISTROS_DES FOREIGN KEY (DE) REFERENCES DES (ENV_NAME);