I have a MySQL insertion template:
INSERT INTO $0.$1 ($2$ColumnList)
VALUES ($2$ValueList) ON DUPLICATE KEY UPDATE
This is a MySQL command file (*.sqlcmd) which a program uses to randomly pass ColumnList and ValueList. So, I don't know in advance what are the values or the columns.
Now, I wish to make a conditional insertion to insert only if the columns are NULL or NOT NULL. Please note that I know I can write a MySQL statement like where mycolumn IS NULL or NOT NULL.
But are there any standard MySQL flags similar to ON DUPLICATE KEY UPDATE type, which I can specify once and for all, and that helps me to get rid of mentioning individual column names one at a time with IS NULL or IS NOT NULL?
No, there's no way to do this automatically. You need to name each column explicitly:
ON DUPLICATE KEY UPDATE col1 = IFNULL(VALUES(col1), col1), col2 = IFNULL(VALUES(col2), col2), ...
Whatever script is creating the variable $ColumnList could presumably generate this ON DUPLICATE KEY UPDATE clause from the same original data.
Related
I am doing the following SQL tutorial: http://sql.learncodethehardway.org/book/ex11.html
and in this exercise the author says in the second paragraph:
In this situation, I want to replace my record with another guy but
keep the unique id. Problem is I'd have to either do a DELETE/INSERT
in a transaction to make it atomic, or I'd need to do a full UPDATE.
Could anyone explain to me what the problem is with doing an UPDATE, and when we might choose REPLACE instead of UPDATE?
The UPDATE code:
UPDATE person SET first_name = "Frank", last_name = "Smith", age = 100
WHERE id = 0;
Here is the REPLACE code:
REPLACE INTO person (id, first_name, last_name, age)
VALUES (0, 'Frank', 'Smith', 100);
EDIT: I guess another question I have is why would you ever do a DELETE/INSERT instead of just an UPDATE as is discussed in the quoted section?
According to the documentation, the difference is:
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.
So what it does:
Try to match the row using one of the available indexes;
If the row doesn't exist already: add a new one;
If the row exists already: delete the existing row and add a new one afterwards.
When might using this become useful over separate insert and update statements?
You can safely call this, and you don't have to worry about existing rows (one statement vs. two);
If you want related data to be removed when inserting / updating, you can use replace: it deletes all related data too);
When triggers need to fire, and you expect an insert (bad reason, okay).
First Replace isn't widely understood in all database engines.
Second replace inserts/updates a record based on the primary key. While with update you can specify more elaborate conditions:
UPDATE person SET first_name = 'old ' + first_name WHERE age > 50
Also UPDATE won't create records.
UPDATE will have no effect if the row does not exist.
Where as the INSERT or REPLACE will insert if the row doesn't exists or replace the values if it does.
Update will change the existing records value in table based on particular condition. So you can change one or many records in single query.
Insert or Replace will insert a new record if records is not present in table else will replace. Replace will only work if and only if you provide the primary key value in the insert or replace query. If you forget to add primary key field value than a new record will created in table.
Case example:-
Update: You have a calculation of wages to be done based on a formula using the column values. In this case you will always use update query as using one single query you can update multiple records.
Insert or Replace: Already mentioned in the link you shared.
How the REPLACE INTO statement works:
AS INSERT:
REPLACE INTO table_name (column1name, column2name, ...)
VALUES (value1, value2, ...);
AS UPDATE:
REPLACE INTO table_name SET column1name = value, column2name = value, ... ;
The REPLACE statement checks whether the intended data record's unique key value already exists in the table before inserting it as a new record or updating it.
The REPLACE INTO statement attempts to insert a new record or modify an existing record. In both cases, it checks whether the unique key of the proposed record already exists in the table. Suppose a value of NO or FALSE is returne. In that case, the REPLACE statement inserts the record similar to the INSERT INTO statement.
Suppose the key value already exists in the table (in other words, a duplicate key). In that case, the REPLACE statement deletes the existing record of data and replaces it with a new record of data. This happens regardless of whether you use the first or the second REPLACE statement syntax.
Once the REPLACE INTO statement is used to insert or modify data, it determines first whether the new data record already exists in the table. It checks if the PRIMARY or the UNIQUE KEY matches one of the existing records.
If there is no matching key, the REPLACE works like a normal INSERT statement. Otherwise, it deletes the existing record and replaces it with the new one. This is considered a sort of modification or update of an existing record. However, it would be best if you were careful here. Suppose you do not specify a value for a column in the SET clause. In that case, the REPLACE statement uses the default value (if a default value has been set). Otherwise, it's set as NULL.
I want to do the following:
INSERT INTO table1 (term1, term2, number) values ('A','B',10);
however if values A and B are already present in table1 regardless of their order, ie. the predicate
(term1='A' && term2='B') OR (`term1='B' && term2='A')
holds true, then I just want to update column number. Is there any way of doing that?
A (perhaps the) clean way to handle this situation is to use INSERT ... ON DUPLICATE KEY UPDATE, read the documentation.
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that
would cause a duplicate value in a UNIQUE index or PRIMARY KEY, MySQL
performs an UPDATE of the old row
The important part is would cause a duplicate value in a UNIQUE index. Therefore you need to create an multicolumn unique index.
Now I'm not sure if you can manage the order that way, therefore I'd create an extra field with the concatenation of the sorted values of your fields, and have that field uniquely indexed.
EDIT: Instead of storing the concatenation your fields, you could also just store the hash and index it.
Thanks #okiharaherbst,
This is what I did: I added new column "uniqueKey" as primary key and insert goes as follows:
INSERT INTO table1(term1,term2,num,uniquekey) VALUES ( "a","b",10,
concat(greatest(term1,term2),least(term1,term2))) on duplicate key update num=10;
I'm moving a msSQL database to mySQL. In my MS SQL database I have stored procedures that use an "upsert" (update, if ##rowcount = 0, Insert) type of thing.
I want to do the same kind of think in My SQL. I have found a couple of options
1) use - Insert xxxx on duplicate key update values (x, y, x) etc.
2) Replace into table_name (col_name,...) (value,...)
Which one is more efficient? I'm leaning towards the 2nd one since I will be doing a lot of updating, rather than inserting. Also, I believe that the insert on duplicate key will keep bumping the auto_increment values even when it ends up being an update.
Another note: Each account record will be updated EVERY night. Occasionally a new account record will be inserted, but again, primarily the accounts will be updated.
Are there other/better options that I'm overlooking. Am I on the right track?
MySQL has several facilities for this:
REPLACE has the effect of a DELETE if the row exists, then INSERT. This means it cannot perform partial updates on the data, any fields that are not specified revert to defaults.
ON DUPLICATE KEY UPDATE is an option on an INSERT that can handle key collisions, including those on a PRIMARY KEY. If a duplicate is found, the UPDATE statement you specify is executed instead.
For example:
INSERT INTO people (id, name) VALUES (1, 'Jeremy')
ON DUPLICATE KEY UPDATE name=VALUES(name)
You can use VALUES() to specify the same value in the INSERT without having to repeat it.
It's important to remember that NULL values can be duplicated since they don't exist and aren't equivalent: NULL=NULL is false. Non-NULL values can be enforced unique, or you can have a NOT NULL column to avoid this.
I have an insert query for MySQL that looks like this:
INSERT INTO table (foo, bar, fooo, baar, etc) VALUES (?,?,?,?,?)
It is used in a script to migrate some columns and keeps encountering duplicate primary keys. (Old database was awful and poorly maintained).
Is there a way I can just tell it to replace the whole offending row with the current values tossing out the old stuff entirely? I know there is an ON DUPLICATE KEY UPDATE command, but I don't know if it would help me as all I've seen it used for is incrementing.
ANSWER: INSERT INTO table (foo, bar, fooo, baar, etc) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE foo=?, bar=?, fooo=?, baar=?, etc=?
Keep in mind that you have to add the values in the referenced array again to account for the extra question marks.
on duplicate key update should work, as should a replace statement.
From MySQL manual:
If you specify ON DUPLICATE KEY
UPDATE, and a row is inserted that
would cause a duplicate value in a
UNIQUE index or PRIMARY KEY, an UPDATE
of the old row is performed.
What you said:
Is there a way I can just tell it to
replace the whole offending row with
the current values tossing out the old
stuff entirely?
Conclusion: why don't you just try it? It seems it does exactly what you want.
Edit: Since you haven't provided any examples of what you were trying to do, I'll use some from MySQL's website.
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
Or if you want something that relates more to real world:
INSERT INTO table(int_field, str_field, float_field) VALUES (15, 'some string', '1.22')
ON DUPLICATE KEY UPDATE int_field = 15, str_field = 'some_string', float_field = '1.22';
I want to update a table value on Mysql 5 but if the key does not exist create it.
The way I found to do it is by:
INSERT yyy ON DUPLICATE KEY UPDATE field;
The question is : is the format above less efficient than other ways to do it (As the insert will happen only once and update will happen very often)?
for example:
$result = UPDATE field;
if (num_rows_effected($result)==0) INSERT yyy
Furthermore: Is there a better way to do this in Mysql: for example a kind of:
UPDATE value IF NO SUCH ROW INSERT yyy;
Update: For those who suggested REPLACE, here is an extension to my question:
"Thanks! I need to increase a counter that is already in the table (if it exists). If not create a table row with value 1 for this column. How can I do update with this format (REPLACE)? "
There is a REPLACE also.
INSERT ON DUPLICATE KEY UPDATE will fire UPDATE triggers when it will stumble upon a duplicate key and won't violate FK's in case on UPDATE.
REPLACE will fire DELETE and INSERT triggers, and will violate FK's referencing the row being REPLACE'd.
If you don't have any triggers or FK's, then use INSERT ON DUPLICATE KEY UPDATE, it's most efficient.
You seem to be looking for this query:
INSERT
INTO table (key, counter)
VALUES (#key, 1)
ON DUPLICATE KEY UPDATE
counter = counter + 1
You cannot do this with REPLACE unless you have selected previous value of the counter before running the query.
P. S. REPLACE appeared in MySQL before ON DUPLICATE KEY UPDATE and is being kept only for compatibility. There is no performance increase from using it.
Yes, you can use the 'replace' syntax:
REPLACE INTO table1 (key, col1, col2) values (1, 'val1','val2');
This is a feature specific to MySQL and is not necessarily implemented in other databases.
As for efficiency, my guess is that a straight update will be faster, since MySQL essentially catches the duplicate key error and handles it accordingly. However, unless you are doing large amounts of insert/updates, the performance impact will be fairly small.
Look at the REPLACE command, it meets your requirements.