Drop unique index when having Primary Key index - sql

I have the following table
CREATE TABLE steps (
hash_id text UNIQUE PRIMARY KEY,
depth integer
);
-- Indices -------------------------------------------------------
CREATE UNIQUE INDEX steps_hash_id_key ON steps(hash_id text_ops);
CREATE UNIQUE INDEX steps_pkey ON steps(hash_id text_ops);
But I'd like to remove the redundant UNIQUE index because PRIMARY KEY is already unique.
I've also many other tables linked to the hash_id of my steps table with foreign keys.
When I try to remove my UNIQUE index like this:
ALTER TABLE steps DROP CONSTRAINT steps_hash_id_key;
I get
ERROR: cannot drop constraint steps_hash_id_key on table steps because other objects depend on it
DETAIL: constraint steps_routes_step_hash_id_fkey on table steps_routes depends on index steps_hash_id_key
constraint steps_likes_dislikes_step_hash_id_fkey on table steps_likes_dislikes depends on index steps_hash_id_key
HINT: Use DROP ... CASCADE to drop the dependent objects too.
The matter is that I don't want to cascade delete anything, I'd just like to remove this duplicated unique index. Is it possible ?

Thanks to the discussion in comments (#Gordon Linoff) here's a way to fix this issue:
Drop foreign keys
Drop Primary Keys and Unique Keys
Recreate Primary Key only
Recreate Foreign Keys
ALTER TABLE steps_routes DROP CONSTRAINT steps_routes_step_hash_id_fkey;
ALTER TABLE steps_likes_dislikes DROP CONSTRAINT steps_likes_dislikes_step_hash_id_fkey;
ALTER TABLE steps DROP CONSTRAINT steps_pkey;
ALTER TABLE steps DROP CONSTRAINT steps_hash_id_key;
ALTER TABLE steps ADD PRIMARY KEY (hash_id);
ALTER TABLE steps_routes ADD FOREIGN KEY (step_hash_id) REFERENCES steps(hash_id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE steps_likes_dislikes ADD FOREIGN KEY (step_hash_id) REFERENCES steps(hash_id) ON DELETE CASCADE ON UPDATE CASCADE;

Related

DB2 - Can I recreate a foreign key constraint in a table with data?

I'm having the following problem with DB2:
I need to change a column name (column "A"), but the thing is that column A has a PK constraint and a FK constraint. So I need to drop this constraints first, change the column name and then create the constraints again. But I remember a Professor told me once that you can't create a foreign key in a column which already has values. Is that true?
This is my script:
ALTER TABLE TARGET_TABLE
DROP PRIMARY KEY PK_A CASCADE;
ALTER TABLE TARGET_TABLE
RENAME COLUMN A TO B;
alter table TARGET_TABLE
add CONSTRAINT PK_B PRIMARY KEY( B);
alter table TARGET_TABLE add CONSTRAINT FK_B FOREIGN KEY( B) REFERENCES OTHER_TABLE(C);
Thanks in advance.
You can create a foreign key on a column which already has values. The only restriction is that the values must be be valid for the FK you are defining.
If not you will get an error such as
SQL0667N The FOREIGN KEY "I..." cannot be created because the table contains
rows with foreign key values that cannot be found in the parent key of the
parent table. SQLSTATE=23520

CASCADE behaviour on the drop of a foreign key

I am not clear about what happens when a "foreign key constraint" is deleted specifying the option CASCADE.
For instance, consider this command
ALTER TABLE table1 DROP CONSTRAINT foreignKeyToTable2 CASCADE.
What the option CASCADE is supposed to do in this case? What would happen if I omitted it? And if I wrote RESTRICT instead of CASCADE?
Note: this example of query is excerpted from "Ramez Elmasri, Shamkant B. Navathe - Fundamentals of database systems, end of chapter 5".
The cascade option to drop a constraint is only needed when dropping primary keys, not when dropping a foreign key.
Consider this example in Postgres:
create table t1 (id integer, constraint pk_one primary key (id));
create table t2 (id integer primary key, id1 integer references t1);
When you try to run:
alter table t1 drop constraint pk_one;
You get:
ERROR: cannot drop constraint pk_one on table t1 because other objects depend on it
Detail: constraint t2_id1_fkey on table t2 depends on index pk_one
Hint: Use DROP ... CASCADE to drop the dependent objects too.
If you run:
alter table t1 drop constraint pk_one cascade;
you get:
NOTICE: drop cascades to constraint t2_id1_fkey on table t2
Telling you that the foreign key that needed the primary key was dropped as well.
Note that not all DBMS support a cascading drop. Postgres and Oracle do.
MySQL, SQL Server or Firebird do not. You need to drop the foreign keys manually in those DBMS.

How to turn a Unique Constraint into a Primary key in PostgreSQL?

i have a table that has a primary key on some columns, and another unique constraint on another column. I dropped the old primary key, and now want to make the existing unique constraint the new primary key of the table, without dropping/rebuilding it from scratch.
The situation right now is like this:
Indexes:
"t_review_routing_id_key" UNIQUE CONSTRAINT, btree (id)
When I run:
ALTER TABLE t_review_routing ADD PRIMARY KEY USING INDEX t_review_routing_id_key;
It says:
ERROR: index "t_review_routing_id_key" is already associated with a constraint
LINE 1: ALTER TABLE t_review_routing ADD PRIMARY KEY USING INDEX t_r...
I also tried ALTER TABLE t_review_routing ADD CONSTRAINT t_review_routing_id_pkey PRIMARY KEY USING INDEX t_review_routing_id_key;, same error.
Any ideas?
You can drop your already existing constraint before creating the new one, but dropping the constraint will make the index disappear too.
But, you can create a new index CONCURRENTLY (example from the docs):
CREATE UNIQUE INDEX CONCURRENTLY dist_id_temp_idx ON distributors (dist_id);
ALTER TABLE distributors DROP CONSTRAINT distributors_pkey,
ADD CONSTRAINT distributors_pkey PRIMARY KEY USING INDEX dist_id_temp_idx;
This method is explicitly mentioned at the docs of ALTER TABLE ... ADD table_constraint_using_index.

Change Primary Key

I have a table in Oracle which has following schema:
City_ID Name State Country BuildTime Time
When I declared the table my primary key was both City_ID and the BuildTime, but now I want to change the primary key to three columns:
City_ID BuildTime Time
How can I change the primary key?
Assuming that your table name is city and your existing Primary Key is pk_city, you should be able to do the following:
ALTER TABLE city
DROP CONSTRAINT pk_city;
ALTER TABLE city
ADD CONSTRAINT pk_city PRIMARY KEY (city_id, buildtime, time);
Make sure that there are no records where time is NULL, otherwise you won't be able to re-create the constraint.
You will need to drop and re-create the primary key like this:
alter table my_table drop constraint my_pk;
alter table my_table add constraint my_pk primary key (city_id, buildtime, time);
However, if there are other tables with foreign keys that reference this primary key, then you will need to drop those first, do the above, and then re-create the foreign keys with the new column list.
An alternative syntax to drop the existing primary key (e.g. if you don't know the constraint name):
alter table my_table drop primary key;
Sometimes when we do these steps:
alter table my_table drop constraint my_pk;
alter table my_table add constraint my_pk primary key (city_id, buildtime, time);
The last statement fails with
ORA-00955 "name is already used by an existing object"
Oracle usually creates an unique index with the same name my_pk. In such a case you can drop the unique index or rename it based on whether the constraint is still relevant.
You can combine the dropping of primary key constraint and unique index into a single sql statement:
alter table my_table drop constraint my_pk drop index;
check this:
ORA-00955 "name is already used by an existing object"

Dropping then adding a constraint fails in oracle

I'm trying to move a primary key constraint to a different column in oracle. I tried this:
ALTER TABLE MY_TABLE
DROP CONSTRAINT c_name;
ALTER TABLE MY_TABLE
ADD CONSTRAINT c_name PRIMARY KEY
(
"COLUMN_NAME"
) ENABLE;
This fails on the add constraint with an error saying the the constraint already exists even though i just dropped it. Any ideas why this is happening
If the original constraint was a primary key constraint, Oracle creates an index to enforce the constraint. This index has the same name as the constraint (C_NAME in your example). You need to drop the index separately from the constraint. So you will need to do a :
ALTER TABLE <table1> DROP CONSTRAINT C_NAME;
DROP INDEX C_NAME;
ALTER TABLE <table1> ADD CONSTRAINT C_NAME PRIMARY KEY
( COLUMN_2 ) ENABLE;
The safest way is to first add a unique index. Try this:
create unique index new_pk on <tabname> (column_2);
Then drop the old PK:
alter table <tabname> drop primary key drop index;
(Optional) Rename the index:
alter index new_pk rename to c_name;
And then add the PK again indicating the index to be used:
alter table <tabname> add constraint c_name
primary key (column_2) using index c_name;
I don't know if this is a similar problem but, in DB2, you have to actually commit following the alter table statement. Otherwise it's still hanging around.