当父 table 的值都存储在一个数组中时,如何执行数组插入到联结点 table 中?
How do I perform an array insert into a junction table when the parent tables' values are all stored into an array?
我正在使用 postgresql。
所以,假设我有 3 tables.
CREATE TABLE article (
article_id BIGSERIAL,
article_name VARCHAR(20),
PRIMARY KEY(article_id)
);
CREATE TABLE tags (
tag_id VARCHAR(30)[] NOT NULL
PRIMARY KEY(tag_id)
);
和交界处table:
CREATE TABLE article_tags (
tag_id VARCHAR(10) NOT NULL,
article_id INTEGER NOT NULL,
FOREIGN KEY(tag_id) REFERENCES tags(tag_id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY(article_id) REFERENCES article(article_id) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (article_id, tag_id)
所以在我的标签中 table 我有一个条目,它是所有可能标签的数组,即
tag_id
______
{tag1,tag2,tag3,tag4}
当我尝试在任何 individual/combinations 标签的 article_tags 中执行插入时,即(假设存在 ID 为 1 的文章)
INSERT INTO article_tags (article_id, tag_id) VALUES (1, '{tag4}');
OR
INSERT INTO article_tags (article_id, tag_id) VALUES (1, '{tag4, tag3}');
我遇到错误
ERROR: insert or update on table "article_tags" violates foreign key constraint "article_tags_tag_id_fkey"
DETAIL: Key (tag_id)=({tag4}) is not present in table "tags". / DETAIL: Key (tag_id)=({tag4, tag3}) is not present in table "tags".
有没有办法让插入考虑主键数组(tag_id)中的所有值来执行插入?如果是由于 table 结构错误,是否有更好的方法来构建 table 以便我能够将标签的任何值插入标签中存在的 article_tags( tag_id) 的数组,而不将所有可能的标签排列插入到标签 (tag_id) 中,这将花费相当多的时间,但可以正常工作。
如果我恰好插入那个数组,它会起作用
INSERT INTO article_tags (article_id, tag_id) VALUES (1, '{tag1,tag2,tag3,tag4}');
但除非需要,否则我不希望创建标签的每一个排列。
您需要规范化结构,其中每个标签都有自己的行;正如您所说的那样,您有“事先”。 Postgres 提供了 functions dealing with arrays 名副其实的聚宝盆(很多)。要将文章附加到您想要 UNNEST
的数组中的每个标签,要重建 文章,标签数组 结构使用 ARRAY AGG
.
insert into article_tags(article_id, tag_id)
select a.article_id, t.tag_id
from (select article_id
from article
where article_name = <article name>
) a
cross join (select tag_id
from tags
where tag_name in (select unnest ( <tags array >))
) t
on conflict (article_id, tag_id) do nothing ;
--- 重建 Article_Name, Tag_Array
select a.article_name, array_agg(t.tag_name order by t.tag_name)
from article_tags ats
join article a on (a.article_id = ats.article_id)
join tags t on (t.tag_id = ats.tag_id)
group by article_name;
请参阅 example here 了解如何使用它们。该示例构建了一个存储过程来处理同时在 3 个表中创建条目。但是其中的语句可以 运行 独立地对参数传递进行微小的修改。
我正在使用 postgresql。 所以,假设我有 3 tables.
CREATE TABLE article (
article_id BIGSERIAL,
article_name VARCHAR(20),
PRIMARY KEY(article_id)
);
CREATE TABLE tags (
tag_id VARCHAR(30)[] NOT NULL
PRIMARY KEY(tag_id)
);
和交界处table:
CREATE TABLE article_tags (
tag_id VARCHAR(10) NOT NULL,
article_id INTEGER NOT NULL,
FOREIGN KEY(tag_id) REFERENCES tags(tag_id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY(article_id) REFERENCES article(article_id) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (article_id, tag_id)
所以在我的标签中 table 我有一个条目,它是所有可能标签的数组,即
tag_id
______
{tag1,tag2,tag3,tag4}
当我尝试在任何 individual/combinations 标签的 article_tags 中执行插入时,即(假设存在 ID 为 1 的文章)
INSERT INTO article_tags (article_id, tag_id) VALUES (1, '{tag4}');
OR
INSERT INTO article_tags (article_id, tag_id) VALUES (1, '{tag4, tag3}');
我遇到错误
ERROR: insert or update on table "article_tags" violates foreign key constraint "article_tags_tag_id_fkey"
DETAIL: Key (tag_id)=({tag4}) is not present in table "tags". / DETAIL: Key (tag_id)=({tag4, tag3}) is not present in table "tags".
有没有办法让插入考虑主键数组(tag_id)中的所有值来执行插入?如果是由于 table 结构错误,是否有更好的方法来构建 table 以便我能够将标签的任何值插入标签中存在的 article_tags( tag_id) 的数组,而不将所有可能的标签排列插入到标签 (tag_id) 中,这将花费相当多的时间,但可以正常工作。
如果我恰好插入那个数组,它会起作用
INSERT INTO article_tags (article_id, tag_id) VALUES (1, '{tag1,tag2,tag3,tag4}');
但除非需要,否则我不希望创建标签的每一个排列。
您需要规范化结构,其中每个标签都有自己的行;正如您所说的那样,您有“事先”。 Postgres 提供了 functions dealing with arrays 名副其实的聚宝盆(很多)。要将文章附加到您想要 UNNEST
的数组中的每个标签,要重建 文章,标签数组 结构使用 ARRAY AGG
.
insert into article_tags(article_id, tag_id)
select a.article_id, t.tag_id
from (select article_id
from article
where article_name = <article name>
) a
cross join (select tag_id
from tags
where tag_name in (select unnest ( <tags array >))
) t
on conflict (article_id, tag_id) do nothing ;
--- 重建 Article_Name, Tag_Array
select a.article_name, array_agg(t.tag_name order by t.tag_name)
from article_tags ats
join article a on (a.article_id = ats.article_id)
join tags t on (t.tag_id = ats.tag_id)
group by article_name;
请参阅 example here 了解如何使用它们。该示例构建了一个存储过程来处理同时在 3 个表中创建条目。但是其中的语句可以 运行 独立地对参数传递进行微小的修改。