INSERT...ON DUPLICATE KEY UPDATE..... with two key fields - mysql

I have a table that has three fields
field_one
field_two
field_three
I'd like to do an insert/update, but instead of checking if one of the key fields already exists, I need to check if (field_one,field_two) combination is already in the database, if so, then update instead of inserting.

Create unique index your_index_name on yourtable (field_one,field_two) (see docs) and use INSERT...ON DUPLICATE KEY UPDATE.
MySQL will do the rest automagically.

Multiple ways to do this. Easiest is probably something like this:
Obtain the existing fields
Insert all your fields that are not in the existing fields
Update the rest

Sound to me like you can use REPLACE INTO or ON DUPLICATE KEY UPDATE as long as there is a unique constraint on the two fields.
MySql doesn't support the MERGE statement, so need either a unique constraint or some external code.

Related

What is the difference between “INSERT IGNORE” and “INSERT … ON DUPLICATE KEY UPDATE” in MySQL? [duplicate]

This question already has answers here:
"INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
(12 answers)
Closed last month.
What is the difference between INSERT IGNORE and INSERT…ON DUPLICATE KEY UPDATE. I would also like to know which one is preferred over the other. Can someone please help?
If you use INSERT IGNORE, then the row won't actually be inserted if it results in a duplicate key. But the statement won't generate an error. It generates a warning instead. These cases include:
•Inserting a duplicate key in columns with PRIMARY KEY or UNIQUE constraints.
•Inserting a NULL into a column with a NOT NULL constraint.
•Inserting a row to a partitioned table, but the values you insert don't map to a partition.
If you use REPLACE, MySQL actually does a DELETE followed by an INSERT internally, which has some unexpected side effects:
•A new auto-increment ID is allocated.
•Dependent rows with foreign keys may be deleted (if you use cascading foreign keys) or else prevent the REPLACE.
•Triggers that fire on DELETE are executed unnecessarily.
•Side effects are propagated to replication slaves too.
Both REPLACE and INSERT...ON DUPLICATE KEY UPDATE are non-standard, proprietary inventions specific to MySQL. ANSI SQL 2003 defines a MERGE statement that can solve the same need (and more), but MySQL does not support the MERGE statement.
If you try to avoid duplication violation, then the difference is: INSERT IGNORE does not allow to specify an action (to alter something in a row) if unique constraint violation occures whereas for INSERT...ON DUPLICATE KEY UPDATE some action specifying is compulsory. Of course, you can specify fake update in INSERT...ON DUPLICATE KEY UPDATE (for example, SET id=id, where id is primary/unique key) - in this case there is no difference.
INSERT IGNORE also may ignore some another ignorable errors, rather than INSERT...ON DUPLICATE KEY UPDATE.

Is merge statement available in MySQL

I have to use INSERT and UPDATE in single query. For that SQL having MERGE statement.
Is MERGE statement supported in MySQL. If supported, please provide sample.
MERGE is not supported by MySQL, However, there is other possible way of doing the same:
INSERT...ON DUPLICATE KEY UPDATE
If you specify the ON DUPLICATE KEY UPDATE option in the INSERT
statement and the new row causes a duplicate value in the UNIQUE or
PRIMARY KEY index, MySQL performs an update to the old row based on
the new values.

Unique VS INSERT IGNORE

As you know, unique columns only accept non-repetitive values. Now, I saw a keyword named IGNORE (It is used after INSERT statement).
Well, I read about INSERT IGNORE in the documentation and I figured out its job is exactly what unique does! So, when should I use IGNORE instead of unique column? When it is useful?
These two constructs are complimentary. A unique constraint makes sure a column cannot get repetitive values. The ignore keyword in an insert statement allows the insert statement to ignore any errors (such as unique constraint violations) when inserting new rows to a table.
Without the constraint, your insert statement would just create repetitive values in the table. Without the ignore keyword, attempting to insert such values would error out instead of just silently doing nothing.

mysql circular dependency in foreign key constraints

Given the schema:
What I need is having every user_identities.belongs_to reference an users.id.
At the same time, every users has a primary_identity as shown in the picture.
However when I try to add this reference with ON DELETE NO ACTION ON UPDATE NO ACTION, MySQL says
#1452 - Cannot add or update a child row: a foreign key constraint fails (yap.#sql-a3b_1bf, CONSTRAINT #sql-a3b_1bf_ibfk_1 FOREIGN KEY (belongs_to) REFERENCES users (id) ON DELETE NO ACTION ON UPDATE NO ACTION)
I suspect this is due to the circular dependency, but how could I solve it (and maintain referential integrity)?
The only way to solve this (at least with the limited capabilities of MySQL) to allow NULL values in both FK columns. Creating a new user with a primary identity would then look something like this:
insert into users (id, primary_identity)
values (1, null);
insert into identities (id, name, belongs_to)
values (1, 'foobar', 1);
update users
set primary_identity = 1
where id = 1;
commit;
The only drawback of this solution is that you cannot force that a user has a primary identity (because the column needs to be nullable).
Another option would be to change to a DBMS that supports deferred constraints, then you can just insert the two rows and the constraint will only be checked at commit time. Or use a DBMS where you can have a partial index, then you could use the solution with an is_primary column
I would not implement it this way.
Remove the field primary_identity from table users, and the add an additional field to table user_profiles called is_primary, and use this rather as the indicator of a primary profile
This will prevent having NULLs for FKs, but still does not enforce for primary profile to exists -- that has to be managed by application.
Note the alternate key (unique index) {UserID, ProfileID} on Profile table and matching FK on PrimaryProfile.
The problem seems to be that you are trying to keep the primary identity information in the user_identities table.
Instead, I suggest you put the primary user info (name/email) into the users table. Do not foreign key to the user_identities table.
Only foreign key from the user_identities table
All constraints will now work ok as they are only one way.
user_identities cannot be entered unless the primary user (in table users) is present. Similarly the primary user should not be deletable where there are existing child identities (in user_identities).
You might want to change the name of the tables to "primary_users" and "secondary_users" to make it obvious what is going on.
Does that sound okay?
This question was raised at How to drop tables with cyclic foreign keys in MySQL from the delete side of things, but I think that one of the answers is applicable here as well:
SET foreign_key_checks = 0;
INSERT <user>
INSERT <user identity>
SET foreign_key_checks = 1;
Make that a transaction and commit it all at once. I haven't tried it, but it works for deletes, so I don't know why it wouldn't work for inserts.
I've not used it, but you could try INSERT IGNORE. I'd do the two of those, one for each table, such that once they are both done, referential integrity is maintaing. If you do them in a transaction, you can roll back if there is a problem inserting the second one.
Since you're ignoring constraints with this feature, you should do that check in program code instead, otherwise you may end up with data in your database that ignores your constraints.
Thanks to #Mihai for pointing out the problem with the above. Another approach would be to disable constraints whilst you do inserts, and re-enable them afterwards. However, on a large table that might produce more overhead than is acceptable - try it?

Is it possible to declare to mysql queries?

I'm trying to create a code for a single button where it will perform either of two actions where it will add to the database if the user currently don't have the record while it will update the user's record if the user has records already. I've done it like this:
if() {
mysql_query("INSERT INTO table...");
}
else {
mysql_query("UPDATE table SET...");
}
Is it possible?
Yes, what you've written will work. If you have a way to know if there already exists a row or not without making an additional query just for this bit of code, then do exactly as you wrote.
If, however, you planned to first SELECT from the table to see if a row exists, then conditionally INSERT or UPDATE, you will perform more queries than necessary.
It would be better to either:
Have a PRIMARY KEY or other constraint on the table prevent duplicate INSERTs. Then issue an INSERT ... ON DUPLICATE KEY UPDATE query. This will attempt to INSERT the row, and if it is a duplicate, automatically perform the specified UPDATE to that row instead.
Issue the UPDATE query and check mysql_affected_rows to see if it updated an existing row. If not, then issue the INSERT query to create the new row.
Which one is more appropriate depends on your application.
you can use INSERT ... ON DUPLICATE KEY UPDATE Syntax like:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
If you have properly set unique keys, you should use REPLACE so you could remove the if.
REPLACE INTO table VALUE (...);
Pay attention that this is a MySQL extension, thus not portable to other DBs.
Yes, you could try the insert then if it fails try the update.
But you could use the MYSQL sql "REPLACE" keyword, which will insert a new record if it doesn't exist or delete the existing record and insert your new one if it does.
You could also use the INSERT ... ON DUPLICATE KEY UPDATE syntax
(explained here - Link to MYSQL ref which seems to be the closest fit to your requirement.
yes it is possible
first write a query for check that record is already exist or not.
Yes it is possible , it will work