PostgreSQL -- 使用 CTE INSERT ID 加入 UNNEST 输出 -- 多对多插入

问题描述

在 Postgresql 函数中,是否可以将 UNnesT 的结果(函数输入的整数数组)与 CTE INSERT 返回的 ID 连接起来?

我有 Postgresql 表,例如:

CREATE TABLE public.message (
    id SERIAL PRIMARY KEY,content TEXT
);

CREATE TABLE public.message_tag (
    id SERIAL PRIMARY KEY,message_id INTEGER NOT NULL CONSTRAINT message_tag_message_id_fkey REFERENCES public.message(id) ON DELETE CASCADE,tag_id INTEGER NOT NULL CONSTRAINT message_tag_tag_id_fkey REFERENCES public.tag(id) ON DELETE CASCADE
);

我想创建一个 Postgresql 函数,它接受 content 的输入和 tag_id 的数组。这是用于图形的。我想在一个函数中完成这一切,所以我得到了一个突变。

这是我到目前为止所得到的。我不知道如何跨 CTE 返回的 ID 加入 UNnesT

CREATE FUNCTION public.create_message(content text,tags Int[])
RETURNS public.message
AS $$

-- insert to get primary key of message,for many to many message_id
WITH moved_rows AS (
  INSERT INTO public.message (content)
  RETURNING *;
)

-- many to many relation
INSERT INTO public.message_tag
SELECT moved_rows.id as message_id,tagInput.tag_id  FROM moved_rows,UNnesT(tags) as tagInput;
RETURNING *

$$ LANGUAGE sql VOLATILE STRICT;

解决方法

您离目标不远了:

  • CTE 中的分号位置错误
  • 第一个 INSERT 语句缺少 SELECTVALUES 子句来指定应该插入什么
  • 插入 INSERTtag_message 应指定要插入的列(特别是如果您有不必要的序列 id
  • 您已经为 UNNEST 调用指定了关系别名,但未为 tag_id 列指定关系别名
  • 您的函数是 RETURNING 一组 message_tag 行,但被指定为返回单个 message

要解决这些问题:

CREATE FUNCTION public.create_message(content text,tags Int[])
RETURNS public.message
AS $$

-- insert to get primary key of message,for many to many message_id
WITH moved_rows AS (
  INSERT INTO public.message (content)
  VALUES ($1)
  RETURNING *
),-- many to many relation
_ AS (
INSERT INTO public.message_tag (message_id,tag_id)
SELECT moved_rows.id,tagInput.tag_id
FROM moved_rows,UNNEST($2) as tagInput(tag_id)
)
TABLE moved_rows;

$$ LANGUAGE sql VOLATILE STRICT;

(Online demo)