【问题标题】:Postgresql foreign key -- no unique constraintPostgresql 外键——没有唯一约束
【发布时间】:2013-11-21 11:50:50
【问题描述】:

我有以下情况:

我有一个表格,其中包含各种语言的文本条目。定义如下:

    CREATE TABLE text
    (
      textid character varying(70) NOT NULL,
      language character varying(10) NOT NULL,
      content text NOT NULL,
      CONSTRAINT text_pk PRIMARY KEY (textid , language ),
      CONSTRAINT languages_text_fk FOREIGN KEY (language)
          REFERENCES languages (language) MATCH SIMPLE
          ON UPDATE CASCADE ON DELETE RESTRICT
    );

语言表只是语言代码列表,并没有那么相关。

现在,我需要在另一个表上引用一段文本,但我不需要,而且我不知道检索文本时使用的语言。我只知道要检索的文本的 id。实际语言将在运行时由阅读文本的用户口述。

起初我创建了这个:

    CREATE TABLE content_text
    (
      contentid character varying(70) NOT NULL,
      textid character varying(70) NOT NULL,
      CONSTRAINT content_text_pk PRIMARY KEY (contentid , textid ),
      CONSTRAINT content_text_text_fk FOREIGN KEY (textid)
          REFERENCES text (textid) MATCH SIMPLE
          ON UPDATE CASCADE ON DELETE RESTRICT
    );

失败了

错误:没有唯一约束匹配引用表“文本”的给定键

我知道,为了避免这个错误,我必须创建一个只包含 textid 的中间表,该表将被内容和文本引用,但我真的觉得这有点矫枉过正......一个专门用于此的表,在我看来虽然 textid 不是唯一的,但是被拒绝是没有意义的……

有没有更优雅的方法来解决这个问题?

【问题讨论】:

    标签: sql postgresql foreign-keys


    【解决方案1】:

    我知道,为了避免这个错误,我必须创建一个只包含 textid 的中间表,该表将被内容和文本引用,但我真的觉得这有点矫枉过正......有没有更优雅的方法来解决这个问题?

    不,没有。

    据我所知,这也是 SQL 规范的一部分:外键必须引用唯一列。

    另外,您确定这个中间表在某些时候不会有用吗?比如说,要包含诸如 parent_text_id 之类的元数据,以防您引入一些层次结构?或者更重要的是:“引用一段文本”而不​​知道或不需要“检索文本所使用的语言”。

    【讨论】:

      【解决方案2】:

      由于您已经使用主键( textid, language )创建了表 TEXT CONTEXT_TEXT 中的外键必须引用相同的主键。因此:

       CREATE TABLE content_text
          (
            contentid character varying(70) NOT NULL,
            language character varying(10) NOT NULL,
            textid character varying(70) NOT NULL,
            CONSTRAINT content_text_pk PRIMARY KEY (contentid , textid),
            CONSTRAINT content_text_text_fk FOREIGN KEY (textid, language)
                REFERENCES text (textid, language) MATCH SIMPLE
                ON UPDATE CASCADE ON DELETE RESTRICT
          );
      

      或者,您可以从TEXT 的主键中删除language。相反,您可以创建第二个唯一索引:

        CREATE TABLE text2
          (
            textid character varying(70) NOT NULL,
            language character varying(10) NOT NULL,
            content text NOT NULL,
            CONSTRAINT text_pk PRIMARY KEY (textid),
            CONSTRAINT languages_text_fk FOREIGN KEY (language)
                REFERENCES languages (language) MATCH SIMPLE
                ON UPDATE CASCADE ON DELETE RESTRICT, 
            unique (textid, language)
          );
      

      【讨论】:

      • 第二个解决方案不起作用,因为 textid(作为主键)将是唯一的——第二个约束将始终是唯一的,因为 textid 是唯一的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-22
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多