sql - PostgreSQL中如何实现嵌套INSERT语句?

标签 sql postgresql triggers insert common-table-expression

我有两个表,groupgroupmembers。在 group 表中插入行时,我还想插入两个值,groupid(来自组表的 id)和 userid(id创建组的用户的名称)添加到 groupmembers 表中。这些是表格:

CREATE TABLE <b>groups</b> (
  id SERIAL PRIMARY KEY NOT NULL,
  name CHARACTER VARYING(255) NOT NULL,
  creator CHARACTER VARYING(255) NOT NULL,
  role CHARACTER VARYING(100) NOT NULL DEFAULT ('admin'),
  createdon TIMESTAMP WITH TIME ZONE DEFAULT now(),
  FOREIGN KEY (creator) references users (email) on delete CASCADE
);

CREATE TABLE <b>groupmembers</b> (
  id SERIAL PRIMARY KEY NOT NULL,
  groupid INTEGER NOT NULL,
  userid INTEGER NOT NULL,
  createdon TIMESTAMP WITH TIME ZONE DEFAULT now(),
  FOREIGN KEY (groupid) references groups (id) on delete CASCADE,
  FOREIGN KEY (userid) references users (id) on delete CASCADE
);

 CREATE TABLE <b>users</b> (
    id SERIAL PRIMARY KEY NOT NULL,
    firstname CHARACTER VARYING(255) NOT NULL,
    lastname CHARACTER VARYING(255) NOT NULL,
    email CHARACTER VARYING(50) UNIQUE NOT NULL,
    password CHARACTER VARYING(255) NOT NULL,
    registeredon TIMESTAMP WITH TIME ZONE DEFAULT now()
  );

插入组表的语句是:

INSERT INTO groups (name, creator) VALUES ($1, $2) RETURNING *;

如何添加另一个插入语句,将值插入到 groupmembers 表的 groupiduserid 列中?

我看过这个,但它似乎没有回答我的问题:
PostgreSQL nested INSERTs / WITHs for foreign key insertions

最佳答案

我建议使用 data-modifying CTE 将两个插入包装在单个查询中,例如:

WITH grp_ins AS (
   INSERT INTO groups (name, creator)
   VALUES ($1, $2)
   RETURNING id, creator
   )
INSERT INTO groupmembers (groupid, userid)
SELECT g.id, u.id 
FROM   grp_ins    g
JOIN   users u ON u.email = g.creator;

由于groups.creator被定义为NOT NULL并具有强制引用完整性的FK约束,所以[INNER] JOIN是好的。否则我会考虑LEFT JOIN

很像the answer you referred到。或者这些:

如果由于某种原因,您无法强制执行上述命令(例如嵌套在必须用于插入的函数中),下一个最好的事情是一个trigger AFTER INSERT 执行第二个INSERT。稍微复杂一点,成本也高一些。但这项工作确实:

CREATE OR REPLACE FUNCTION trg_ins_row_in_groupmembers()
  RETURNS trigger AS
$func$
BEGIN
   INSERT INTO groupmembers (groupid, userid)
   SELECT NEW.id, (SELECT u.id FROM users u WHERE u.email = NEW.creator);

   RETURN NEW;  -- doesn't matter much what you return here
END
$func$  LANGUAGE plpgsql;

以及上的AFTER INSERT触发器:

CREATE TRIGGER groups_ins_aft
AFTER INSERT ON groups
FOR EACH ROW EXECUTE PROCEDURE trg_ins_row_in_groupmembers();

相关:

关于sql - PostgreSQL中如何实现嵌套INSERT语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55212957/

相关文章:

sql - 甲骨文 10g : truncate string

php - 从表中选择每个 user_id 不同的所有列

mysql - SQL触发器查询错误

bash - 使用本地提供的列表从远程 postgresql 数据库中删除记录

mysql - SQL : How to update table Automatically in 2nd database when table in 1st database is updated?

oracle - 不使用触发器在 Oracle 中自动递增

sql - Rails Active Record 相当于带有条件表达式的 SQL

sql - 实现此 SQL 查询的最简单方法是什么?

postgresql - 如何开放对部署在 okteto 上的 postgresql 的公共(public)访问?

PostgreSQL 使用西里尔文排序 "ь"