Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 是否有针对不同项目的联合表格模式?_Postgresql - Fatal编程技术网

Postgresql 是否有针对不同项目的联合表格模式?

Postgresql 是否有针对不同项目的联合表格模式?,postgresql,Postgresql,我想要两列的基于列约束的组合。我在这里找不到使用外键的方法,因为它应该是有条件的FK。希望此基本SQL能够说明问题: CREATE TABLE performer_type ( id serial primary key, type varchar ); INSERT INTO performer_type ( id, type ) VALUES (1, 'singer'), ( 2, 'band'); CREATE TABLE singer ( id serial primar

我想要两列的基于列约束的组合。我在这里找不到使用外键的方法,因为它应该是有条件的FK。希望此基本SQL能够说明问题:

CREATE TABLE performer_type (
  id serial primary key,
  type varchar
);

INSERT INTO performer_type ( id, type ) VALUES (1, 'singer'), ( 2, 'band');

CREATE TABLE singer (
  id serial primary key,
  name varchar
);

INSERT INTO singer ( id, name ) VALUES (1, 'Robert');

CREATE TABLE band (
  id serial primary key,
  name varchar
);

INSERT INTO band ( id, name ) VALUES (1, 'Animates'), ( 2, 'Zed Leppelin');

CREATE TABLE gig (
  id serial primary key,
  performer_type_id int default null, /* FK, no problem */
  performer_id int default null       /* want FK based on previous FK, no good solution so far */
);

INSERT INTO gig ( performer_type_id, performer_id ) VALUES ( 1,1 ), (2,1), (2,2), (1,2), (2,3);
现在,最后一次插入有效,但对于最后2个值对,我希望它失败,因为没有歌手ID 2或乐队ID 3。如何设置这样的约束

我已经问过类似的问题,唯一的解决办法就是使用触发器。触发器的问题是:不能设置类型和表的动态列表。我想动态添加类型(和相关表)

我也发现了,但这对我来说是颠倒的,我没有弄明白,在我的情况下如何使它工作

我在这里看到的模式对我来说非常有用,我想一定有一些通用的方法。是吗

编辑。

似乎,我在我的示例中选择了不好的项目,所以我尝试弄清楚:不同的表演者表(
singer
band
)之间没有关系
gig
-表格只需列出不同执行者的任务,而不需要设置它们之间的任何关系

另一个例子是库存中的项目:我可能有
item\u type
-表,它定义了数百种与相关表相关的项目类型(例如,
orange
house
),应该有一个表
stock
,它列出了项目的所有外观

我使用的PostgreSQL是基于@Laurenz Albe的9.6

,我形成了上述示例的解决方案。主要区别:有父表
performer
,它的主键是特定performer表的FK/PK,也从
gig
表中引用

CREATE TABLE performer_type (
  id serial primary key,
  type varchar
);
INSERT INTO performer_type ( id, type ) VALUES (1, 'singer' ), ( 2, 'band' );

CREATE TABLE performer (
  id serial primary key,
  performer_type_id int REFERENCES performer_type(id)
);

CREATE TABLE singer (
  id int primary key REFERENCES performer(id),
  name varchar
);

INSERT INTO performer ( performer_type_id ) VALUES (1); -- get PK 1 for next statement
INSERT INTO singer ( id, name ) VALUES (1, 'Robert');

CREATE TABLE band (
  id int primary key REFERENCES performer(id),
  name varchar
);

INSERT INTO performer ( performer_type_id ) VALUES (2); -- get PK 2 for next statement
INSERT INTO singer ( id, name ) VALUES (2, 'Animates');
INSERT INTO performer ( performer_type_id ) VALUES (2); -- get PK 3 for next statement
INSERT INTO singer ( id, name ) VALUES (3, 'Zed Leppelin');

CREATE TABLE gig (
  id serial primary key,
  performer_id int REFERENCES performer(id)
);

INSERT INTO gig ( performer_id ) VALUES (1), (2), (3), (4);
最后一次插入失败,如预期:

ERROR:  insert or update on table "gig" violates foreign key constraint "gig_performer_id_fkey"
DETAIL:  Key (performer_id)=(4) is not present in table "performer".
但是

对我来说,有一个恼人的问题:我没有很好的方法来区分哪个ID是歌手的,哪个是乐队的等等(在最初的例子中,我在
gig
-表中有
performer\u type\u ID
),因为任何
performer\u ID
都可能属于任何表演者。所以我希望任何执行者类型都有自己的ID范围,所以我为每个序列创建虚拟表

CREATE TABLE band_id (
  id int primary key,
  dummy boolean default null
);
CREATE SEQUENCE band_id_seq START 1;
ALTER TABLE band_id ALTER COLUMN id SET DEFAULT nextval('band_id_seq');

CREATE TABLE singer_id (
  id int primary key,
  dummy boolean default null
);
CREATE SEQUENCE singer_id_seq START 2000000;
ALTER TABLE singer_id ALTER COLUMN id SET DEFAULT nextval('singer_id_seq');
现在,要将新行插入到特定的performer表中,我必须获取它的下一个ID:

INSERT INTO band_id (dummy) VALUES (NULL);
试图弄清楚,是否有可能在DB级别上解决这个过程,或者在应用程序级别上做些什么。如果插入
波段
表格可以:

  • 在触发器插入带id之前,生成特定id
  • 在触发器将此新ID插入执行者表之前
  • 将此新ID包含到插入到
    波段中

前两点很简单,但最后一点目前还不清楚。

我认为您的数据库结构可以重新设计。为什么不创建一个名为music的表和一个名为Performer的表,然后在Performer和mummer的多对多关系之间创建一个连接表,该连接表的主键为mummers ID和Performer ID,然后将该组合主键用作表Gig中的外键,例如,表演者可以有奶油乐队、德里克乐队和多米诺骨牌乐队,音乐家有埃里克·克莱普顿,他又属于这两个表演者(乐队)@RyanWilson,也许我的例子不够清楚<代码>执行者类型可能包含数百种类型,每行有相应的表。
gig
-表本身基本上就是类型表和相应执行者表之间的连接表。看不出单独的连接表是如何解决问题的?这就是我试图引导你们远离的,为什么你们要为每种表演者制作单独的表??您可以在表Performer中有一个Performer类型列,它表示它是否是歌手、乐队等。当然,这是一个简化的示例
band
singer
(可能还有
painter
actor
等)在它们的表上有非常不同的属性集。这些表也可能是不同的产品类别,可能会有
库存
销售
连接表,以便在某些共同方面将它们放在一起,但基本上它们是如此不同的对象,您不能将它们放在同一个表中。好的。如果需要,您仍然可以使用不同的表进行操作,但您可以将其更改为使用我建议的一些内容。gig由一个或多个表演者组成,它不关心表演者类型和表演者类型属性,因此您仍然可以使用带有连接表的表演者表和音乐家表,正如我建议的那样,将它们的两个键作为主键,并使用gig中的键,但该执行者表将包含执行者类型的外键,该外键将链接到相关的执行者类型表。