我有以下情况:
我有一个包含各种语言的文本条目的表。它的定义如下:
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并不是唯一的,但被拒绝是没有意义的......
有更优雅的方法来解决这个问题吗?
答案 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)
);