Postgresql外键 - 没有唯一约束

时间:2013-11-21 11:50:51

标签: sql postgresql foreign-keys

我有以下情况:

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

    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
    );

失败
  

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

我知道为了避免这个错误,我必须创建一个仅包含textid的中间表,它将由内容和文本引用,但我真的觉得这是一个矫枉过正的...一个表只是为了这个在我看来,尽管textid并不是唯一的,但被拒绝是没有意义的......

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

2 个答案:

答案 0 :(得分:3)

  

我知道为了避免这个错误,我必须创建一个仅包含textid的中间表,它将被内容和文本引用,但我真的觉得这是一种矫枉过正......是否有一种更优雅的方式绕过这个问题?

不,没有。

在我知道的情况下,它也是SQL规范的一部分:外键必须引用一个唯一的列。

另外,你是否完全确定这个中间表在某些方面不会变得有用?比如,如果你引入了一些层次结构,包含诸如parent_text_id之类的元数据?或者更重要的是:"引用一段文字"不知道或不需要"将用于检索文本的语言。"

答案 1 :(得分:1)

由于您使用主键(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
    );

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

  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)
    );