Alter table error code 1834 - mysql

I am trying to alter a table as follows. But I am receiving an Error Code:
1834 Cannot delete rows from table which is parent in a foreign key constraint 'downloads_ibfk' of table downloads.
ALTER TABLE users
MODIFY first_name VARCHAR(20) NOT NULL UNIQUE;

You obviously have a foreign key constraint blocking the ALTER TABLE.
You can deactivate the FK check by preceding your query with
SET FOREIGN_KEY_CHECKS=0;
But remember to set it back to 1 after the query.
SET FOREIGN_KEY_CHECKS=1;

By deactivating FOREIGN_KEY_CHECKS, as suggested by #zonzon, you may get some unexpected results.
The error could also be due to the initial column schema and an incomplete ALTER TABLE query.
If you have the same issue, here is how I fixed it:
My initial column schema was:
# users.login | varchar(128) | collate utf8_bin | not null;
ALTER TABLE users ADD login varchar(128) COLLATE 'utf8_bin' NOT NULL;
What I was trying to execute, without success:
ALTER TABLE users CHANGE COLUMN login login varchar(128) NULL DEFAULT NULL;
# Cannot delete rows from table which is parent in a foreign key constraint '%s' of table '%s'
What I have executed with success:
ALTER TABLE Internaute CHANGE COLUMN login login varchar(128) COLLATE 'utf8_bin' NULL DEFAULT NULL;
# This query is more complete, I indicated the column's `COLLATE`. Otherwise the default collation is applied.
Why my first query didn't work?
In this query, I was also changing the collation (to the default one), so I think, my ALTER TABLE operation used the COPY algorithm to process my request.
Using this algorithm, a deletion is performed at some point. This is why you could get the error Cannot delete rows from table ... in an ALTER TABLE operation.
By default, the ALTER TABLE operations use other algorithms (INSTANT or INPLACE) that prevent the delete step. But, an ALTER TABLE operation that changes a column's collation is not supported by these other algorithms.
You can get more information here about the ALTER TABLE algorithms and their supported operations.

Related

How to drop auto_increment from a mysql table

this should be a very easy issue but I couldn't find a solution that works.
I migrate the date from Oracle to MYSQL and during the process, all primary keys were set to auto_increment.
However, there are a lot of identified relationships (parent PK is the same of children).
So the correct way to do the transaction is to insert into the parent tables, get result.insertId from this interaction and then insert the same value in the child table. I know that I could simply ignore the auto_increment sending the id in the insert command but I didn't like to just let this go.
As the solutions I read about say that I need to change the column to the exactly the same specification but auto_increment, I run the following SQL:
alter table added_object modify column id_interaction_object int(11) not null;
.. And I get the following message:
ERROR 1833 (HY000): Cannot change column 'id_interaction_object': used
in a foreign key constraint 'FK__METRIC__ADDED_OBJECT' of table
'metric'
Any tips?
Thanks
You need to disable foreign key checks:
SET FOREIGN_KEY_CHECKS=0;
alter table added_object modify column id_interaction_object int(11) not null;
SET FOREIGN_KEY_CHECKS=1;

Why is this foreign key constraint not working?

I'm creating a new table who will have relationships with an existing table. The new table has a column user_id which references a userid column on another table (the ID of a user in the users table).
I have the following table:
CREATE TABLE `ads` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-- Other columns...
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
ENGINE = InnoDB;
Adding a referencing column
ALTER TABLE `ads` ADD `user_id` INT(11) NOT NULL
Which references the following column
CREATE TABLE users
(
userid INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
-- Other irrelevant fields...
);
And finally my key definition:
ALTER TABLE `ads` ADD CONSTRAINT ads_user_id_foreign FOREIGN KEY (`user_id`) REFERENCES `users` (`userid`)
But for some reason I still get an error:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `ads` add constraint ads_user_id_foreign foreign key (`user_id`) references `users` (`userid`))
Note: I don't believe it's of much relevance, but I'm using Laravel's query builder to create the new table. I'm getting these queries from PHPStorm's Copy DDL feature to show you the equivalent "vanilla MySQL query".
Okay, so I figured it out. In my case, I also needed to change the engine, charset, and collation of the users table. IT was set to MyISAM, latin1, and latin1_swedish_ci, respectively.
I did say I was using Laravel, so here are the statements I used to fix that:
DB::statement('ALTER TABLE users CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci');
DB::statement('ALTER TABLE users ENGINE=InnoDB;');
I'll try to leave a generic answer here for those who find this post in the future.
Things to check when foreign keys aren't working:
1. Make sure that the columns are setup identically
I use an IDE (PHPStorm) that allows me to get some DDL from existing tables. I paste that somewhere and find the columns in question to see if they're defined correctly.
2. Check table status for inconsistencies
You can check all tables' statuses with SHOW TABLE STATUS. You'll get a result that looks like this (obviously this depends on your IDE):
Make sure that engine and collation match in both tables
• If you notice that your engine is wrong (it should be InnoDB), you can fix it with
ALTER TABLE <table_name> ENGINE=InnoDB;
• If you notice that your collation is wrong, you can fix it with
alter table <table_name> convert to character set <CHARSET> collate <COLLATION>;
(where a charset might be utf8 and a collation might be utf8_unicode_ci)

MySQL - Duplicate entry error when trying to add new column

I have a MySQL database with a table that has 2 million rows using innodb engine. I want to add another column, but I keep getting the following error:
Error 1062: Duplicate entry '' for key 'PRIMARY' SQL Statement: ALTER TABLE `mydb`.`table` ADD COLUMN `country` VARCHAR(35) NULL DEFAULT NULL AFTER `email`
How can I add the column without getting this error?
EDIT: Table definition
id int(11) NOT NULL AUTO_INCREMENT,
user_id varchar(45) NOT NULL,
first_name varchar(150) DEFAULT NULL,
last_name varchar(150) DEFAULT NULL,
gender varchar(10) DEFAULT NULL,
email varchar(100) DEFAULT NULL,
created_at bigint(20) DEFAULT NULL,
updated_at bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`,`user_id`),
UNIQUE KEY `user_id_UNIQUE` (`user_id`),
KEY `first_name` (`first_name`),
KEY `last_name` (`last_name`)
EDIT #2: SHOW INDEXES output
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Index_type
table 0 PRIMARY 1 id A 3516446 BTREE
table 0 PRIMARY 2 user_id A 3516446 BTREE
table 0 user_id_UNIQUE 1 user_id A 3516446 BTREE
table 1 first_name 1 first_name A 390716 BTREE
table 1 last_name 1 last_name A 439555 BTREE
it solution will lock table on write, but often suitable for solving the problem if table is not very big
LOCK TABLES my_table WRITE;
ALTER TABLE my_table
ADD COLUMN `ts` DATETIME NULL AFTER `id`;
UNLOCK TABLES;
As described in the documentation, When running an online ALTER TABLE operation:
... the thread that runs the
ALTER TABLE operation will apply an “online log” of DML operations
that were run concurrently on the same table from other connection
threads. When the DML operations are applied, it is possible to
encounter a duplicate key entry error (ERROR 1062 (23000): Duplicate
entry), even if the duplicate entry is only temporary and would be
reverted by a later entry in the “online log”. This is similar to the
idea of a foreign key constraint check in InnoDB in which constraints
must hold during a transaction.
If it's not something a program needs to do (altering tables dynamically), then just wait a moment and then try again! It worked for me. :) I guess there are some InnoDB-specific processes/states (maybe still processing another ALTER queried just a moment ago?), during which the ALTER command would fail, and you just need to catch a moment when it succeeds.
I've runned the same code and it works fine.
http://sqlfiddle.com/#!2/1937e
As a solution, I would try to recreate the table , copy the data into it, and then switch tables using rename.
If that doesn't work then it's clear that it's a bug with your current mysql configuration, and we'll need more details to figure it out or at least reproduce it (mysql version, mysql config, database settings, the actual data, etc.).
If it works then it probably was a problem with tables or indexes and here are a few things you can check (you can also start with these if you don't wish to recreate the table):
Check that you don't have any triggers that are causing other inserts
Check that you are just creating a column and not adding other keys/indexes
Check that the auto_increment value is not overflowing (for int it's over 2,000,000,000)
If none of the above, then you probably have a some corrupt data, or you missed to share some details.
I guess there are some other ALTERs or INSERTs which are still processing.
First, to check the processing triggers with this following queries:
SHOW FULL PROCESSLIST;
SELECT * FROM information_schema.INNODB_TRX\G
Then, kill the locked query by trx_mysql_thread_id: 132092 for example:
KILL 132092;
Finally, here‘s a solution - OnlineSchemaChange (OSC). It built by Facebook supports online alter MySQL table schema with minimal impact.
use change column
ALTER TABLE database.table_name
CHANGE COLUMN id id INT(11) NOT NULL AUTO_INCREMENT ,
ADD PRIMARY KEY (id);
Use percona toolkit to change db scheme without needing to lock tables: https://www.percona.com/doc/percona-toolkit/3.0/pt-online-schema-change.html
This allows to continue updating db while scheme change is being applied. This especially useful for large dbs where updating scheme can take a while.

InnoDB mySQL unable to set "ON DELETE SET DEFAULT'. How to set?

I am trying to create a table named EMPLOYEE. When I use the following statements without "ON DELETE SET DEFAULT" it is working.
Here is the Error I get with "ON DELETE SET DEFAULT":
ERROR 1005 (HY000): Can't create table 'COMPANY.EMPLOYEE' (errno: 150)
Here is the DDL
CREATE TABLE EMPLOYEE (
Fname VARCHAR(15) NOT NULL,
Minit CHAR, Lname VARCHAR(15) NOT NULL,
Ssn CHAR(9) NOT NULL DEFAULT '123456789',
Bdate DATE, ADDRESS VARCHAR(30),
Sex CHAR, Salary DECIMAL(10,2),
Super_Ssn CHAR(9) NOT NULL DEFAULT '123456789',
Dno INT NOT NULL DEFAULT -99,
PRIMARY KEY (Ssn),
FOREIGN KEY (Super_Ssn) REFERENCES COMPANY.EMPLOYEE(Ssn)
ON DELETE SET DEFAULT
ON UPDATE CASCADE )ENGINE=InnoDB;
Please help me!!! and Thanks in advance :)
You can't use ON DELETE SET DEFAULT or ON UPDATE SET DEFAULT with InnoDB
InnoDB and FOREIGN KEY Constraints
While SET DEFAULT is allowed by the MySQL Server, it is rejected as
invalid by InnoDB. CREATE TABLE and ALTER TABLE statements using this
clause are not allowed for InnoDB tables.
You may try ON DELETE SET NULL if it fits your needs
If ON UPDATE CASCADE or ON UPDATE SET NULL recurses to update the same
table it has previously updated during the cascade, it acts like
RESTRICT. This means that you cannot use self-referential ON UPDATE
CASCADE or ON UPDATE SET NULL operations. This is to prevent infinite
loops resulting from cascaded updates. A self-referential ON DELETE
SET NULL, on the other hand, is possible, as is a self-referential ON
DELETE CASCADE. Cascading operations may not be nested more than 15
levels deep
Here is SQLFiddle demo
just use SET NULL rule and define trigger which will try to set to default value with exception handler if your default value has been deleted from master table
You delete your parent table, which triggers the set default in the
child. The DB tries to set the child records to their default 0. But
there's no 0 record in the parent table, triggering the foreign key
violation.
Check out the MySQL manual about foreign key constrains:
If you re-create a table that was dropped, it must have a definition
that conforms to the foreign key constraints referencing it. It must
have the right column names and types, and it must have indexes on the
referenced keys, as stated earlier. If these are not satisfied, MySQL
returns error number 1005 and refers to error 150 in the error
message.
A few ideas:
Better drop the tables and create it new with a well formed syntax.
Make sure to add ENGINE=InnoDB; to your CREATE TABLE - command.
Make sure InnoDB is enabled on your MySQL server. To verify this, try this command: SHOW VARIABLES LIKE 'have_innodb'; - if it returns a YES, then InnoDB is enabled.
Check your command for upper- and lowercases in table- and fieldnames.
Check this not only one the table you want to create, but also on the tables the foreign keys are referring to.
Make sure your referred tables are properly indexed.
"When creating a foreign key constraint, MySQL requires a usable index on both the referencing table and also on the referenced table. The index on the referencing table is created automatically if one doesn't exist, but the one on the referenced table needs to be created manually (Source). Yours appears to be missing."
See MySQL Foreign Key Error 1005 errno 150

How do I drop 'NOT NULL' from a column in MySQL?

A show create table command shows the following:
'columnA' varchar(6) NOT NULL DEFAULT '';
How do I modify that column so that the not null is removed?
I need it to be:
'columnA' varchar(6) DEFAULT NULL;
I thought the following would work, but it has no effect:
ALTER TABLE tbl_name MODIFY columnA varchar(6) DEFAULT NULL;
Try this instead:
ALTER TABLE tbl_name MODIFY columnA varchar(6) NULL DEFAULT NULL;
Normally, Eric's answer should work:
ALTER TABLE tbl_name MODIFY columnA varchar(6) NULL DEFAULT NULL;
(Although the 'NULL DEFAULT NULL' part is optional).
But like you, I had a case that just returned OK without doing anything. In my case it appears to be due to the fact that my key was part of the primary key. So I had to do the following:
ALTER TABLE tbl_name DROP PRIMARY KEY;
ALTER TABLE tbl_name MODIFY columnA varchar(6);
ALTER TABLE tbl_name ADD PRIMARY KEY (columnA);
with that last query specifying whatever your primary key actually is.
Also, in case anyone thinks that is too verbose, the following combined query does NOT work, even though it should be identical:
ALTER TABLE tbl_name DROP PRIMARY KEY, MODIFY columnA varchar(6), ADD PRIMARY KEY (columnA);
I assume that mysql rewrites that last query into a different order so that the primary key still exists when the modify is performed, hence the need to break it out into three statements.
FYI, this is on mysql 5.1.47 but I haven't yet found any documentation indicating why this happens so I don't know what versions are affected.
Make the change (locally) in phpMyAdmin. It will show the query it used for the change. Execute this query in production and you're done.
You can use this strategy in any GUI tool to see the queries it performs. I personally use Sequel Pro (for Mac OS X) instead of phpMyAdmin.