如何在PostgreSQL中实现嵌套的INSERT语句?

时间:2019-03-17 23:28:33

标签: sql postgresql triggers insert common-table-expression

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

CREATE TABLE groups (
  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 groupmembers (
  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 users (
    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 *;

如何添加另一个将值插入groupid表的useridgroupmembers列中的插入语句?

我已经看到了,但是似乎无法回答我的问题:
PostgreSQL nested INSERTs / WITHs for foreign key insertions

1 个答案:

答案 0 :(得分:1)

我建议用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是用强制引用完整性的FK约束定义的NOT NULL,因此[INNER] JOIN是好的。否则,我会考虑使用LEFT JOIN

非常类似于the answer you referred。或这些:

如果由于某种原因您无法执行上述命令(例如嵌套在必须插入groups的函数中),则下一个最佳选择是{{ 3}} 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上的触发器groups

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

相关: