Updating PK and all FKs to it in CTE - Mailing list pgsql-general

From Tom Kazimiers
Subject Updating PK and all FKs to it in CTE
Date
Msg-id YQKef3h1sWgnvnx+@dewberry.localdomain
Whole thread Raw
Responses Re: Updating PK and all FKs to it in CTE  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-general
Hi all,

I am on Postgres 13 and have a problem with updates in a CTE. While certainly
not generally recommended, I need to update the primary key in a table that is
referenced by a few other tables. The table definition is attached to the end
of this email [2]. I'd like to avoid dropping and recreating the constraints or
even columns, because these tables can become quite large. While I could define
the FK constraints as ON UPDATE CASCADE, I wonder why an alternative solution
using a CTE doesn't work:

According to [1], I should be able to update all FKs and the PK within a 
single CTE. My CTE looks like this (a few tables left out for readability, they
follow the same pattern):

WITH update_catmaid_deep_link AS (
     UPDATE catmaid_deep_link
     SET active_skeleton_id = 12
     WHERE active_skeleton_id = 16150756
), update_class_instance_class_instance_a AS (
     UPDATE class_instance_class_instance
     SET class_instance_a = 12
     WHERE class_instance_a = 16150756
),
[…]
), update_catmaid_skeleton_summary AS (
     UPDATE catmaid_skeleton_summary
     SET skeleton_id = 12
     WHERE skeleton_id = 16150756
     AND project_id = 1
)
UPDATE class_instance
                                                     
 
SET id = 12
WHERE id = 16150756
AND project_id = 1;

However, when I try this, I still get an error about a conflict with a FK
constraint in a table updated in the CTE:

ERROR:  23503: update or delete on table "class_instance" violates foreign key constraint
"catmaid_skeleton_summary_skeleton_id_fkey"on table "catmaid_skeleton_summary"
 
DETAIL:  Key (id)=(16150756) is still referenced from table 
"catmaid_skeleton_summary".

It seems like the CTE change wasn't reflected when checking the constraint (?).

As can be seen in the table definition [2], the primary key comes with an
INCLUDE statement. Is this potentially a problem? Is such an update maybe not
always possible without DDL?

Thanks for any insight!

Cheers,
Tom

[1] https://stackoverflow.com/a/34383663/1665417
[2] Table definition:

# \d class_instance
                                      Table "public.class_instance"
     Column     |           Type           | Collation | Nullable |               Default               
---------------+--------------------------+-----------+----------+-------------------------------------
  id            | bigint                   |           | not null | nextval('concept_id_seq'::regclass)
  user_id       | integer                  |           | not null | 
  project_id    | integer                  |           | not null | 
  creation_time | timestamp with time zone |           | not null | now()
  edition_time  | timestamp with time zone |           | not null | now()
  txid          | bigint                   |           | not null | txid_current()
  class_id      | bigint                   |           | not null | 
  name          | character varying(255)   |           | not null | 
Indexes:
     "class_instance_id_pkey" PRIMARY KEY, btree (id) INCLUDE (class_id, project_id)
     "class_instance_class_id" btree (class_id)
     "class_instance_name_trgm_idx" gin (name gin_trgm_ops)
     "class_instance_project_id" btree (project_id)
     "class_instance_upper_name_idx" btree (upper(name::text))
     "class_instance_user_id" btree (user_id)
Foreign-key constraints:
     "class_instance_class_id_fkey" FOREIGN KEY (class_id) REFERENCES class(id) DEFERRABLE INITIALLY DEFERRED
     "class_instance_project_id_fkey" FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE DEFERRABLE
INITIALLYDEFERRED
 
     "class_instance_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
Referenced by:
     TABLE "catmaid_deep_link" CONSTRAINT "catmaid_deep_link_active_skeleton_id_fkey" FOREIGN KEY (active_skeleton_id)
REFERENCESclass_instance(id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED
 
     TABLE "catmaid_sampler" CONSTRAINT "catmaid_sampler_skeleton_id_fkey" FOREIGN KEY (skeleton_id) REFERENCES
class_instance(id)ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "catmaid_skeleton_summary" CONSTRAINT "catmaid_skeleton_summary_skeleton_id_fkey" FOREIGN KEY (skeleton_id)
REFERENCESclass_instance(id) DEFERRABLE INITIALLY DEFERRED
 
     TABLE "class_instance_class_instance" CONSTRAINT "class_instance_class_instance_class_instance_a_fkey" FOREIGN KEY
(class_instance_a)REFERENCES class_instance(id) DEFERRABLE INITIALLY DEFERRED
 
     TABLE "class_instance_class_instance" CONSTRAINT "class_instance_class_instance_class_instance_b_fkey" FOREIGN KEY
(class_instance_b)REFERENCES class_instance(id) DEFERRABLE INITIALLY DEFERRED
 
     TABLE "connector_class_instance" CONSTRAINT "connector_class_instance_class_instance_id_fkey" FOREIGN KEY
(class_instance_id)REFERENCES class_instance(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "point_class_instance" CONSTRAINT "point_class_instance_class_instance_id_fkey" FOREIGN KEY
(class_instance_id)REFERENCES class_instance(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "region_of_interest_class_instance" CONSTRAINT "region_of_interest_class_instance_class_instance_id_fkey"
FOREIGNKEY (class_instance_id) REFERENCES class_instance(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "review" CONSTRAINT "review_skeleton_id_fkey" FOREIGN KEY (skeleton_id) REFERENCES class_instance(id) ON
DELETECASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "skeleton_origin" CONSTRAINT "skeleton_origin_skeleton_id_fkey1" FOREIGN KEY (skeleton_id) REFERENCES
class_instance(id)ON DELETE CASCADE
 
     TABLE "stack_class_instance" CONSTRAINT "stack_class_instance_class_instance_id_fkey" FOREIGN KEY
(class_instance_id)REFERENCES class_instance(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "stack_group_class_instance" CONSTRAINT "stack_group_class_instance_class_instance_id_fkey" FOREIGN KEY
(class_instance_id)REFERENCES class_instance(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "treenode_class_instance" CONSTRAINT "treenode_class_instance_class_instance_id_fkey" FOREIGN KEY
(class_instance_id)REFERENCES class_instance(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "treenode_connector" CONSTRAINT "treenode_connector_skeleton_id_fkey" FOREIGN KEY (skeleton_id) REFERENCES
class_instance(id)ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "treenode" CONSTRAINT "treenode_skeleton_id_fkey" FOREIGN KEY (skeleton_id) REFERENCES class_instance(id) ON
DELETECASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "volume_class_instance" CONSTRAINT "volume_class_instance_class_instance_id_fkey" FOREIGN KEY
(class_instance_id)REFERENCES class_instance(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
 
     TABLE "volume_origin" CONSTRAINT "volume_origin_volume_id_fkey" FOREIGN KEY (volume_id) REFERENCES
class_instance(id)ON DELETE CASCADE
 



pgsql-general by date:

Previous
From: Lucas
Date:
Subject: Low cache hit ratio
Next
From: Philip Semanchuk
Date:
Subject: Re: Low cache hit ratio