INSERT ... ON DUPLICATE KEY (do nothing) - mysql

I have a table with a unique key for two columns:
CREATE TABLE `xpo`.`user_permanent_gift` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`fb_user_id` INT UNSIGNED NOT NULL ,
`gift_id` INT UNSIGNED NOT NULL ,
`purchase_timestamp` TIMESTAMP NULL DEFAULT now() ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `user_gift_UNIQUE` (`fb_user_id` ASC, `gift_id` ASC) );
I want to insert a row into that table, but if the key exists, to do nothing! I don't want an error to be generated because the keys exist.
I know that there is the following syntax:
INSERT ... ON DUPLICATE KEY UPDATE ...
but is there something like:
INSERT ... ON DUPLICATE KEY DO NOTHING
?

Yes, use INSERT ... ON DUPLICATE KEY UPDATE id=id (it won't trigger row update even though id is assigned to itself).
If you don't care about errors (conversion errors, foreign key errors) and autoincrement field exhaustion (it's incremented even if the row is not inserted due to duplicate key), then use INSERT IGNORE like this:
INSERT IGNORE INTO <table_name> (...) VALUES (...)

HOW TO IMPLEMENT 'insert if not exist'?
1. REPLACE INTO
pros:
simple.
cons:
too slow.
auto-increment key will CHANGE(increase by 1) if there is entry matches unique key or primary key, because it deletes the old entry then insert new one.
2. INSERT IGNORE
pros:
simple.
cons:
auto-increment key will not change if there is entry matches unique key or primary key but auto-increment index will increase by 1
some other errors/warnings will be ignored such as data conversion error.
3. INSERT ... ON DUPLICATE KEY UPDATE
pros:
you can easily implement 'save or update' function with this
cons:
looks relatively complex if you just want to insert not update.
auto-increment key will not change if there is entry matches unique key or primary key but auto-increment index will increase by 1
4. Any way to stop auto-increment key increasing if there is entry matches unique key or primary key?
As mentioned in the comment below by #toien: "auto-increment column will be effected depends on innodb_autoinc_lock_mode config after version 5.1" if you are using innodb as your engine, but this also effects concurrency, so it needs to be well considered before used. So far I'm not seeing any better solution.

Use ON DUPLICATE KEY UPDATE ...,
Negative : because the UPDATE uses resources for the second action.
Use INSERT IGNORE ...,
Negative : MySQL will not show any errors if something goes wrong, so you cannot handle the errors. Use it only if you don’t care about the query.

Related

ON DUPLICATE KEY UPDATE only for primary keys?

Is there a way to restrict "ON DUPLICAYE KEY UPDATE" to only trigger if the duplicate key is the PRIMARY KEY of the table? (and not if the conflict is generated by a UNIQUE KEY)
For example in the following table:
CREATE TABLE users (
id INT(16) UNSIGNED AUTO_INCREMENT,
username VARCHAR(255) NOT NULL UNIQUE,
PRIMARY KEY (id),
UNIQUE (username)
);
I would like to trigger the update only if the id column generate the conflict, and throw an error as usual in case the conflict happened because of the unique key username.
Edit:
I'm working on a very simple PHP framework. Previously I had a single method save() that discriminated between INSERT and UPDATE based on the presence of the id property on the object on which it was called.
Now I rewrote this method using the INSERT INTO ... ON DUPLICATE KEY UPDATE query, but when I try to insert (for example) a user with an already existing username value, it updates that user instead of throwing an error.
I know this is the correct behaviour, I just wanted to know if there's a way to achieve the same result only on the PRIMARY KEY.
on duplicate key triggers for both primary keys and unique keys.
In your case, the primary key is an auto-incremented column, so you should not be inserting a value. Period.
Hence, you can get the behavior you want by simply not including the on duplicate key clause and leaving out the id from the insert.

How to don´t repeat values stored in database

I´m creating a database addrees and I want to know what I need to set in Mysql to don´t store repeat values?
Like
Addrees 1 ("teste",1,new york,eua);
Addrees 2 ("teste",1,new york,eua);
If this happen my database will not store.
So what I need to do?
To alter an already existing table, run this MySQL command:
alter table yourtablename add unique index(firstcolumn, secondcolumn, thirdcolumn, fourthcolumn);
That'll add the unique constraint to the specified columns. Here's how to specify such a constraint in the CREATE TABLE.
CREATE TABLE buyers (
buyer_id INT UNSIGNED NOT NULL,
first_name CHAR(19) NOT NULL,
last_name CHAR(19) NOT NULL,
age SMALLINT NOT NULL,
post_code SMALLINT NOT NULL,
UNIQUE idx_flname_age (first_name,last_name,age)
);
The primary key constraint will do this too, as mentioned by #Ajeesh
EDIT:
As per the suggestion in the comment, if you want to avoid errors generated by this unique constraint, you have three good options:
INSERT IGNORE
and
INSERT...ON DUPLICATE KEY UPDATE
and
REPLACE
INSERT IGNORE will not do anything if the insert violates the unique constraint, except log a harmless warning. The table will be left as is, and no error would be reported. This may be desireable in some cases.
More commonly is the second option, ON DUPLICATE KEY UPDATE, which says "Well, if the key already exists, then update that key's row like this instead."
And lastly is REPLACE, which will, if the key already exists, delete the row, then do an INSERT as normal. If the key did not exist previously, it will simply act as an INSERT.
This stack overflow answer has some examples.
"INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
You need to call these fields a UNIQUE_KEY
To make a column to be distinct you need to have Primary Key constraint/Unique Key. Primary key is used for relating one table with another and it's values should not be NULL. But in your case you can have Unique constraint to store only unique/distinct values.

Primary Key in SQL - Default value

I am working from this database, its one of the first I have tried building:
http://sqlfiddle.com/#!2/38ef8
When I try to add this line:
Insert Into country (name) values ('US');
It says Field 'id' doesn't have a default value. Am I doing my primary key correctly? I have seen people using "auto_incrment" on their primary key like this example:
http://sqlfiddle.com/#!2/c807a/2
Is that what I should be using?
If you didn't specify PRIMARY KEY column as AUTO_INCREMENT then you have to give values manually, for example:
INSERT INTO Country(id, name) values(1, 'US');
It's up to you wheter use AUTO_INCREMENT or not. There are many reasons to do it and many not to do it:
Pros and Cons of autoincrement keys on "every table"
Should each and every table have a primary key?
there are the properties of PRIMARY key
1 : cant be NULL
2 : cant be duplicate
now when you select AUTO_INCREMENT , every time you use the query
Insert Into country (name) values ('US');
it automatically generates a number incrementing the highest value existing in the table for the primary key column
but when you do not set the primary key as AUTO_INCREMENT ,
Insert Into country (name) values ('US');
this query will enter NULL values in every column for the row except the given column
in that case your PRIMARY_KEY also gets a null value
which clearly contradicts with the definition of PRIMARY_KEY .
that is why you get the error
I hope the explanation serves
If you have not set your primary key as auto increment, you will have to insert that manually in your queries.
The primary key should be set to AUTO_INCREMENT, if it is not so, you will have to set that manually.
Although you can still insert with specific values after setting the primary key to AUTO_INCREMENT provided the key is not already existing :D

sql: change primary key to another list of unique elements

i want to change the ids of a table to some other unique value.
This is a simplified example:
CREATE TABLE IF NOT EXISTS test (
id int(11) NOT NULL,
reverse_id int(11) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY reverse_id (reverse_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO test (id, reverse_id) VALUES ('1', '2'), ('2', '1');
UPDATE test SET id = reverse_id;
# Duplicate entry '2' for key 'PRIMARY'
I am looking for a command that checks only at the end of the UPDATE for the uniqueness of the id elements.
[I know that I can create a second row and change the status of this row to primary, then i can update the ids and reset the primary status, but i want to have one command, without adding or changing other rows, tables]
This is not possible with MySQL as far as I know.
It neither evaluates constraint on statement level (it does that on row level while processing) nor does it allow you to define them to be deferred (so the constraint would be evaluated at commit time).
The only option I can see if you want to "renumber" your primary key: drop the primary key, renumber the ids then re-create the primary key.
What if you create the table having reverse_id as its primary key? - that is unique in your definition so it is a valid candidate for primary key.
Primary keys are unique by definition - this constraint is stopping you from achieving what you want

What could cause duplicate ids on a auto increment primary key field (mysql)?

RESOLVED
From the developer: the problem was that a previous version of the code was still writing to the table which used manual ids instead of the auto increment. Note to self: always check for other possible locations where the table is written to.
We are getting duplicate keys in a table. They are not inserted at the same time (6 hours apart).
Table structure:
CREATE TABLE `table_1` (
`sales_id` int(10) unsigned NOT NULL auto_increment,
`sales_revisions_id` int(10) unsigned NOT NULL default '0',
`sales_name` varchar(50) default NULL,
`recycle_id` int(10) unsigned default NULL,
PRIMARY KEY (`sales_id`),
KEY `sales_revisions_id` (`sales_revisions_id`),
KEY `sales_id` (`sales_id`),
KEY `recycle_id` (`recycle_id`)
) ENGINE= MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=26759 ;
The insert:
insert into `table_1` ( `sales_name` ) VALUES ( "Blah Blah" )
We are running MySQL 5.0.20 with PHP5 and using mysql_insert_id() to retrieve the insert id immediately after the insert query.
I have had a few duplicate key error suddenly appear in MySql databases in the past even though the primary key is defined and auto_increment. Each and every time it has been because the table has become corrupted.
If it is corrupt performing a check tables should expose the problem. You can do this by running:
CHECK TABLE tbl_name
If it comes back as corrupt in anyway (Will usually say the size is bigger than it actually should be) then just run the following to repair it:
REPAIR TABLE tbl_name
Does the sales_id field have a primary (or unique) key? If not, then something else is probably making inserts or updates that is re-using existing numbers. And by "something else" I don't just mean code; it could be a human with access to the database doing it accidentally.
As the other said; with your example it's not possible.
It's unrelated to your question, but you don't have to make a separate KEY for the primary key column -- it's just adding an extra not-unique index to the table when you already have the unique (primary) key.
We are getting duplicate keys in a table.
Do you mean you are getting errors as you try to insert, or do you mean you have some values stored in the column more than once?
Auto-increment only kicks in when you omit the column from your INSERT, or try to insert NULL or zero. Otherwise, you can specify a value in an INSERT statement, over-riding the auto-increment mechanism. For example:
INSERT INTO table_1 (sales_id) VALUES (26759);
If the value you specify already exists in the table, you'll get an error.
Please post the results of this query:
SELECT `sales_id`, COUNT(*) AS `num`
FROM `table_1`
GROUP BY `sales_id`
HAVING `num` > 1
ORDER BY `num` DESC
If you have a unique key on other fields, that could be the problem.
If you have reached the highest value for your auto_increment column MySQL will keep trying to re-insert it. For example, if sales_id was a tinyint column, you would get duplicate key errors after you reached id 127.