Postgresql 多对多关系插入

Posted

技术标签:

【中文标题】Postgresql 多对多关系插入【英文标题】:Postgresql Many to Many relationship insert 【发布时间】:2014-08-07 05:08:45 【问题描述】:

我使用的是 Postresql 9.3.5。我在实体“Foo”和“Bar”之间有一个多对多的关系,我将其建模为:

CREATE TABLE Foo
(
    id SERIAL PRIMARY KEY NOT NULL,
    .... various columns for foo ....
);

CREATE TABLE Bar
(
    id SERIAL PRIMARY KEY NOT NULL,
    field1 varchar(50) UNIQUE NOT NULL,
    .... various columns for bar ....
);

CREATE TABLE FooBar
(
    fooID int NOT NULL,
    barID int NOT NULL,
    PRIMARY KEY (fooID, barID),
    FOREIGN KEY (fooID) REFERENCES Foo(id),
    FOREIGN KEY (barID) REFERENCES Bar(id)
);

现在我要做的是在 Foo 中插入一条记录,在 Bar 中插入一条对应的记录,然后插入匹配的 FooBar 记录,其中包含 foo 和 bar 条目的 id。

Catch:我不知道何时插入 Bar 记录(如果它们已经存在),所以目前我对 Bar 的插入看起来像:

INSERT INTO Bar(field1, .... other fields for Bar....) 
SELECT 'value1', .... other values for the insert....
WHERE NOT EXISTS (
SELECT 1 FROM Bar WHERE field1 = 'value1')

这很好用,但我的问题是:如何获取新插入(或现有)Bar 记录的 id,以便将其插入 FooBar 表中?

【问题讨论】:

【参考方案1】:

这似乎可行,尽管它远非优雅并且可能非常低效:

WITH new AS (
    INSERT INTO bar(field1) 
    SELECT ('aaa') WHERE NOT EXISTS (
        SELECT 1 FROM bar WHERE field1='aaa'
    ) RETURNING id
),
existing AS (
    SELECT id FROM bar WHERE field1='aaa'
) 
SELECT id FROM existing UNION SELECT id FROM new

我想这会因为在 bar 中重复搜索匹配值而效率低下。更有效的解决方案可能是编写存储过程。

【讨论】:

【参考方案2】:

试试这个

INSERT INTO Bar(field1, field2,etc...) values(value1, value2,etc...) RETURNING id;

SQL FIDDLE

【讨论】:

再次,来自问题:“我不知道何时插入 Bar 记录,如果它们已经存在”。如果我在记录已存在时执行此操作,则会导致错误。

以上是关于Postgresql 多对多关系插入的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PostgreSQL 中实现多对多关系?

在 PostgreSQL 中存储一对多或多对多关系的最佳方式是啥?

在 laravel 中使用多对多关系同步:PostgreSQL 数据透视表不更新

教义 - 在多对多关系表中插入记录

CoreData 多对多关系插入和删除操作

JPA多对多关系:无法插入生成的表