mysql error 1062 during alter table modify column - mysql

I have a table that looks like this:
CREATE TABLE t1 (
id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY,
col1 VARCHAR(256),
UNIQUE INDEX t1_col1_index (col1)
)
I'm trying to modify the col1 type using the following query:
ALTER TABLE t1 MODIFY COLUMN col1 varchar(191) COLLATE utf8mb4_unicode_ci;
However, I run into this duplication error:
error: ("1062", "QMYSQL3: Unable to execute statement", "Duplicate entry '+123456789' for key 't1_col1_index'")
I initially thought it could be because two or more rows might 'contain' similar value for col1 and on changing varchar length the data gets truncated but then I found out that data truncation wouldn't even allow the query to go through. Any pointers on what could be causing this?
EDIT (Resolved): Truncation does happen when ##sql_mode is not set with STRICT_TRANS_TABLES. This was causing the error.

You are reducing the length of a varchar column that is controlled by a UNIQUE constraint.
This is risky business. Oversize data will be silently trimed (unless you have the ##sql_mode set to STRICT_TRANS_TABLES in which case an error will be raised). This probably generates duplicates, which cause the error to be raised by your UNIQUE constraint.
You can check the max length of the values in your column with :
SELECT MAX(CHAR_LENGTH(col1)) FROM t1:

I am not sure if this is work.
Try to check the table t1.
select count(1) from t1 where col1 = 123456789
Now if count is greater than one then try to remove the other one and leave only one record.
Then try to run your statement again.
Reminder:
Do back up first before removing.

Related

Equal to operation not working on a field with updated collation

I was trying to convert an existing varchar column with a unique index on it to a case sensitive column. So to do this, I updated the collation of the particular column.
Previous value: utf8mb4_unicode_ci
Current value: utf8mb4_bin
Now I have a row in my table TEST_TABLE with test_column value is abcd.
When I try to run a simple query like SELECT * FROM TEST_TABLE WHERE test_column = 'abcd'; it returns no result.
However when I try SELECT * FROM TEST_TABLE WHERE test_column LIKE 'abcd'; it returns the data correctly.
Also when I try SELECT * FROM TEST_TABLE WHERE BINARY test_column = 'abcd'; it returns the data correctly.
One more thing I tried was creating a duplicate of the table with column collation set as utf8mb4_bin while creating itself and then copy all data from original table. Then the query SELECT * FROM TEST_TABLE WHERE test_column = 'abcd'; is working alright.
So this seems to be a problem with BINARY conversion. Is there any solution to this or Am I doing something wrong ?
This seems to be an issue with MySQL. The steps I followed to resolve this is as follows:
dropped the unique index on the column
change the collation of the column
created the unique index again
Now it is working as expected. It seems MySQL didn't rebuild unique index when collation was changed. However the above steps solved my issue.
How did you change the collation? There are about 4 ways that you might think to do it. Most do something different.
Probably ALTER TABLE ... CONVERT TO COLLATION utf8mb4_bin was what you needed.
Why "bin"? You want to match case and accents? That is "abcd" != "Abcd"?

MySql Query to Update Auto increment Primary Key [duplicate]

How can I reset the AUTO_INCREMENT of a field?
I want it to start counting from 1 again.
You can reset the counter with:
ALTER TABLE tablename AUTO_INCREMENT = 1
For InnoDB you cannot set the auto_increment value lower or equal to the highest current index. (quote from ViralPatel):
Note that you cannot reset the counter to a value less than or equal
to any that have already been used. For MyISAM, if the value is less
than or equal to the maximum value currently in the AUTO_INCREMENT
column, the value is reset to the current maximum plus one. For
InnoDB, if the value is less than the current maximum value in the
column, no error occurs and the current sequence value is not changed.
See How can I reset an MySQL AutoIncrement using a MAX value from another table? on how to dynamically get an acceptable value.
SET #num := 0;
UPDATE your_table SET id = #num := (#num+1);
ALTER TABLE your_table AUTO_INCREMENT =1;
Simply like this:
ALTER TABLE tablename AUTO_INCREMENT = value;
Reference: 13.1.9 ALTER TABLE Statement
There is a very easy way with phpMyAdmin under the "operations" tab. In the table options you can set autoincrement to the number you want.
The best solution that worked for me:
ALTER TABLE my_table MODIFY COLUMN ID INT(10) UNSIGNED;
COMMIT;
ALTER TABLE my_table MODIFY COLUMN ID INT(10) UNSIGNED AUTO_INCREMENT;
COMMIT;
It's fast, works with InnoDB, and I don't need to know the current maximum value!
This way. the auto increment counter will reset and it will start automatically from the maximum value exists.
The highest rated answers to this question all recommend "ALTER yourtable AUTO_INCREMENT= value". However, this only works when value in the alter is greater than the current max value of the autoincrement column. According to the MySQL 8 documentation:
You cannot reset the counter to a value less than or equal to the value that is currently in use. For both InnoDB and MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is reset to the current maximum AUTO_INCREMENT column value plus one.
In essence, you can only alter AUTO_INCREMENT to increase the value of the autoincrement column, not reset it to 1, as the OP asks in the second part of the question. For options that actually allow you set the AUTO_INCREMENT downward from its current max, take a look at Reorder / reset auto increment primary key.
As of MySQL 5.6 you can use the simple ALTER TABLE with InnoDB:
ALTER TABLE tablename AUTO_INCREMENT = 1;
The documentation are updated to reflect this:
13.1.7 ALTER TABLE Statement
My testing also shows that the table is not copied. The value is simply changed.
Beware! TRUNCATE TABLE your_table will delete everything in your your_table.
You can also use the syntax TRUNCATE table like this:
TRUNCATE TABLE table_name
ALTER TABLE news_feed DROP id
ALTER TABLE news_feed ADD id BIGINT( 200 ) NOT NULL AUTO_INCREMENT FIRST ,ADD PRIMARY KEY (id)
I used this in some of my scripts. The id field is dropped and then added back with previous settings. All the existent fields within the database table are filled in with the new auto increment values. This should also work with InnoDB.
Note that all the fields within the table will be recounted and will have other ids!!!.
It is for an empty table:
ALTER TABLE `table_name` AUTO_INCREMENT = 1;
If you have data, but you want to tidy up it, I recommend to use this:
ALTER TABLE `table_name` DROP `auto_colmn`;
ALTER TABLE `table_name` ADD `auto_colmn` INT( {many you want} ) NOT NULL AUTO_INCREMENT FIRST ,ADD PRIMARY KEY (`auto_colmn`);
To update to the latest plus one id:
ALTER TABLE table_name AUTO_INCREMENT =
(SELECT (id+1) id FROM table_name order by id desc limit 1);
Edit:
SET #latestId = SELECT MAX(id) FROM table_name;
SET #nextId = #latestId + 1;
ALTER TABLE table_name AUTO_INCREMENT = #nextId;
Not tested please test before you run*
Warning: If your column has constraints or is connected as a foreign key to other tables this will have bad effects.
First, drop the column:
ALTER TABLE tbl_name DROP COLUMN column_id
Next, recreate the column and set it as FIRST (if you want it as the first column I assume):
ALTER TABLE tbl_access ADD COLUMN `access_id` int(10) NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST
As of MySQL 5.6 the approach below works faster due to online DDL (note algorithm=inplace):
alter table tablename auto_increment=1, algorithm=inplace;
SET #num := 0;
UPDATE your_table SET id = #num := (#num+1);
ALTER TABLE your_table AUTO_INCREMENT =1;
ALTER TABLE tablename AUTO_INCREMENT = 1
Try to run this query:
ALTER TABLE tablename AUTO_INCREMENT = value;
Or try this query for the reset auto increment
ALTER TABLE `tablename` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL;
And set auto increment and then run this query:
ALTER TABLE `tablename` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT;
The auto-increment counter for a table can be (re)set in two ways:
By executing a query, like others already explained:
ALTER TABLE <table_name> AUTO_INCREMENT=<table_id>;
Using Workbench or another visual database design tool. I am going to show in Workbench how it is done - but it shouldn't be much different in other tools as well. By right clicking over the desired table and choosing Alter table from the context menu. On the bottom you can see all the available options for altering a table. Choose Options and you will get this form:
Then just set the desired value in the field Auto increment as shown in the image. This will basically execute the query shown in the first option.
If you're using PHPStorm's database tool you have to enter this in the database console:
ALTER TABLE <table_name> AUTO_INCREMENT = 0;
I tried to alter the table and set auto_increment to 1 but it did not work. I resolved to delete the column name I was incrementing, then create a new column with your preferred name and set that new column to increment from the onset.
I googled and found this question, but the answer I am really looking for fulfils two criteria:
using purely MySQL queries
reset an existing table auto-increment to max(id) + 1
Since I couldn't find exactly what I want here, I have cobbled the answer from various answers and sharing it here.
Few things to note:
the table in question is InnoDB
the table uses the field id with type as int as primary key
the only way to do this purely in MySQL is to use stored procedure
my images below are using SequelPro as the GUI. You should be able to adapt it based on your preferred MySQL editor
I have tested this on MySQL Ver 14.14 Distrib 5.5.61, for debian-linux-gnu
Step 1: Create Stored Procedure
create a stored procedure like this:
DELIMITER //
CREATE PROCEDURE reset_autoincrement(IN tablename varchar(200))
BEGIN
SET #get_next_inc = CONCAT('SELECT #next_inc := max(id) + 1 FROM ',tablename,';');
PREPARE stmt FROM #get_next_inc;
EXECUTE stmt;
SELECT #next_inc AS result;
DEALLOCATE PREPARE stmt;
set #alter_statement = concat('ALTER TABLE ', tablename, ' AUTO_INCREMENT = ', #next_inc, ';');
PREPARE stmt FROM #alter_statement;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
Then run it.
Before run, it looks like this when you look under Stored Procedures in your database.
When I run, I simply select the stored procedure and press Run Selection
Note: the delimiters part are crucial. Hence if you copy and paste from the top selected answers in this question, they tend not to work for this reason.
After I run, I should see the stored procedure
If you need to change the stored procedure, you need to delete the stored procedure, then select to run again.
Step 2: Call the stored procedure
This time you can simply use normal MySQL queries.
call reset_autoincrement('products');
Originally from my own SQL queries notes in https://simkimsia.com/reset-mysql-autoincrement-to-max-id-plus-1/ and adapted for Stack Overflow.
delete from url_rewrite where 1=1;
ALTER TABLE url_rewrite AUTO_INCREMENT = 1;
and then reindex
ALTER TABLE `table_name` DROP `id`;
ALTER TABLE `table_name` ADD `id` INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`) ;
Shortly,First we deleted id column then added it with primary key id again...
The best way is remove the field with AI and add it again with AI. It works for all tables.
You need to follow the advice from Miles M's comment and here is some PHP code that fixes the range in MySQL. Also you need to open up the my.ini file (MySQL) and change max_execution_time=60 to max_execution_time=6000; for large databases.
Don’t use "ALTER TABLE tablename AUTO_INCREMENT = 1". It will delete everything in your database.
$con = mysqli_connect($dbhost, $dbuser, $dbpass, $database);
$res = mysqli_query($con, "select * FROM data WHERE id LIKE id ORDER BY id ASC");
$count = 0;
while ($row = mysqli_fetch_array($res)){
$count++;
mysqli_query($con, "UPDATE data SET id='".$count."' WHERE id='".$row['id']."'");
}
echo 'Done reseting id';
mysqli_close($con);
I suggest you to go to Query Browser and do the following:
Go to schemata and find the table you want to alter.
Right click and select copy create statement.
Open a result tab and paste the create statement their.
Go to the last line of the create statement and look for the Auto_Increment=N,
(Where N is a current number for auto_increment field.)
Replace N with 1.
Press Ctrl + Enter.
Auto_increment should reset to one once you enter a new row in the table.
I don't know what will happen if you try to add a row where an auto_increment field value already exist.

MySQL: unexpected SELECT result after INSERT into table with autoincrement column

I'm seeing a weird behavior when I INSERT some data into a table and then run a SELECT query on the same table. This table has an auto-increment primary key (uid), and this problem occurs when I try to then select results where 'uid IS NULL'.
I've golfed this down to the following SQL commands:
DROP TABLE IF EXISTS test_users;
CREATE TABLE test_users (uid INTEGER PRIMARY KEY AUTO_INCREMENT, name varchar(20) NOT NULL);
INSERT INTO test_users(name) values('foo');
SELECT uid FROM test_users WHERE uid IS NULL;
SELECT uid FROM test_users WHERE uid IS NULL; -- no output from this query
I'd expect SELECT uid FROM test_users WHERE uid IS NULL to never return anything, but it does, sometimes. Here's what I've found:
Version of MySQL/MariaDB seems to matter. The machine having this problem is running MySQL 5.1.73 (CentOS 6.5, both 32-bit and 64-bit). My other machine running 5.5.37-MariaDB (Fedora 19, 64-bit). Both running default configs, aside from being configured to use MyISAM tables.
Only the first SELECT query after the INSERT is affected.
If I specify a value for uid rather than let it auto-increment, then it's fine.
If I disconnect and reconnect between the INSERT and SELECT, then I get the expected no results. This is easiest to see in something like Perl where I manage the connection object. I have a test script demonstrating this at https://gist.github.com/avuserow/1c20cc03c007eda43c82
This behavior is by design.
It's evidently equivalent to SELECT * FROM t1 WHERE id = LAST_INSERT_ID(); which would also work only from the connection where you just did the insert, exactly as you described.
It's apparently a workaround that you can use in some environments that make it difficult to fetch the last inserted (by your connection) row's auto-increment value in a more conventional way.
To be precise, it's actually the auto_increment value assigned to the first row inserted by your connection's last insert statement. That's the same thing when you only inserted one row, but it's not the same thing when you insert multiple rows with a single insert statement.
http://dev.mysql.com/doc/connector-odbc/en/connector-odbc-usagenotes-functionality-last-insert-id.html

unexpected error 1054 in sql

After table setup, I suddenly remember to update it by adding one column and assign all the same value to that column. So I wrote the queries on Workbench like this
ALTER TABLE sthebc3_cle ADD COLUMN Species char(30) AFTER Genome_ACC;
SET SQL_SAFE_UPDATES=0;
UPDATE cle.sthebc3_cle
SET Species='StHe';
But it reported error like
error 1054: unknown column "Species" in "field list
I checked table after ALTER, The new column "Species" was indeed added to the column and values are NULL.
How could be the error reported?
You need to make sure that the current session is the database you want. There is always a selected database in MySQL.
If you want to be 100% sure which database you are using you Always put nameofthedatabase.tablename,
For the table
ALTER TABLE cle.sthebc3_cle ADD COLUMN Species char(30) AFTER Genome_ACC;
SET SQL_SAFE_UPDATES=0;
UPDATE cle.sthebc3_cle
SET Species='StHe';
For you view, try this
USE cle;
CREATE VIEW all_cle AS
(SELECT Species, Genome_ACC, CLE_start, CLE_end, CLE_domain
FROM nameofdatabase.cowpea_cle)
UNION
(SELECT Species, Genome_ACC, CLE_start, CLE_end, CLE_domain
FROM nameofdatabase.sthebc3_cle);

Why does this table name require back-ticks?

I am seeing a curious name dependency in the following MySQL table definition. When I code the table as shown, it seems to break MySQL. When I perform "select * from dictionary_pair_join" from MySQLQueryBrowser, the status bar says "No resultset returned" -- no column names and no errors. When I insert a row into the table, the status bar says "1 row affected by the last command, no resultset returned", and subsequent selects give the same "No resultset returned" response.
When I enclose the tablename in backticks in the "select" statement, all works fine. Surely there are no mysql entities named "dictionary_pair_join"!
Here is the table definition:
DROP TABLE IF EXISTS dictionary_pair_join;
CREATE TABLE dictionary_pair_join (
version_id int(11) UNSIGNED NOT NULL default '0',
pair_id int(11) UNSIGNED default NULL,
KEY (version_id),
KEY (pair_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Here is the broken select statement:
select * from dictionary_pair_join;
Here is its working counterpart:
select * from `dictionary_pair_join`;
Why are backticks required in the select statement?
Update: This also fails in the Python mysqldb interface, which is why I started looking at it. I can put the backticks into my Python "select" generators, but I was hoping this was some stupid and easily-changed nit. I suppose I can also find a different name.
I've uprated the comments from Quassnoi and Software Guy, together they've persuaded me that it's just a bug in mysql/mysqldb/mysqlquerybrowser.
I changed the table name (to "dictionary_pair_cons") and the problem went away, in both the query browser and mysqldb.