Change Index in Postgres - postgresql

I have been facing a problem on my django application while trying to add an value to a model. It seems that there is a constraint in the DB that should not be there, according to models.py. The error I get is:
IntegrityError: null value in column "column_x_ptr_id" violates not-null constraint
Doing a \dt in psql, I get:
Indexes:
"mytable_model_pkey" PRIMARY KEY, btree (column_x_ptr_id)
"mytable_model_p_key" UNIQUE CONSTRAINT, btree (column_y_ptr_id)
So, my question is how can I modify this index like so?
"mytable_model_pkey" PRIMARY KEY, btree (column_y_ptr_id)
I'm not sure that would solve the problem though..

Ok this will give you a "more or less" of what you need to do. Your table looks something like this:
CREATE TABLE mytable_model
(
column_x_ptr_id integer NOT NULL,
column_y_ptr_id integer,
CONSTRAINT mytable_model_pkey PRIMARY KEY (column_x_ptr_id),
CONSTRAINT mytable_model_p_key UNIQUE (column_y_ptr_id)
)
You need to drop both indexes, create a new PK on the second column, and remove the NOT NULL constraint:
ALTER TABLE mytable_model DROP CONSTRAINT mytable_model_pkey;
ALTER TABLE mytable_model DROP CONSTRAINT mytable_model_p_key;
ALTER TABLE mytable_model ADD CONSTRAINT mytable_model_pkey PRIMARY KEY (column_y_ptr_id);
ALTER TABLE mytable_model ALTER COLUMN column_x_ptr_id DROP NOT NULL;
Bear in mind that adding a primary key to column_y_ptr_id will change the column to NOT NULL. If any records have NULL in that field, this will fail. Then as I mentioned, you will probably want to put another index on column_x_ptr_id for performance reasons. What type you use is up to you.

Related

there is no unique constraint matching given keys for referenced table "employees" [duplicate]

Trying to create this example table structure in Postgres 9.1:
CREATE TABLE foo (
name VARCHAR(256) PRIMARY KEY
);
CREATE TABLE bar (
pkey SERIAL PRIMARY KEY,
foo_fk VARCHAR(256) NOT NULL REFERENCES foo(name),
name VARCHAR(256) NOT NULL,
UNIQUE (foo_fk,name)
);
CREATE TABLE baz(
pkey SERIAL PRIMARY KEY,
bar_fk VARCHAR(256) NOT NULL REFERENCES bar(name),
name VARCHAR(256)
);
Running the above code produces an error, which does not make sense to me:
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
NOTICE: CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "bar_pkey" for table "bar"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar"
NOTICE: CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "baz_pkey" for table "baz"
ERROR: there is no unique constraint matching given keys for referenced table "bar"
********** Error **********
ERROR: there is no unique constraint matching given keys for referenced table "bar"
SQL state: 42830
Can anyone explain why this error arises?
It's because the name column on the bar table does not have the UNIQUE constraint.
So imagine you have 2 rows on the bar table that contain the name 'ams' and you insert a row on baz with 'ams' on bar_fk, which row on bar would it be referring since there are two rows matching?
In postgresql all foreign keys must reference a unique key in the parent table, so in your bar table you must have a unique (name) index.
See also http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK and specifically:
Finally, we should mention that a foreign key must reference columns
that either are a primary key or form a unique constraint.
Emphasis mine.
You should have name column as a unique constraint. here is a 3 lines of code to change your issues
First find out the primary key constraints by typing this code
\d table_name
you are shown like this at bottom "some_constraint" PRIMARY KEY, btree (column)
Drop the constraint:
ALTER TABLE table_name DROP CONSTRAINT some_constraint
Add a new primary key column with existing one:
ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);
That's All.
when you do UNIQUE as a table level constraint as you have done then what your defining is a bit like a composite primary key see ddl constraints, here is an extract
This specifies that the combination of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique.
this means that either field could possibly have a non unique value provided the combination is unique and this does not match your foreign key constraint.
most likely you want the constraint to be at column level. so rather then define them as table level constraints, 'append' UNIQUE to the end of the column definition like name VARCHAR(60) NOT NULL UNIQUE or specify indivdual table level constraints for each field.

ERROR: there is no unique constraint matching given keys for referenced table "mail_message" Odoo Postgres [duplicate]

Trying to create this example table structure in Postgres 9.1:
CREATE TABLE foo (
name VARCHAR(256) PRIMARY KEY
);
CREATE TABLE bar (
pkey SERIAL PRIMARY KEY,
foo_fk VARCHAR(256) NOT NULL REFERENCES foo(name),
name VARCHAR(256) NOT NULL,
UNIQUE (foo_fk,name)
);
CREATE TABLE baz(
pkey SERIAL PRIMARY KEY,
bar_fk VARCHAR(256) NOT NULL REFERENCES bar(name),
name VARCHAR(256)
);
Running the above code produces an error, which does not make sense to me:
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
NOTICE: CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "bar_pkey" for table "bar"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar"
NOTICE: CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "baz_pkey" for table "baz"
ERROR: there is no unique constraint matching given keys for referenced table "bar"
********** Error **********
ERROR: there is no unique constraint matching given keys for referenced table "bar"
SQL state: 42830
Can anyone explain why this error arises?
It's because the name column on the bar table does not have the UNIQUE constraint.
So imagine you have 2 rows on the bar table that contain the name 'ams' and you insert a row on baz with 'ams' on bar_fk, which row on bar would it be referring since there are two rows matching?
In postgresql all foreign keys must reference a unique key in the parent table, so in your bar table you must have a unique (name) index.
See also http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK and specifically:
Finally, we should mention that a foreign key must reference columns
that either are a primary key or form a unique constraint.
Emphasis mine.
You should have name column as a unique constraint. here is a 3 lines of code to change your issues
First find out the primary key constraints by typing this code
\d table_name
you are shown like this at bottom "some_constraint" PRIMARY KEY, btree (column)
Drop the constraint:
ALTER TABLE table_name DROP CONSTRAINT some_constraint
Add a new primary key column with existing one:
ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);
That's All.
when you do UNIQUE as a table level constraint as you have done then what your defining is a bit like a composite primary key see ddl constraints, here is an extract
This specifies that the combination of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique.
this means that either field could possibly have a non unique value provided the combination is unique and this does not match your foreign key constraint.
most likely you want the constraint to be at column level. so rather then define them as table level constraints, 'append' UNIQUE to the end of the column definition like name VARCHAR(60) NOT NULL UNIQUE or specify indivdual table level constraints for each field.

Make a previously existing foreign key column have a unique constraint in postgres

I need to create a migration for an already existing table to make it's foreign key have a UNIQUE constraint. How do I do this?
From the examples I found in the documentation, it is mostly done when the table is created. The issue is I need to add this onto a column that already exists and is already set as a foreign key. This is what the table looks like at it's creation:
CREATE TABLE IF NOT EXISTS "myTable" (
"_id" SERIAL NOT NULL,
"myForeignKeyId" INTEGER NOT NULL,
"name" VARCHAR(255) NOT NULL,
CONSTRAINT "pk_myTable" PRIMARY KEY ("_id"),
CONSTRAINT "fk_myTable_myForeignKeyId" FOREIGN KEY ("myForeignKeyId") REFERENCES "myOtherTable" ("_id")
);
What I want to do is on a migration make myForeignKeyId unique. How do I do that?
I have tried to following:
CREATE UNIQUE INDEX CONCURRENTLY "myTable_myForeignKeyId"
ON province ("myForeignKeyId");
ALTER TABLE IF EXISTS "myTable"
ADD CONSTRAINT "myForeignKeyId"
UNIQUE USING INDEX "myTable_myForeignKeyId";
First off, when I try this in a migration I get the error:
CREATE INDEX CONCURRENTLY cannot run inside a transaction block
So that part cannot be done, but even just doing it through SQL, the second part doesn't work either as it claims myForeignKeyId already exists. Even if I add an ALTER COLUMN myForeignKeyId it just says there is an error on that line.
This seems like it should be a simple enough operation, how can I do this?
After digging some more found quite a simple way to do this, was clearly originally off target.
To add a unique constraint to a column:
ALTER TABLE "myTable"
ADD CONSTRAINT "myUniqueKeyNameOfChoice" UNIQUE ("myColumn");
To remove it:
ALTER TABLE "myTable"
DROP CONSTRAINT "myUniqueKeyNameOfChoice";

Alter the table by adding constraint and using index in postgresql getting an error syntax error at or near "("IDX_emp_PK

CREATE INDEX IDX_emp_PK ON
EMP(ID);
ALTER TABLE EMP ADD
CONSTRAINT PK_emp PRIMARY KEY (ID)
USING INDEX IDX_emp_PK;
There are two errors in your script:
First: you can't use a non-unique index for a primary key constraint, so you need
CREATE UNIQUE INDEX idx_emp_pk ON emp(id);
When you add a primary or unique constraint based on an index, you can't specify columns (as they are already defined in the index):
ALTER TABLE emp ADD
CONSTRAINT pk_emp PRIMARY KEY
USING INDEX idx_emp_pk;

How to disable foreign key and primary key constraint temporarily in PostgreSQL?

I have one table that has two fields. The structure is like this:
CREATE TABLE raw_links
(
value_id bigint NOT NULL,
raw_id integer NOT NULL,
CONSTRAINT raw_links_pk PRIMARY KEY (raw_id, dp_id),
CONSTRAINT raw_fk FOREIGN KEY (raw_id)
REFERENCES raw_data (raw_data_id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT
)
I have to delete 5 million records from this table. For that I want to disable both constraints so that deletion will be faster. After deletion I want to create both constraints.
You can do ALTER TABLE DROP CONSTRAINT raw_links_pk and the same for raw_fk.
After you delete the records, first do a VACUUM ANALYZE raw_links (or VACUUM FULL raw_links if you want to reclaim disk space), to update the table statistics.
Then finally rebuild the constraints with ALTER TABLE ADD CONSTRAINT ....
For the example.
Schema: source, Table: finalsales, Constrait: finalsales_pkey, Column: order_id.
--Disable Primary Key
ALTER TABLE source."finalsales" DROP CONSTRAINT finalsales_pkey;
--Enable Primary Key
ALTER TABLE source."finalsales"
ADD CONSTRAINT finalsales_pkey PRIMARY KEY ( order_id );