简体   繁体   English

PostgreSQL在外键中使用常量

[英]PostgreSQL using constants in foreign key

The syntax for Foreign Key, as described in official documentation , includes set of column from table A referencing set of column from table B. 官方文档中所述,外键的语法包括表A中的列集引用表B中的列集。

Is it possible to use Constant in foreign key declaration? 是否可以在外键声明中使用Constant?

The problem is, I have table DICTIONARIES which contains all dictionary values, discriminated by TYPE. 问题是,我有表DICTIONARIES,它包含所有字典值,由TYPE区分。 I know it's not good design, but unfortunatelly, I have not much to say, as the DB admin wants to 'minimize the number of tables'... 我知道这不是好设计,但不幸的是,我没有太多话要说,因为数据库管理员希望'尽量减少表的数量'......

Is it possible to achieve something like that: 是否有可能实现这样的目标:

CREATE TABLE PERSON (
  id integer primary key,
  country_id integer,
  ...
  FOREIGN KEY ('COUNTRY', country_id) REFERENCES DICTIONARIES(TYPE, ID)
)

It would effectively solve the issue. 它将有效地解决这个问题。 I'm aware I can add column to the table person, which will has only one possible value 'COUNTRY', or I could write a trigger, but I'd prefer to avoid that to keep design cleaner. 我知道我可以向表人添加列,这个列只有一个可能的值'COUNTRY',或者我可以写一个触发器,但我宁愿避免这样做以保持设计更清洁。

A foreign key constraint is from one table's columns to another's columns, so, no. 外键约束是从一个表的列到另一个列的列,因此,没有。

Of course the database should have a table COUNTRY(country_id). 当然,数据库应该有一个表COUNTRY(country_id)。 Commenters have pointed out that your admin is imposing an anti-pattern. 评论者指出,您的管理员正在强加反模式。

Good, you are aware that you can define a column and set it to the value you want and make the foreign key on that. 好的,您知道您可以定义一个列并将其设置为您想要的值并在其上创建外键。 That is an idiom used for avoiding triggers in constraining some subtyping schemes. 这是用于避免限制某些子类型方案的触发器的习惯用法。

You may be able to compute a 'COUNTRY' column depending on your DBMS, at least. 您可以至少根据您的DBMS计算“COUNTRY”列。

Your question is essentially this one , see the end of the question & the comments & answers. 您的问题基本上就是这个问题,请参阅问题的结尾以及评论和答案。

(Lots of functionality would be trivial to implement. Perhaps the difficulty (besides ignorance of consumers) is that arbitrary constraints become quickly expensive computationally. That might just get vendors aggravation. Also, optimization in SQL is impeded by its differences from the relatonal model.) (许多功能实现起来都很简单。也许困难(除了消费者的无知)是任意约束在计算上变得非常昂贵。这可能只会让供应商变得更加恶化。而且,SQL的优化受到与对等模型的差异的阻碍。 )

For Posrgres not having computed (or constant) columns, you can force them to a fixed value column, using DEFAULT plus (maybe) a check. 对于没有计算(或常量)列的Posrgres,可以使用DEFAULT plus(可能)检查将它们强制为固定值列。 This may be ugly, but it works: 这可能很难看,但它有效:

CREATE TABLE dictionaries
  ( id integer primary key
  , typename varchar NOT NULL CHECK ( typename IN ('person' ,'animal' ,'plant' ))
  , content varchar NOT NULL
  -- ...
  , UNIQUE (typename, id)
  , UNIQUE (typename, content)
  );

CREATE TABLE person
  ( id integer primary key
  , typename varchar NOT NULL DEFAULT 'person' CHECK( typename IN ('person' ))
  , species_id integer
  -- ...
  , FOREIGN KEY (typename, species_id) REFERENCES dictionaries(typename, id) -- DEFERRABLE INITIALLY DEFERRED
);

INSERT INTO dictionaries( id, typename, content) VALUES
 ( 1 , 'person' , 'Bob')
,( 2 , 'person' , 'Alice')
,( 11 , 'animal' , 'monkey')
,( 12 , 'animal' , 'cat')
,( 13 , 'animal' , 'dog')
,( 21 , 'plant' , 'cabbage')
        ;
SELECT * FROM dictionaries;

        -- this should succeed
INSERT INTO person( id, species_id) VALUES
 ( 1,1 )
,( 2,2 )
        ;
        -- this should fail
INSERT INTO person( id, species_id) VALUES
 ( 3,11 )
,( 4,12 )
        ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM