From 69595aeb9f1e6eda74fa29fde22bd117a8044812 Mon Sep 17 00:00:00 2001 From: Bernice Southey Date: Thu, 20 Nov 2025 11:53:57 +0000 Subject: [PATCH] Add ctid guidance and remove from examples --- doc/src/sgml/ddl.sgml | 5 ++++- doc/src/sgml/ref/delete.sgml | 10 +++++----- doc/src/sgml/ref/update.sgml | 9 +++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 09ad8400fd0..99c8facfe0b 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -1559,7 +1559,10 @@ CREATE TABLE circles ( ctid will change if it is updated or moved by VACUUM FULL. Therefore ctid is useless as a long-term row - identifier. A primary key should be used to identify logical rows. + identifier. Be aware that ctids will change in data-modifying + concurrent transactions, and they are not unique across table partitions. + A primary key should be used to identify logical rows. + diff --git a/doc/src/sgml/ref/delete.sgml b/doc/src/sgml/ref/delete.sgml index 5b52f77e28f..48eb1b6755a 100644 --- a/doc/src/sgml/ref/delete.sgml +++ b/doc/src/sgml/ref/delete.sgml @@ -313,15 +313,15 @@ DELETE FROM tasks WHERE CURRENT OF c_tasks; documentation of UPDATE: WITH delete_batch AS ( - SELECT l.ctid FROM user_logs AS l - WHERE l.status = 'archived' - ORDER BY l.creation_date + SELECT a.id FROM accounts AS a + WHERE a.status = 'archived' + ORDER BY a.id FOR UPDATE LIMIT 10000 ) -DELETE FROM user_logs AS dl +DELETE FROM accounts AS dl USING delete_batch AS del - WHERE dl.ctid = del.ctid; + WHERE dl.id = del.id; diff --git a/doc/src/sgml/ref/update.sgml b/doc/src/sgml/ref/update.sgml index 40cca063946..7374b884080 100644 --- a/doc/src/sgml/ref/update.sgml +++ b/doc/src/sgml/ref/update.sgml @@ -486,13 +486,10 @@ UPDATE films SET kind = 'Dramatic' WHERE CURRENT OF c_films; no LIMIT clause for UPDATE, it is possible to get a similar effect through the use of a Common Table Expression and a - self-join. With the standard PostgreSQL - table access method, a self-join on the system - column ctid is very - efficient: + self-join: WITH exceeded_max_retries AS ( - SELECT w.ctid FROM work_item AS w + SELECT w.id FROM work_item AS w WHERE w.status = 'active' AND w.num_retries > 10 ORDER BY w.retry_timestamp FOR UPDATE @@ -500,7 +497,7 @@ WITH exceeded_max_retries AS ( ) UPDATE work_item SET status = 'failed' FROM exceeded_max_retries AS emr - WHERE work_item.ctid = emr.ctid; + WHERE work_item.id = emr.id; This command will need to be repeated until no rows remain to be updated. Use of an ORDER BY clause allows the command to -- 2.43.0