Alter a live table to make a key non-unique - mysql

I saw some other questions related to this, but they were not MySQL.
The database is a live database, so I don't want to delete and recreate the table. I simply want to make a column no longer unique, which is less permissive in nature so it shouldn't cause any problems.

If your column was defined unique using UNIQUE clause, then use:
ALTER TABLE mytable DROP INDEX constraint_name
, or, if your constraint was implicitly named,
ALTER TABLE mytable DROP INDEX column_name
If it was defined unique using PRIMARY KEY clause, use:
ALTER TABLE mytable DROP PRIMARY KEY
Note, however, that if your table is InnoDB, dropping PRIMARY KEY will result in implicit recreation of your table and rebuilding all indexes, which will lock the table and may make it inaccessible for quite a long time.

These are instructions for phpmyadmin app (if you are using phpMyAdmin) ::
In a some cases, the developer (you) may not want to drop it but rather just modify the "uniqueness" to "not-unique".
Steps :
Go to the table in context, where you want to make the modification
Click on the "Structure" tab (mostly next to Browse)
Look for the "+Indexes" link, just under the columns. Yeah... now click it
Now you can see all the "Indexes" and you can now click on the "DROP" button or link to modify.
Answer was found here :
Source : https://forums.phpfreaks.com/topic/164827-phpmyadmin-how-to-make-not-unique/

Just DROP the unique index. There shouldn't be a problem with the fact that it is a live DB. If it is a really large table, you may block some queries temporarily while the index is removed. But that should only happen if you were adding an index.
ALTER TABLE table_name DROP INDEX index_name;

Although the accepted answer is incorrect (see comments), the suggested workaround is possible. But it is not correct too, at least for a "live table", as asked.
To lower the impact you should create a new index at first, and then delete the old one:
ALTER TABLE mytable ADD INDEX idx_new (column);
ALTER TABLE mytable DROP INDEX idx_old;
This avoids using the table (column) without index at all, which can be quite painful for clients and the MySQL itself.

MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast (MySQL Manual).
If the unique key that you want to make non-unique is used by a foreign key constraint, then you'll get an error when dropping it. You will have to recreate it on the same line:
alter table mytable drop KEY myUniqueKey, add key myUniqueKey (myColumn);

Related

Is it possible to alter a MySQL unique index to non-unique without recreating it

Is it possible to alter a MySQL unique index to non-unique without recreating it (DROP and CREATE)?
I'm using MySQL version 8.0.19.
No, in MySQL it is not possible to change the definition of an index without dropping it and recreating it. There is no ALTER INDEX statement.
Correction: You can rename an index without rebuilding it. You can make an index visible/invisible without rebuilding it.
If you've meant that you want to avoid dropping the unique index, then please read Bill Karwin's answer, which properly describes that it's not possible.
However, if you've meant that you want to recreate an index without dropping and recreating the table, then it's certainly possible, like:
DROP INDEX indexname on tablename;
and then
CREATE UNIQUE indexname ON tablename(columnname);

Clarification on MySQL 5.6 using IN PLACE alter table for adding/dropping the same index

From the docs:
An ALTER TABLE statement that contains DROP INDEX and ADD INDEX
clauses that both name the same index uses a table copy, not Fast
Index Creation.
This is a bit unclear to me. Is it talking about the NAME of the index? Can someone give an example of a query in which MySQL resorts to a table copy?
Indeed, it sounds like this line is about:
An (One, single) ALTER TABLE statement
that contains (both) a DROP INDEX and an ADD INDEX clause
and both clauses name the same index
and states that such a statement uses a table copy, not Fast Index Creation.
Such a statement would be:
ALTER TABLE MyTable
DROP INDEX MyIndex
ADD INDEX MyIndex(MyColumn);
The documentation is not really clear about the reason behind this, but I think the database want to create an index first and then drop the other index, so the statement by itself can more easily be made atomic. (Creating the index might fail.) If the index name itself is used in the storage as well, that order of first creating then dropping would give a conflict.
After all, fast index creation is a relatively new feature, so they might improve this over time.

Dropping/ Disabling index is better in sql server

I am writing this a follow up to Changing data type of column in SQL Server
My question earlier was if I need to remove all indexes and constraints and it was answered I do need to remove them.
So as I was surf internet on the topic I came across a few post saying its better to disable and enable an index, rather than removing and recreating them .
So which is better way of doing it? Does disabling of index allow you to change the data type of the column as well? What is the difference between both?
Statement with dropping and creating index
DROP INDEX UX_1_COMPUTATION ON dbo.Computation
ALTER TABLE dbo.Computation
ALTER COLUMN ComputationID NVARCHAR(25) not null
CREATE UNIQUE INDEX UX_1_COMPUTATION ON dbo.Computation (ComputationID);
Statement with disabling and enabling index
ALTER INDEX [UX_1_COMPUTATION ] ON dbo.Computation DISABLE
ALTER TABLE dbo.Computation
ALTER COLUMN ComputationID NVARCHAR(25) not null
ALTER INDEX [UX_1_COMPUTATION ] ON dbo.Computation REBUILD;
Does disabling of index allow you to change the data type of the column as well?
It is based on the index type you choosed. You cannot modify a column data type when an clustered index on the table is disabled. If your index is a non clustered index then you can.
What is the difference between both?
The biggest difference between disabling and dropping an index is whether the metadata and statistics are persisted. If disabled, they are. If dropped, they are not. Make sure you carefully weigh your options before performing either action, and always have a way to recreate the index available.
which is better way of doing it?
In your case I would suggest drop and recreate indexes.

Creating UNIQUE constraint on multiple columns in MySQL Workbench EER diagram

In MySQL Workbench's EER diagram, there is a checkbox to make each column in a table unique, not null, primary key etc.
However, I would like to have a UNIQUE constraint on multiple columns. Is it possible to add it in in MySQL Workbench's EER diagram?
EDIT: Ok, I realised the unique checkbox, creates a UNIQUE INDEX, and not a UNIQUE CONSTRAINT
In the Alter Table dialog of MySQL Workbench:
Go to Indexes tab.
Double-click on a blank row to create a new index.
Choose 'UNIQUE' as the index type.
Check the columns that you want to be unique together.
There's some discussion as to whether this is weird, since an index is not the same as a constraint. I certainly wouldn't have thought to look there. However, apparently the `unique index' enforces uniqueness in the same way as a unique constraint, and may improve performance. For example, if I try to insert a row that would break unique together after using this method, it throws an '1062 Duplicate entry' error.
it does not seem to be available : http://bugs.mysql.com/bug.php?id=48468 . it seems what you can is to create a multi column unique index on the indexes tab but for a multi column unique constraint, you need to run the creation command manually.
With latest MWB (I'm on 6.0.8), it is possible to create composite keys
If you wish to create a composite primary key you can select multiple columns and check the PK check box. However, there is an additional step that is required, you must click the Indexes tab, then in the Index Columns panel you must set the desired order of the primary keys.

mysql drop foreign key without table copy

I have an InnoDB table claims which has about 240 million rows. The table has a foreign key constraint: CONSTRAINT FK78744BD7307102A9 FOREIGN KEY (ID) REFERENCES claim_details (ID). I want to delete the table claim_details as quickly as possible.
Based on some experimentation it seems that if I use SET foreign_key_checks = 0; drop claim_details and then re-enable foreign keys, mysql will continue to enforce the constraint even though the table no longer exists. So, I believe I must drop the constraint from the table.
I have tried to use ALTER TABLE claims DROP FOREIGN KEY FK78744BD7307102A9 to drop the constraint and the query has been in a state of "copy to tmp table" for over 24 hours (on a machine with no other load). I don't understand why dropping a constraint requires making a copy of the table. Is there any way to prevent this?
mysql version 5.1.48.
Starting with MySQL 5.6, MySQL supports dropping of foreign keys in-place/without copying. Oracle calls this Online DDL.
This table lists all Online DDL operations and their runtime behavior.
From my experience, dropping foreign keys and the corresponding constraints on a 600GB table is almost instantaneous. With 5.5 it would probably have taken days.
The only disadvantage that I am aware of is, that 5.6 does not allow you to reclaim table space. I.e. if you are using innodb_file_per_table, that file will not shrink when you drop indices. Only the unused data in the file will grow. You can easily check using SHOW TABLE STATUS, and the Data_free column.
I think there is no a good way to drop that foreign key
http://dev.mysql.com/doc/refman/5.5/en/innodb-create-index-limitations.html
"MySQL 5.5 does not support efficient creation or dropping of FOREIGN KEY constraints. Therefore, if you use ALTER TABLE to add or remove a REFERENCES constraint, the child table is copied, rather than using Fast Index Creation." This probably refers also to older versions of mysql.
I think the best method will be to dump data from claims with mysqldump, recreate table without foreign key referencing to claim_details, disable key check with SET foreign_key_checks = 0; in case you have other foreign keys and import back data for claims. Just remember to make separate dumps for data and structure so you don't need to edit this huge file to remove foreign key from table creation syntax.