0

In PostgreSQL 9.5, I have a table: A

Table A has two properties as:

  1. recid -- the primary key for the table (serial)
  2. description -- a unique key for the table (text)

The primary key of table A is used as a foreign key by other tables with the definition of:

CONSTRAINT fk FOREIGN KEY (A_recid)
      REFERENCES A (recid) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE RESTRICT

I need to change the description in record 1 in table A to an already existing description in record 2 and delete record 1 to keep the descriptions unique for the table.

Record 1 in table A will have child records in other tables which will need to be moved to the new recid of record 2 according to the cascading update of the foreign key constraint.

How is this done? Could writable CTE's be used?

(If necessary, I am not opposed to changing the table design).

Much thanks for any suggestions.

Edit #1 The full table declaration for the parent table is:

CREATE TABLE cpt
(
  recid serial NOT NULL,
  code text,
  cdesc text NOT NULL,
  modified timestamp without time zone DEFAULT now(),
  procedure_type text,
  CONSTRAINT pk_cpt_recid PRIMARY KEY (recid),
  CONSTRAINT cpt_noduplicate UNIQUE (cdesc)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE cpt
  OWNER TO postgres;

And example of a child table (one of many tables):

CREATE TABLE cpt_invoice
(
  recid serial NOT NULL,
  cpt_recid integer NOT NULL,
  ninsurance numeric(10,2),
  ncash numeric(10,2),
  mustschedule boolean,
  doneinoffice boolean,
  common boolean,
  "timestamp" timestamp without time zone DEFAULT now(),
  modified timestamp without time zone DEFAULT now(),
  CONSTRAINT pk_cpt_invoice_recid PRIMARY KEY (recid),
  CONSTRAINT cs_cpt_invoice FOREIGN KEY (cpt_recid)
      REFERENCES cpt (recid) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT cs_unique_cpt_invoice UNIQUE (cpt_recid)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE cpt_invoice
  OWNER TO postgres;

Edit #2: This is kind-of what I'm hoping for. But this will not work with error:

ERROR: update or delete on table "cpt" violates foreign key constraint "nursebilling_cpt_fk" on table "nursebilling" DETAIL: Key (recid)=(459) is still referenced from table "nursebilling".

with plana as (  -- get snapshot of original record
    select * from cpt where recid = 459
)
, planb as (  -- change the primary key on snapshot -- I am hoping this will be cascaded
    update cpt
    set recid = 2
    from plana
    where cpt.recid = plana.recid
)   
, planc as ( -- delete the one-to-one record in cpt_invoice
    delete from cpt_invoice
    using planA 
    where cpt_invoice.cpt_recid = planA.recid
)
, pland as(  -- delete the now unused record from cpt
    delete from cpt
    using plana
    where plana.cdesc = cpt.cdesc
)
select * from cpt
Alan Wayne
  • 5,122
  • 10
  • 52
  • 95
  • Not clear. Maybe you mean DEFERRED constraints? – wildplasser Feb 12 '16 at 00:06
  • @wildplasser Can a constraint on a primary key be defered? – Alan Wayne Feb 12 '16 at 00:07
  • Please give the full DDL. text is ambiguous. IMHO. – wildplasser Feb 12 '16 at 00:25
  • @wildplasser Please excuse my ignorance, DDL means ? – Alan Wayne Feb 12 '16 at 01:02
  • 1
    @wildplasser Please see above edits for full table declarations. Thanks. – Alan Wayne Feb 12 '16 at 01:08
  • So you want to *redirect* one of the FKs of `cpt_invoice.cpt_recid` to point to a different *existing* record of `cpt.recid` ? Only one, or a whole bunch of them/all of them for a given `cpt.recid` or `cpt.cdesc` ? – wildplasser Feb 12 '16 at 01:17
  • @wildplasser The problem here is three fold: 1. I would like to change the cpt_invoice.cpt_recid to point to another existing record of cpt.recid; 2. duplicating the value of a primary key is not allowed, and 3. there are many different tables that need to be redirected. So I was hoping to use the automatic cascading feature of the referencing table as shown above to perform these updates. It is unknown at this time how many child tables will be involved and need to be redirected. – Alan Wayne Feb 12 '16 at 02:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/103252/discussion-between-alan-wayne-and-wildplasser). – Alan Wayne Feb 12 '16 at 04:00

1 Answers1

0

Well, after further investigation, the crux of the matter was disclosed by Erwin Brandstetter

If you need any FOREIGN KEY constraints to reference the column(s), DEFERRABLE is not an option because (per documentation):

The referenced columns must be the columns of a non-deferrable unique or primary key constraint in the referenced table.

Hence, CTE's are out and I'm left with a plpgsql script that in some way will have to explicitly find the child tables, move the child records, then delete the old parent record.

Community
  • 1
  • 1
Alan Wayne
  • 5,122
  • 10
  • 52
  • 95