Compound foreign key constraint with a String literal - postgresql

I have a table with a compound primary key:
Table "account.enum"
Column | Type | Modifiers
-----------+------------------------+-----------
classname | character varying(256) | not null
name | character varying(64) | not null
active | boolean | not null
Indexes: "enum_pkey" PRIMARY KEY, btree (classname, name)
Values:
classname | name | active
--------------+--------+--------
CURRENCY | EUR | t
CURRENCY | USD | t
MUTATIONTYPE | CREDIT | t
MUTATIONTYPE | DEBET | t
Another table account uses this table:
Table "account.mutation"
Column | Type | Modifiers
-----------------+------------------------+-------------------------------------------------------
id | bigint | not null default nextval('mutation_id_seq'::regclass)
accountnumber | character varying(9) | not null
interestdate | date | not null
balancebefore | numeric(10,2) | not null
balanceafter | numeric(10,2) | not null
transactiondate | date | not null
amount | numeric(10,2) | not null
description | character varying(512) | not null
ordernumber | smallint | default (-1)
mutationtype | character varying(64) |
currency | character varying(64) |
I want to add foreign key constraints (for mutationtype and currency):
alter table mutation add constraint FK_mutationtype foreign key('MUTATIONTYPE', mutationtype) references enum(classname, name);
alter table mutation add constraint FK_currency foreign key('CURRENCY', currency) references enum(classname, name);
However the string literals are not accepted.
What am I doing wrong? Is what I want possible in postgres?

You cannot do this because foreign keys can only be defined on columns, not on expressions like the literal 'MUTATIONTYPE'.
You could introduce a column like mutation_class in mutation that is always set to 'MUTATIONTYPE', but that sounds wasteful, redundant and silly.
I think that you should solve the problem by having different lookup tables for the different enumerations, then the difficulty would just vanish, and the whole design looks more reasonable from a relational perspective.

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

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.

Postgres Datebase multi foreign keys

I have a table described as following:
Table "public.lead"
Column | Type | Modifiers
-----------------------------+--------------------------------+-----------------------------------------
id | character varying(36) | not null
reference_code | character varying(20) | not null
country_id | character varying(36) | not null
language_id | character varying(36) | not null
locale_id | character varying(36) | not null
from_country_id | character varying(36) | not null
to_country_id | character varying(36) | not null
customer_id | character varying(36) | not null
user_id | character varying(36) |
from_date | date | not null
from_date_type | smallint | not null default (0)::smallint
from_street | character varying(200) |
from_postalcode | character varying(25) |
from_city | character varying(100) |
from_country | character varying(50) |
from_apartment_type | character varying(255) | not null default '0'::character varying
from_floor | smallint |
from_rooms | numeric(3,1) |
from_people | integer |
from_squaremeter | integer |
from_elevator | smallint | not null
I am trying to create foreign keys for (country_id, from_country_id, to_country_id)
As you can see all these 3 fields has a relation with table.
But when i try to create these foreign keys, i got the following error.
ERROR: insert or update on table "lead" violates foreign key constraint "lead_to_country_id" Detail: Key (to_country_id)=(United Kingdom) is not present in table "country".
Details
This error is often related to a missing key.
When you try to create a foreign key AFTER an insert statement, SQL searches for those keys in the table which has the Primary Key (PK).
Eg.
table_with_PK
col1(Pk) | col2| coln ...
id_1 foo bar ...
id_2 nan ana ...
table_connected_to_table_with_PK
col1(Fk) | col2 | etc...
id_1
id_2
id_3 (Error because not present in table_with_PK)
So first create the table which has your primary keys, then populate it.
Second create the table with foreign keys, make foreign keys(Fk), then populate/update it, in order to have coherence in your database.
Check postgresql documentation on constraints: https://www.postgresql.org/docs/current/static/ddl-constraints.html
The error message pretty much says it: You are trying to set the to_country_id column value to 'United Kingdom' which does not exist in the referenced country table. Insert that value into the country table and retry.

Insert row into a postgresql table

I have the following table definition:
foo=# \d+ tag
Table "public.tag"
Column | Type | Modifiers | Storage | Stats target | Description
-------------+------------------------+--------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('tag_id_seq'::regclass) | plain | |
name | character varying(255) | not null | extended | |
version | integer | not null | plain | |
description | character varying(255) | not null | extended | |
active | boolean | not null | plain | |
Indexes:
"tag_pkey" PRIMARY KEY, btree (id)
"unique_tag" UNIQUE CONSTRAINT, btree (name, version)
I am trying to insert a row into as follows:
foo=# insert into tag (name, version, description, active) values ("scala", 1, "programming language", true);
ERROR: column "scala" does not exist
LINE 1: ... tag (name, version, description, active) values ("scala", 1...
I took this command from the manual but it doesn't work. What I am doing wrong? It's a simple thing but I'm stumped. First time I am using postgres.
Postgres uses single quotes.
insert into tag (name, version, description, active) values ('scala', 1, 'programming language', true);