Question

Hi people i need some help deciding on the best way to do an insert into table ‘shop’ which has a serial id field. I also need to insert into tables ‘shopbranch’ and ‘shopproperties’ which both references shop.id.

In a nutshell I need to insert one shop record. Then two records for each table of the following tables, shopproperty and shopbranch, whose shopid (FK) references the just created shop.id field

I saw somewhere that i could wrap the ‘shop’ insert, inside a function called lets say ‘insert_shop’ which does the 'shop' insert and returns its id using a select statement

Then inside another function which inserts shoproperty and shopbranch records i could do one call to insert_shop function to return the shop id which can be used to be passed in as the shop id for the records.

Can you let me know if I’m looking at this in the correct way as I’m a newbie.

Was it helpful?

Solution

One way to approach this is to create a view on your three tables that shows all columns from all three tables that can be inserted or updated. If you then create an INSTEAD OF INSERT trigger on the view then you can manipulate the view contents as if it were a table. You can do the same with UPDATE and even combine the two into an INSTEAD OF INSERT OR UPDATE trigger. The function that your trigger calls then has three INSERT statements that redirect the insert on the view to the underlying tables:

CREATE TABLE shop (
  id serial PRIMARY KEY,
  nm text,
  ...
);

CREATE TABLE shopbranch (
  id serial PRIMARY KEY,
  shop integer NOT NULL REFERENCES shop,
  branchcode text,
  loc text,
  ...
);

CREATE TABLE shopproperties (
  id serial PRIMARY KEY,
  shop integer NOT NULL REFERENCES shop,
  prop1 text,
  prop2 text,
  ...
);

CREATE VIEW shopdetails AS
  SELECT s.*, b.*, p.*
  FROM shop s, shopbranch b, shopproperties p,
  WHERE b.shop = s.id AND p.shop = s.id;

CREATE FUNCTION shopdetails_insert() RETURNS trigger AS $$
DECLARE
  shopid integer;
BEGIN
  INSERT INTO shop (nm, ...) VALUES (NEW.nm, ...) RETURNING id INTO shopid;
  IF NOT FOUND
    RETURN NULL;
  END;
  INSERT INTO shopbranch (shop, branchcode, loc, ...) VALUES (shopid, NEW.branchcode, NEW.loc, ...);
  INSERT INTO shopproperties(shop, prop1, prop2, ...) VALUES (shopid, NEW.prop1, NEW.prop2, ...);
  RETURN NEW;
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER shopdetails_trigger_insert
  INSTEAD OF INSERT
  FOR EACH ROW EXECUTE PROCEDURE shopdetails_insert();

You could of course play with the view and show only those columns from the three tables that can be inserted or updated (such as excluding primary and foreign keys).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top