postgres Foreign Key to only accept table names - postgresql

I'm using postgres, and I want to log new changes in several of my tables. I want to have a column which will only take on values which are table names, so that I can have a column for table, column for id, and column for date that that value was updated.
I see that all the table names are in the table information_schema.tables. Is it possible to use that as a foreign key, or would that be inadvisable?

Related

postgresql partitioned table primary key issue

I am working on a requirement to create partition for customer name table in Postgresql DB. Primary Key of this table is an auto generated sequence number.
Since regular table cannot be turned into a partitioned table, I am planning to create a new partitioned table with primary key as composite key (sequence number + first letter of the customer's name).
I am not sure if it is required to define different sequence number one for each partition of customer name or defining the sequence number for partitioned table once will work.

PostgreSQL id column not defined

I am new in PostgreSQL and I am working with this database.
I got a file which I imported, and I am trying to get rows with a certain ID. But the ID is not defined, as you can see it in this picture:
so how do I access this ID? I want to use an SQL command like this:
SELECT * from table_name WHERE ID = 1;
If any order of rows is ok for you, just add a row number according to the current arbitrary sort order:
CREATE SEQUENCE tbl_tbl_id_seq;
ALTER TABLE tbl ADD COLUMN tbl_id integer DEFAULT nextval('tbl_tbl_id_seq');
The new default value is filled in automatically in the process. You might want to run VACUUM FULL ANALYZE tbl to remove bloat and update statistics for the query planner afterwards. And possibly make the column your new PRIMARY KEY ...
To make it a fully fledged serial column:
ALTER SEQUENCE tbl_tbl_id_seq OWNED BY tbl.tbl_id;
See:
Creating a PostgreSQL sequence to a field (which is not the ID of the record)
What you see are just row numbers that pgAdmin displays, they are not really stored in the database.
If you want an artificial numeric primary key for the table, you'll have to create it explicitly.
For example:
CREATE TABLE mydata (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
obec text NOT NULL,
datum timestamp with time zone NOT NULL,
...
);
Then to copy the data from a CSV file, you would run
COPY mydata (obec, datum, ...) FROM '/path/to/csvfile' (FORMAT 'csv');
Then the id column is automatically filled.

Add column to show a row number in the PostgreSQL [duplicate]

I have a table with existing data. Is there a way to add a primary key without deleting and re-creating the table?
(Updated - Thanks to the people who commented)
Modern Versions of PostgreSQL
Suppose you have a table named test1, to which you want to add an auto-incrementing, primary-key id (surrogate) column. The following command should be sufficient in recent versions of PostgreSQL:
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
Older Versions of PostgreSQL
In old versions of PostgreSQL (prior to 8.x?) you had to do all the dirty work. The following sequence of commands should do the trick:
ALTER TABLE test1 ADD COLUMN id INTEGER;
CREATE SEQUENCE test_id_seq OWNED BY test1.id;
ALTER TABLE test1 ALTER COLUMN id SET DEFAULT nextval('test_id_seq');
UPDATE test1 SET id = nextval('test_id_seq');
Again, in recent versions of Postgres this is roughly equivalent to the single command above.
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
This is all you need to:
Add the id column
Populate it with a sequence from 1 to count(*).
Set it as primary key / not null.
Credit is given to #resnyanskiy who gave this answer in a comment.
To use an identity column in v10,
ALTER TABLE test
ADD COLUMN id { int | bigint | smallint}
GENERATED { BY DEFAULT | ALWAYS } AS IDENTITY PRIMARY KEY;
For an explanation of identity columns, see https://blog.2ndquadrant.com/postgresql-10-identity-columns/.
For the difference between GENERATED BY DEFAULT and GENERATED ALWAYS, see https://www.cybertec-postgresql.com/en/sequences-gains-and-pitfalls/.
For altering the sequence, see https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/.
I landed here because I was looking for something like that too. In my case, I was copying the data from a set of staging tables with many columns into one table while also assigning row ids to the target table. Here is a variant of the above approaches that I used.
I added the serial column at the end of my target table. That way I don't have to have a placeholder for it in the Insert statement. Then a simple select * into the target table auto populated this column. Here are the two SQL statements that I used on PostgreSQL 9.6.4.
ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
ALTER TABLE test1 ADD id int8 NOT NULL GENERATED ALWAYS AS IDENTITY;

Altering table for adding foreign key constraint take very long time

I have one table manual_errors_archive. I need to add foreign key to this table keeping reference to values table, values table having 800,000 records and manual_errors_archive table does not have any records.
ALTER TABLE manual_errors_archive
ADD CONSTRAINT fk_manua_reference_value
FOREIGN KEY (value_id)
REFERENCES values;
Postgres version i am using 9.1
But this is running for more than 1 hr after that I canceled the process. Any idea how to optimize this process?

Modifying column data type

I have two tables like Samp1(Parent Table) and Samp2 (Child table)
Parent Table :Samp1
column Datatype Constraint
----------------------------------------
Id Number(6) Primary Key
Child table :Samp2
column Datatype Constraint
----------------------------------------------
Id Number(6) Foriegn Key
Then how to modify column data type Number to Varchar2(10) both parent and child table at a time, can I?
You can't do this in one step. Assuming the tables have data, you'd probably need to do something like
Add a new column (e.g. id_varchar) to your parent table
Populate the data in this new column from the data in the existing column
Add that new column to the child table
Populate the data in this new column from the data in the existing column
Create a new foreign key constraint for the new column
Drop the existing foreign key constraint
Drop the existing primary key constraint
Drop the existing id columns from both tables
Rename the id_varchar column to id in each table
Create a new primary key constraint on the parent table
Normally, this would require some downtime since you generally don't want sessions modifying data while you're doing this. If you need to do this online, you could potentially use the dbms_redefinition package which would involve creating new copies of both tables.