So when trying to add an autoincrement to a field it comes up with #1062 - Duplicate entry '1' for key 1 . I've tried removing the primary key and re-adding it and that works fine (which I assume wouldn't if there was duplicates?)
But when I try to add an autoincrement to the field it throws an error. It gives me a browse option which runs the following SQL:
SELECT *
FROM `myTbl`
WHERE CONCAT_WS( "-", 11 ) = "1"
ORDER BY 11
LIMIT 0 , 30
However this returns a empty result set.. suggesting there are no duplicates. So if there are no duplicates, how come i can't add an autoincrement?
Do you have any rows with value 0 or NULL for this column? ALTER TABLE can cause primary keys to be resequenced. In the case of a key of 0, MySQL will try to give it the value 1, which will fail if the key 1 already exists.
Try changing any 0 or NULL values in the column to something higher (and unused).
Michael Mior's answer works if you can change the data in the table. However, there is also a workaround that lets you keep the data intact (I've tested this on MySQL 5.5). Remember that having a zero value as a primary key in MySQL is not a recommended practice just for this reason. If you can get rid of the zero, then do it.
Disable automatic value generation when a zero is inserted:
SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO;
Add AUTO_INCREMENT to your column:
ALTER TABLE ... AUTO_INCREMENT;
Re-enable automatic value generation:
SET SQL_MODE='';
It should be obvious that inserting data to the table during this whole operation can not be allowed. Otherwise there will be unwanted zero values in the column.
SELECT * <<-- Select * is an anti-pattern
FROM myTbl
WHERE CONCAT_WS( "-", 11 ) = "1" <<-- You are not selecting a column
ORDER BY 11 <<-- This however does refer to a column.
LIMIT 30 OFFSET 0
rewrite the query to
SELECT field1, field2, field3, ...., field11
FROM myTbl
WHERE COALESCE(field1, field2, field3, field11) = '1'
ORDER BY field11
LIMIT 30 OFFSET 0
If you want to insert a row use code like this:
INSERT INTO table1 (/*do not list the PK!*/ field2, field3, field4)
VALUES ('a', 'test' ,'b' ,'example');
If you want to select all duplicate rows use:
SELECT id, count(*) as duplicate_count
FROM table1
GROUP BY id
HAVING duplicate_count > 1
You will need to update those id's that are listed as duplicate.
Another option is to add an extra column and drop the old PK.
ALTER TABLE table1 ADD COLUMN new_id unsigned integer not null auto_increment primary key;
ALTER TABLE table1 DROP COLUMN id;
ALTER TABLE table1 CHANGE COLUMN newid id;
Related
I've got the following table:
productId price
1 price_value1
2 price_value2
3 price_value3
I would like to insert a new product into the table and assign it a new productId. In this case its value equals to 4.
So I want my new table to look like so:
productId price
1 price_value1
2 price_value2
3 price_value3
4 price_value4
So as far as I understand, in order to do that I have to somehow retrieve the max value of productId and insert it using INSERT INTO mytable VALUES (productId + 1, price_value4).
But how do I find out the maximum value of productId?
I tried INSERT INTO mytable VALUES (SELECT MAX(productId) + 1 FROM mytable, price_value4) but it didn't work.
This should Work:
Select the max(productID) and price_value4 as a columns from mytable and insert the result.
INSERT INTO mytable (SELECT MAX(productId) + 1, 'price_value4' FROM mytable);
However, if you are not going to jump some number you can just add an auto increment id key to product_id and then you will have only to insert the price, the product ID will be incremented automatically..
This will do so :
ALTER TABLE mytable
MODIFY COLUMN `productId` INT(10) UNSIGNED PRIMARY KEY AUTO_INCREMENT;
you can change INT(10) with the INT(5) for example depanding on the size you want to give to your productId column
EDIT :
In return to the OP question in comments why his solution wouldn't work
Some suggetions says you have to make the SELECT statment in insert always between parenthesis
INSERT INTO mytable VALUES ( (SELECT MAX(ID)+1 FROM mytable) , price_value4)
.. In my Case it Return
(1093): You can't specify target table
'mytable' for update in FROM clause
AND HERE IS WHY (Quoting From the documentation)
When selecting from and inserting into the same table, MySQL creates
an internal temporary table to hold the rows from the SELECT and then
inserts those rows into the target table. However, you cannot use
INSERT INTO t ... SELECT ... FROM t when t is a TEMPORARY table,
because TEMPORARY tables cannot be referred to twice in the same
statement
BUT there is away to overcome by using a query instead of the table itself in the FROM, which has the effect of copying the requested table values instead of referencing the one that you are updating..
INSERT INTO mytable VALUES (
(SELECT MAX(ID)+1 FROM (SELECT * FROM mytable ) as mytmp ),
'price_value4');
OR (Quoting From the documentation)
To avoid ambiguous column reference problems when the SELECT and the
INSERT refer to the same table, provide a unique alias for each table
used in the SELECT part, and qualify column names in that part with
the appropriate alias.
INSERT INTO mytable Values ( (SELECT MAX(ID)+1 FROM mytable as mytmp) , 'price_value4')
This is a duplicate question. In order to take advantage of the auto-incrementing capability of the column, do not supply a value for that column when inserting rows.
A simple syntax to create table
CREATE TABLE Product (
productId MEDIUMINT NOT NULL AUTO_INCREMENT,
price INT NOT NULL,
PRIMARY KEY (productid)
);
While inserting supplied default or leave column as blank or supplied value as NULL. Take a look at below code snippet.
INSERT INTO Product (price) VALUES
('10'),('20'),('4'),
('30');
refer this link
I'm trying to update values already stored in a table, and I've implemented an auto-incrementing primary key column so that I can reference specific rows by number (as recommended here).
Using...
ALTER TABLE taxipassengers ADD COLUMN rid INT NOT NULL AUTO_INCREMENT PRIMARY KEY
The problem I'm running into though is that now I'm getting Column count doesn't match value count at row 1 when I insert the same data as before. It's like it wants me to give it a value for the PK. If I delete the column with the PK, the error goes away, and I'm back to square one.
Am I missing something?
EDIT: Here's the insert statement
INSERT INTO taxipassengers SELECT a.post_date, b.vendor_name, c.lastName, d.firstName, null as taxiGroup
FROM (select ID,post_date from wp_posts where post_type = 'shop_order') a,
(SELECT order_id,vendor_name FROM wp_wcpv_commissions) b,
(SELECT post_id,meta_value as lastName FROM wp_postmeta where meta_key ='_billing_last_name') c,
(SELECT post_id,meta_value as firstName FROM wp_postmeta WHERE meta_key ='_billing_first_name') d
WHERE a.ID = b.order_id and b.order_id=c.post_id and c.post_id = d.post_id;
Mind you, the insert statement worked before implementing the PK column, and it still works if I remove the PK column.
Possibly you are using this syntax to insert rows
INSERT INTO mytable VALUES (1, 'abc', 'def');
INSERT syntax from MySQL manual
The columns for which the statement provides values can be specified as follows:
If you do not specify a list of column names for INSERT ... VALUES or INSERT ... SELECT, values for every column in the table must be provided by the VALUES list or the SELECT statement. If you do not know the order of the columns in the table, use DESCRIBE tbl_name to find out.
You must add new column to your INSERT query. For autoincrement column NULL can be inserted to generate new value. And your column will be added last by default (if you don't use AFTER in ALTER TABLE).
To add a column at a specific position within a table row, use FIRST or AFTER col_name. The default is to add the column last. You can also use FIRST and AFTER in CHANGE or MODIFY operations to reorder columns within a table.
So, now your INSERT must look like this:
INSERT INTO mytable VALUES (1, 'abc', 'def', NULL); -- use NULL for autoincrement
INSERT INTO mytable (col1, col2, col3) VALUES (1, 'abc', 'def'); -- or add column names
First check if your database allows mutable PK, or prefers stable PK .
Please read through below articles, I am sure you will get what's going wrong.
http://rogersaccessblog.blogspot.in/2008/12/what-is-primary-key.html
First, the value in the primary key cannot be duplicated
Can we update primary key values of a table?
I have a table with primary key (its name is "id") defined as auto_increment. I use NULL in INSERT statements to "fill" the id value. It works, of course. However now I need to "move" an existing record to a new primary key value (the next available, the value is not so much important, but it must be a new one, and the last one if ordered by id). How can I do it in an "elegant" way? Since the "use NULL at INSERT" does not work too much with UPDATE:
update idtest set id=NULL where id=1;
This simply makes the id of the record zero. I would expect to do the same thing as with INSERT, but it seems my idea was incorrect.
Of course I can use "INSERT ... SELECT" statement, then a DELETE on the old one, or I can use something like MAX(id) + 1 to UPDATE the id of the old record in one step, etc, but I am curious if there is a finer solution.
Also, the MAX(id) solution doesn't seem to work either by the way:
mysql> update idtest set id=max(id)+1 where id=3;
ERROR 1111 (HY000): Invalid use of group function
mysql> update idtest set id=(select max(id)+1 from idtest) where id=3;
ERROR 1093 (HY000): You can't specify target table 'idtest' for update in FROM clause
This is the way I believe:
UPDATE users SET id = (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'
AND TABLE_NAME = 'users') WHERE id = 2;
select * from users;
I used by own tables substitute yours.
test is database name, users is table name and id is AUTO_INCREMENT in my case.
EDIT: My Query above works perfect but its side effects are somewhat 'dangerous', upon next insert as AUTO_INCREMENT value will collide with this recently updated record so just next single insert will fail. To avoid that case I've modified above query to a transaction:
START transaction;
UPDATE users SET id = (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'
AND TABLE_NAME = 'users') WHERE id = 2;
#renew auto increment to avoid duplicate warning on next insert
INSERT IGNORE INTO users(username) values ('');
COMMIT
Hope this will help someone if not OP.
The way you are trying to update same table is wrong but you can use join on same table
update idtest t
join (select id +1 as id
from idtest order by id desc
limit 1) t1
set t.id=t1.id
where t.id=3;
or
update idtest t
join (select max(id) +1 as id
from idtest ) t1
set t.id=t1.id
where t.id=3;
You can use the REPLACE INTO clause to do the trick.
From the manual:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 13.2.5, "INSERT Syntax".
EDIT
My mistake (in the comments) that you have to have two unique constraint to achieve this:
When you use the auto_increment value to REPLACE the record, the record will be replaced with the give ID and will not change (however the AI value will increment).
You have to exclude the AI column from the query. You can do that if you have one more UQ constraint.
Check this SQLFiddle demo: http://sqlfiddle.com/#!2/1a702e
The first query will replace all the records (but the id's value will not change).
The second one will replace it too, and the new AI value will be used. (Please note, that the second query does not contain the id column, and there is a UQ constraint on the some column).
You can notice, that the second query uses higher AI values than it is excepted: this is because the first replace incremented the AI value.
If you do not have two unique keys (one for the AI and one for another columns), the REPLACE statement will work as a normal INSERT statement!
(Ofcourse you can change one of the UNIQUE KEYs with a PRIMARY KEY)
I have seen this issue around (See links at bottom) but I can't seem to figure out an answer. The problem is that I insert data on a table with an auto increment ID that is a primary key, and another field with a UNIQUE index to avoid duplicates. This works, but when that happens the ID is incremented, although no data has been stored.
Would it be better to remove the auto increment, and handle it myself, selecting the max(ID)?
At the moment I have tried several strategies to make it work as is, including INSERT IGNORE and INSERT ... ON DUPLICATE KEY UPDATE
My latest try was using the following query:
INSERT INTO
content(field1, field2)
SELECT(:field1, :field2) FROM DUAL
WHERE NOT EXISTS(
SELECT field1, field2
FROM content
WHERE field1 = :field1
)
Related
In MySQL, when there is a "duplicate entry" error, how do I prevent the primary key from auto incrementing?
SQL Server - How to insert a record and make sure it is unique
Thanks to this question I have been able to fix that error. The problem was that the SELECT(:field1, :field2) shouldn't have the parenthesis. So the query should be:
INSERT INTO
content(field1, field2)
SELECT :field1, :field2 FROM DUAL
WHERE NOT EXISTS(
SELECT field1, field2
FROM content
WHERE field1 = :field1
)
You could just do an ORDER BY :)
UPDATE 'table'
SET column_id = column_id+1
WHERE column_id > [point where you want a un-occupied key]
ORDER BY column_id DESC
mysql executes the where and order by first then your update
I would like to insert a new row into my table from the output of an aggregated query:
INSERT INTO table_name (id) SELECT MAX(id) + 1 FROM table_name;
but it fails with the following error:
ERROR 1339 (20000): Case not found for CASE statement
If I add the + 1 part to the aggregate function like this:
INSERT INTO table_name (id) SELECT MAX(id + 1) FROM table_name;
it produces the same error. If I remove the + 1 part, it will of course fail because the id is the primary key:
ERROR 1062 (23000): Duplicate entry '48' for key 'PRIMARY'
How can I achieve this in MySQL 5.5.29-0ubuntu0.12.10.1 without modifying the table structure?
UPDATE
This is probably because of a missing not null field in the original table, I'll post the solution here if I'll find it out tomorrow.
since you want to increment the last id by one, why don't you use AUTO_INCREMENT column for column ID.
CREATE TABLE tableName
(
ID INT AUTO_INCREMENT PRIMARY KEY,
....
)
Although the error said differently the cause of the problem was a missing not NULL field in the insert.
Filling out every field resulted a correct MAX(id) + 1 query.