2

I've two tables accounts and projects:

create table accounts (
  id          bigserial primary key,
  slug        text unique
);


create table projects (
  id          bigserial primary key,
  account_id  bigint not null references accounts (id),
  name        text
);

I want to be able to insert a new row into projects by specifying only account.slug (not account.id). What I'm trying to achieve is something like:

INSERT into projects (account_slug, name) values ('account_slug', 'project_name');

I thought about using a trigger (unfortunately it doesn't work):

create or replace function trigger_projects_insert() returns trigger as $$
begin
  if TG_OP = 'INSERT' AND NEW.account_slug then

    select id as account_id
      from accounts as account
      where account.slug = NEW.account_slug;

    NEW.account_id = account_id;

    -- we should also remove NEW.account_slug but don't know how

  end if;
  return NEW;
end;
$$ LANGUAGE plpgsql;

create trigger trigger_projects_insert before insert on projects
  for each row execute procedure trigger_projects_insert();

What is the best way to achieve what I'm trying to do?

Is a trigger a good idea? Is there any other solution?

1 Answer 1

1
WITH newacc AS (
   INSERT INTO accounts (slug)
      VALUES ('account_slug')
      RETURNING id
)
INSERT INTO projects (account_id, name)
   SELECT id, 'project_name'
      FROM newacct;

If you are limited in the SQL you can use, another idea might be to define a view over both tables and create an INSTEAD OF INSERT trigger on the view that performs the two INSERTs on the underlying tables. Then an INSERT statement like the one in your question would work.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the reply, I'm using postgrest.com/en/v0.4, don't know if you're familiar with it, your solution even if correct, won't really work using postgrest, that's why i would like to use a trigger.
I'd say that you should use something different if it keeps you from using the database properly, but it might not b your choice. I'll add a different idea, maybe that will help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.