I'm familiar with using the ON DUPLICATE KEY construct when doing INSERT queries. I'd like to do the same with an UPDATE query, but it seems to be not allowed in MySQL, or else I just don't know the syntax.
My table has a unique index, and I want my UPDATE query to update as many records as it can, and ignore or delete records that would cause a duplicate key. The hypothetical query would look something like this:
UPDATE votes SET user = 'foo' WHERE user = 'bar'
ON DUPLICATE KEY <ignore update or delete row>;
I'm trying to merge 2 users in my database. Where that user already has an existing vote on a topic, the duplicate vote can be ignored, but I don't want the whole query to fail when this happens. Ideally I'd like to delete any records that trigger the duplicate key, and if that can be rolled into the query, so much the better.
This would be a fairly rare event, so if this functionality just plain doesn't exist with UPDATE, I'm open to answers that accomplish what I want with multiple queries.
You can check for this with a self-join:
UPDATE votes AS v1
LEFT JOIN votes AS v2 ON v1.topic = v2.topic AND v2.user = 'foo'
SET v1.user = 'foo'
WHERE v1.user = 'bar'
AND v2.user IS NULL
DEMO
It's not possible to combine UPDATE and DELETE in a single query. You need to do them separately, using a transaction to ensure atomicity. The DELETE query should only delete the records that would be duplicated based on the topic.
START TRANSACTION;
DELETE v1 FROM votes AS v1
JOIN votes AS v2 ON v1.topic = v2.topic
WHERE v1.user = 'foo' AND v2.user = 'bar';
UPDATE votes SET user = 'foo' WHERE user = 'bar';
COMMIT;
Related
I trying to update a table with another table of other database, I the last updated I created a function to save more than one category in one product, so, I when a run the old script to update my table, a constraint error appears. I understand the situation and why that is happenning, but how I allow the update with the table with duplicates data? Is there a way to disable the constraint?
My query
UPDATE novourbano.oc_product_to_category oc
INNER JOIN erp_product_category erp ON oc.product_id = erp.erp_productid
SET oc.product_id = erp.erp_productid,
oc.category_id = erp.erp_categoryid
WHERE oc.product_id <> 0
I try to use that:
SET GLOBAL FOREIGN_KEY_CHECKS=0;
But still not working. Any suggestion? Thank's in advance!
If the table name reflects the table purpose the primary key should be
PRIMARY KEY(product_id, category_id)
in order to avoid duplicates like several rows with the same product_id and category_id.
You can use IGNORE for this update:
UPDATE IGNORE novourbano.oc_product_to_category oc
INNER JOIN erp_product_category erp ON oc.product_id = erp.erp_productid
SET oc.product_id = erp.erp_productid,
oc.category_id = erp.erp_categoryid
I have a MySQL table like this,
id (primary key) | name | scores
and I am reading a large file to insert records into the MySQL table.
New records will be added into this file but the old records are not deleted, so when I read the file, a lot of records are already in the database.
Except to use SELECT COUNT to see if a record is already in the database, is there a best way to check it (to save processing time & database load)?
Or maybe I should just INSERT it directly? (The database will not allow records with duplicate id anyway.)
I usually use update + insert method.
first i will run the update statement. the update query will act like a select query + directly update the data.
update t1 set t1.Name = 'Name', t1.Scores = 99
where t1.Name = 'Name' and t1.Scores = 99
then check if there is a row affected by the above query. if not run the insert statement
if ##RowCount = 0
insert into t1 (Name, Scores) values ('Name',99)
Serch examples for
INSERT IGNORE INTO table
Simple example for this is
INSERT IGNORE INTO `transcripts`
SET `ensembl_transcript_id` = ‘ENSORGT00000000001′,
`transcript_chrom_start` = 12345
`transcript_chrom_end` = 12678;
So I been reading that mysql does not support insert into multiply tables.
you need actually to do two or more INSERT INTO in the query. But my problem is update two tables but insert if one does not exist. is it possible to do in just one query ?
I have this.
UPDATE user, userdetails SET
userdetails.firstname = ?,
user.username = ?,
user.email = ?,
userdetails.location = ?
WHERE user.id = ?
AND userdetails.user_id = ?
$values = array($firstname,$username,$email,$location,$_SESSION['id'],$_SESSION['id']);
But its not always something into the last row
AND userdetails.user_id='{$_SESSION['id']}'
Ill been also read
DUPLICATE KEY UPDATE, but that should not work since they are more than one table ?
I could easily create a query that insert user_id into userdetails.user_id by default when the user registered but it would be much nicer to have it the query.
The INSERT statement does not support adding records to multiple tables simultaneously. For that you want a simple transaction:
BEGIN
INSERT INTO table_a (...)
INSERT INTO table_b (...)
COMMIT
If there's an error when inserting into table_a, it is possible to rollback to the beginning of your transaction. This is the SQL standard way of doing things.
You can use INSERT ... ON DUPLICATE KEY to update records in place if they already exist, or the non-standard MySQL REPLACE INTO which will delete any conflicting records and replace them with your data.
I must create a mysql query with a large number of queries (about 150,000)
For the moment the query is:
UPDATE table SET activated=NULL
WHERE (
id=XXXX
OR id=YYYY
OR id=ZZZZ
OR id=...
...
)
AND activated IS NOT NULL
Do you know a best way for to do that please?
If you're talking about thousands of items, an IN clause probably isn't going to work. In that case you would want to insert the items into a temporary table, then join with it for the update, like so:
UPDATE table tb
JOIN temptable ids ON ids.id = tb.id
SET tb.activated = NULL
UPDATE table
SET activated = NULL
WHERE id in ('XXXX', 'YYYY', 'zzzz')
AND activated IS NOT NULL
In DB2, I need to do a SELECT FROM UPDATE, to put an update + select in a single transaction.
But I need to make sure to update only one record per transaction.
Familiar with the LIMIT clause from MySQL's UPDATE option
places a limit on the number of rows that can be updated
I looked for something similar in DB2's UPDATE reference but without success.
How can something similar be achieved in DB2?
Edit: In my scenario, I have to deliver 1000 coupon codes upon request. I just need to select (any)one that has not been given yet.
The question uses some ambiguous terminology that makes it unclear what needs to be accomplished. Fortunately, DB2 offers robust support for a variety of SQL patterns.
To limit the number of rows that are modified by an UPDATE:
UPDATE
( SELECT t.column1 FROM someschema.sometable t WHERE ... FETCH FIRST ROW ONLY
)
SET column1 = 'newvalue';
The UPDATE statement never sees the base table, just the expression that filters it, so you can control which rows are updated.
To INSERT a limited number of new rows:
INSERT INTO mktg.offeredcoupons( cust_id, coupon_id, offered_on, expires_on )
SELECT c.cust_id, 1234, CURRENT TIMESTAMP, CURRENT TIMESTAMP + 30 DAYS
FROM mktg.customers c
LEFT OUTER JOIN mktg.offered_coupons o
ON o.cust_id = c.cust_id
WHERE ....
AND o.cust_id IS NULL
FETCH FIRST 1000 ROWS ONLY;
This is how DB2 supports SELECT from an UPDATE, INSERT, or DELETE statement:
SELECT column1 FROM NEW TABLE (
UPDATE ( SELECT column1 FROM someschema.sometable
WHERE ... FETCH FIRST ROW ONLY
)
SET column1 = 'newvalue'
) AS x;
The SELECT will return data from only the modified rows.
You have two options. As noted by A Horse With No Name, you can use the primary key of the table to ensure that one row is updated at a time.
The alternative, if you're using a programming language and have control over cursors, is to use a cursor with the 'FOR UPDATE' option (though that may be probably optional; IIRC, cursors are 'FOR UPDATE' by default when the underlying SELECT means it can be), and then use an UPDATE statement with the WHERE CURRENT OF <cursor-name> in the UPDATE statement. This will update the one row currently addressed by the cursor. The details of the syntax vary with the language you're using, but the raw SQL looks like:
DECLARE CURSOR cursor_name FOR
SELECT *
FROM SomeTable
WHERE PKCol1 = ? AND PKCol2 = ?
FOR UPDATE;
UPDATE SomeTable
SET ...
WHERE CURRENT OF cursor_name;
If you can't write DECLARE in your host language, you have to do manual bashing to find the equivalent mechanism.