Tables referencing each other workaround - postgresql

I have two tables (simplified):
+-------------+--------------+----------------------------+
| article |
+-------------+--------------+----------------------------+
| id | int | PRIMARY KEY AUTO_INCREMENT |
| author | int | FK (users) |
| created_at | date | |
| revision | int | FK (article_revision) |
+-------------+--------------+----------------------------+
+-------------+--------------+----------------------------+
| article_revision |
+-------------+--------------+----------------------------+
| id | int | PRIMARY KEY AUTO_INCREMENT |
| title | text | |
| content | text | |
| article_id | int | FOREIGN KEY (article) |
+-------------+--------------+----------------------------+
They are representing news feed articles. Every article can have multiple revisions (changes). I need somehow to specify a current revision from article table which is used (there can be pending revisions that can be used, only one at the time). But it would be circular references. Any workaround for this situation?

There is nothing that keeps you from adding circular foreign key references.
To deal with them, you only have to make sure that at the end of each statement or transaction, all constraints are satisfied:
If you use normal NOT DEFERRABLE constraints, you have to modify both tables in a single statement:
WITH current_revision AS (
INSERT INTO article_revision VALUES (...) RETURNING id
)
UPDATE article
FROM current_revision
SET revision = current_revision.id
WHERE ...;
With DEFERRABLE foreign keys, the check is deferred to the end of the transaction:
BEGIN;
INSERT INTO article_revision VALUES (...) RETURNING id;
UPDATE article SET revision = ... WHERE ...;
COMMIT;

Related

PSQL import fails: ERROR: invalid input syntax for type uuid: "id"

I exported the users table from my Heroku-hosted sql db. The export looks fine, but when I try to import it, I get ERROR: invalid input syntax for type uuid: "id"
This is the command used, per the Heroku site:
\copy users FROM ~/user_export.csv WITH (FORMAT CSV);
EDIT:
I didn't include this, but the error also includes:
CONTEXT: COPY users, line 1, column id: "id"
I had done programmer math and translated that to a zero-based format, but maybe it's the header that's the issue?
-- ANSWER: YES. argh.
/EDIT
I've found some posts in different places that seem to involve JSON fields, but the schema is fairly simple, and only simple objects are used:
Table "public.users"
Column | Type | Collation | Nullable | Default
------------------+--------------------------+-----------+----------+---------------------
id | uuid | | not null |
name | text | | not null |
username | text | | not null |
password_hash | text | | not null |
created_at | timestamp with time zone | | |
updated_at | timestamp with time zone | | |
tournament_id | uuid | | |
background | text | | |
as_player | boolean | | |
as_streamer | boolean | | |
administrator | administrator | | not null | 'no'::administrator
creator | boolean | | not null | false
creator_approved | boolean | | not null | true
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"uq:users.username" UNIQUE CONSTRAINT, btree (username)
Referenced by:
TABLE "tokens" CONSTRAINT "tokens_userID_fkey" FOREIGN KEY ("userID") REFERENCES users(id) ON DELETE CASCADE
TABLE "tournament_player_pivot" CONSTRAINT "tournament_player_pivot_playerID_fkey" FOREIGN KEY ("playerID") REFERENCES users(id)
The table the data was exported from and the table I'm trying to import to have the identical schema. I've come across suggestions that there is a specific single-quoted format for UUID fields, but manually modifying that has no effect.
What is the problem here?
This is a sample from the export file using a testing user:
id,name,username,password_hash,created_at,updated_at,tournament_id,background,as_player,as_streamer,administrator,creator,creator_approved
ad5230b4-2377-4a8d-8725-d49cd78121af,z9,z9#test.com,$2b$12$97GXVp1p.nfke8L4EYK2Fuev9IE3k0WFAf4O3NvziYHjogFCAppO6,2022-05-07 06:03:44.020019+00,2022-05-07 06:03:44.020019+00,,,f,f,no,f,t

Find related columns in between two Table

Imagine, you have two tables.
And each Table has a lot of columns.
I did not create the database, so I really don't know what columns are related.
One problem is there's no same Column name in between two tables, So I can not figure out by column name.
How can I find the column which is related to two different tables?
If there are foreign keys between the tables, then you can find the relationship between them. To do this, you can call \d on a table and see the foreign keys associated with its columns. Without explicit foreign keys, then there is no way to determine the relationship between tables except by talking with the developers and/or technical decision-makers.
An example of how the foreign key relationship is displayed in psql:
postgres=# alter table pgbench_accounts add constraint "pgb_accounts_branches_fk" foreign key (bid) references pgbench_branches (bid);
ALTER TABLE
postgres=# \d pgbench_accounts
Table "public.pgbench_accounts"
Column | Type | Collation | Nullable | Default
----------+---------------+-----------+----------+---------
aid | integer | | not null |
bid | integer | | |
abalance | integer | | |
filler | character(84) | | |
Indexes:
"pgbench_accounts_pkey" PRIMARY KEY, btree (aid)
Foreign-key constraints:
"pgb_accounts_branches_fk" FOREIGN KEY (bid) REFERENCES pgbench_branches(bid)
postgres=# \d pgbench_branches
Table "public.pgbench_branches"
Column | Type | Collation | Nullable | Default
----------+---------------+-----------+----------+---------
bid | integer | | not null |
bbalance | integer | | |
filler | character(88) | | |
Indexes:
"pgbench_branches_pkey" PRIMARY KEY, btree (bid)
Referenced by:
TABLE "pgbench_accounts" CONSTRAINT "pgb_accounts_branches_fk" FOREIGN KEY (bid) REFERENCES pgbench_branches(bid)
postgres=#

Deleting records which have foreign key to partitioned table on PostgreSQL

I have a partitioned table called datapoint which have child tables like datapoint_s1, datapoint_s2, ...
I have another table called device which has foreign key to datapoint table.
Here is the story;
Datapoint table is about 100GB with all partitioned tables. I truncated datapoint_s2 table. After that, I want to delete devices belongs to datapoints_s2 table. Also, there is no data in other partitioned tables related to devices I want to delete. Although the datapoint_s2 table is empty, COMMIT; is waiting more than one hour to complete process.
Edit: When I cancel the query, this error occured.
ERROR: canceling statement due to user request
CONTEXT: SQL statement "SELECT 1 FROM "public"."datapoint" x WHERE $1 OPERATOR(pg_catalog.=) "device_id" FOR KEY SHARE OF x"
How I can make device deletion process faster in partitioned tables?
Edit:
Parent table description:
Table "public.datapoint"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
------------+--------------------------+-----------+----------+---------------------------------------+----------+--------------+-------------
id | bigint | | not null | nextval('datapoint_id_seq'::regclass) | plain | |
station_id | integer | | not null | | plain | |
device_id | integer | | not null | | plain | |
data | jsonb | | | | extended | |
created_at | timestamp with time zone | | not null | | plain | |
Partition key: LIST (station_id)
Indexes:
"datapoint_uniq" UNIQUE CONSTRAINT, btree (station_id, device_id, created_at)
Foreign-key constraints:
"datapoint_device_id_fk" FOREIGN KEY (device_id) REFERENCES device(id) DEFERRABLE INITIALLY DEFERRED
"datapoint_station_id_fk" FOREIGN KEY (station_id) REFERENCES station(id) DEFERRABLE INITIALLY DEFERRED
Partitions: datapoint_s2 FOR VALUES IN (10),
datapoint_s3 FOR VALUES IN (11),
....
Child table description:
Table "public.datapoint_s2"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
------------+--------------------------+-----------+----------+---------------------------------------+----------+--------------+-------------
id | bigint | | not null | nextval('datapoint_id_seq'::regclass) | plain | |
station_id | integer | | not null | | plain | |
device_id | integer | | not null | | plain | |
data | jsonb | | | | extended | |
created_at | timestamp with time zone | | not null | | plain | |
Partition of: solarify_datapoint FOR VALUES IN (2)
Partition constraint: ((station_id IS NOT NULL) AND (station_id = 2))
Indexes:
"datapoint_s2_station_id_device_id_created_at_key" UNIQUE CONSTRAINT, btree (station_id, device_id, created_at)
Foreign-key constraints:
"datapoint_device_id_fk" FOREIGN KEY (device_id) REFERENCES device(id) DEFERRABLE INITIALLY DEFERRED
"datapoint_station_id_fk" FOREIGN KEY (station_id) REFERENCES station(id) DEFERRABLE INITIALLY DEFERRED

Two Postgres tables with same column name and same Index name. Need to drop index on one of them

I have two tables:
x_development=# \d+ xref__email_addresses__organizations
Table "public.xref__email_addresses__organizations"
Column | Type | Modifiers | Storage | Stats target | Description
-------------------------+-----------------------------+------------------------+---------+--------------+-------------
email_address_id | integer | not null | plain | |
rorganization_id | integer | not null | plain | |
last_update | timestamp without time zone | not null default now() | plain | |
Indexes:
"email_address_id_idx" UNIQUE, btree (email_address_id)
"xref_idx" UNIQUE, btree (email_address_id, organization_id)
Foreign-key constraints:
"email_address_id_fkey" FOREIGN KEY (email_address_id) REFERENCES email_addresses(email_address_id) ON UPDATE CASCADE ON DELETE RESTRICT
"organization_id_fkey" FOREIGN KEY (realtor_organization_id) REFERENCES realtor_organizations(realtor_organization_id) ON UPDATE CASCADE ON DELETE RESTRICT
x_development=# \d+ email_addresses
Table "public.email_addresses"
Column | Type | Modifiers | Storage | Stats target | Description
--------------------+---------+----------------------------------------------------------------------------+----------+--------------+-------------
email_address_id | integer | not null default nextval('email_addresses_email_address_id_seq'::regclass) | plain | |
email_address | citext | not null | extended | |
unsubscribe_reason | text | not null default ''::text | extended | |
Indexes:
"email_addresses_pkey" PRIMARY KEY, btree (email_address_id)
"email_address_idx" UNIQUE, btree (email_address)
Referenced by:
TABLE "xref__email_addresses__organizations" CONSTRAINT "email_address_id_fkey" FOREIGN KEY (email_address_id) REFERENCES email_addresses(email_address_id) ON UPDATE CASCADE ON DELETE RESTRICT
Note they both have an email_address_id column and
"email_address_id_idx" UNIQUE, btree (email_address_id) index.
I need to drop the email_address_id_idx on the xref__email_addresses__organizations table but it seems if mis-created the table by having two identical index names.
How do I drop the email_address_id_idx from the xref__email_addresses__organizations table?
From what i have understood, the indexes are different. One of them is email_address_id_idx and the other is email_address_idx. So I Think you can just use drop index to remove the desired one.

Error:"Key ... is not present in table"

I have a table with a character varying(12) field in it which is its PRIMARY KEY. I ran this query
SELECT * FROM bg WHERE bg_id ='470370111002'
It selects a row from the table. All looks good. Then I try.
INSERT INTO csapp_center_bgs(bg_id,center_id) VALUES('470370111002',2)
There is a foreign key on bg_id that looks like...
ALTER TABLE csapp_center_bgs
ADD CONSTRAINT csapp_center_bgs_bg_id_65c818f360c84dc5_fk_bg_bg_id
FOREIGN KEY (bg_id)
REFERENCES tiger.bg (bg_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED;
Here is the precise error...
ERROR: insert or update on table "csapp_center_bgs" violates foreign key constraint "csapp_center_bgs_bg_id_65c818f360c84dc5_fk_bg_bg_id"
DETAIL: Key (bg_id)=(470370111002) is not present in table "bg".
********** Error **********
ERROR: insert or update on table "csapp_center_bgs" violates foreign key constraint "csapp_center_bgs_bg_id_65c818f360c84dc5_fk_bg_bg_id"
SQL state: 23503
Detail: Key (bg_id)=(470370111002) is not present in table "bg".
Why did this not work?! Any ideas? Here is \d+ bg...
Column | Type | Modifiers | Storage | Stats target | Description
----------+-----------------------+--------------------------------------------------+----------+--------------+-------------
gid | integer | not null default nextval('bg_gid_seq'::regclass) | plain | |
statefp | character varying(2) | | extended | |
countyfp | character varying(3) | | extended | |
tractce | character varying(6) | | extended | |
blkgrpce | character varying(1) | | extended | |
bg_id | character varying(12) | not null | extended | |
namelsad | character varying(13) | | extended | |
mtfcc | character varying(5) | | extended | |
funcstat | character varying(1) | | extended | |
aland | double precision | | plain | |
awater | double precision | | plain | |
intptlat | character varying(11) | | extended | |
intptlon | character varying(12) | | extended | |
the_geom | geometry | | main | |
Indexes:
"bg_pkey" PRIMARY KEY, btree (bg_id)
"idx_bg_geom" gist (the_geom) CLUSTER
Check constraints:
"enforce_dims_geom" CHECK (st_ndims(the_geom) = 2)
"enforce_geotype_geom" CHECK (geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL)
"enforce_srid_geom" CHECK (st_srid(the_geom) = 4269)
Referenced by:
TABLE "csapp_center_bgs" CONSTRAINT "csapp_center_bgs_bg_id_65c818f360c84dc5_fk_bg_bg_id" FOREIGN KEY (bg_id) REFERENCES bg(bg_id) DEFERRABLE INITIALLY DEFERRED
Child tables: tiger_data.tn_bg
Has OIDs: no
And here is \d+ on csapp_...
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------+---------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('csapp_center_bgs_id_seq'::regclass) | plain | |
bg_id | character varying(12) | not null | extended | |
center_id | integer | not null | plain | |
Indexes:
"csapp_center_bgs_pkey" PRIMARY KEY, btree (id)
"csapp_center_bgs_5e94e25f" btree (bg_id)
"csapp_center_bgs_c63f1184" btree (center_id)
Foreign-key constraints:
"csapp_center_bgs_bg_id_65c818f360c84dc5_fk_bg_bg_id" FOREIGN KEY (bg_id) REFERENCES bg(bg_id) DEFERRABLE INITIALLY DEFERRED
"csapp_center_bgs_center_id_360e6806f7d3fee_fk_csapp_centers_id" FOREIGN KEY (center_id) REFERENCES csapp_centers(id) DEFERRABLE INITIALLY DEFERRED
Has OIDs: no
Here is the version:
version
------------------------------------------------------------------------------------------------------
PostgreSQL 9.3.5 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64-bit
And here is my search path....
search_path
---------------
public, tiger
(1 row)
bg is in schema tiger and csapp_center_bgs is in schema public...
My first guess would be that you are dealing with two different tables named bg. One in the schema tiger, and another one in an undisclosed schema that comes before tiger in your search_path - or tiger is not in the search_path at all.
Find all tables named bg (case sensitive) in all schemas in the current db:
SELECT * FROM pg_tables WHERE tablename = 'bg';
To understand the search_path setting:
How does the search_path influence identifier resolution and the "current schema"
To understand the structure of a Postgres DB cluster:
What's the difference between a catalog and a schema in a relational database?
If that's not it, your index may be corrupted. I would first try a REINDEX:
REINDEX bg_pkey;
Inheritance!
I see in your added table definition:
Child tables: tiger_data.tn_bg
Suspecting that the row with bg_id ='470370111002' actually lives in the child table tiger_data.tn_bg. But your FK constraint references the parent table. FK constraints are not inherited.
What do you get if you query:
SELECT * FROM ONLY bg WHERE bg_id ='470370111002'
If my hypothesis holds, you get no row. Read the chapter Caveats on the Inheritance page of the manual.
Related:
Use triggers on inherited tables to replace foreign keys