473,387 Members | 1,504 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

MySql UPDATE problem with duplicate rows

Hi,

I have a MySql problem I hope someone can help me with. I'm trying to run
an update on a linking table, the update is running into a Primary Key
constraint violation, and in my workaround I've got stuck trying to write a
DELETE statement.

Here's the table I'm working on:

CREATE TABLE `articles_categories` (
`articleId` int(11) NOT NULL default '0',
`categoryId` int(11) NOT NULL default '0',
PRIMARY KEY (`articleId`,`categoryId`),
CONSTRAINT `articles_categories_ibfk_1` FOREIGN KEY (`articleId`) REFERENCES
`articles` (`articleId`),
CONSTRAINT `articles_categories_ibfk_2` FOREIGN KEY (`categoryId`)
REFERENCES `categories` (`categoryId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC

table: articles_categories - START POINT

articleId | categoryId
-----------------------
39 | 7
39 | 8
40 | 8

In my web app I am deleting categoryId=8 from the categories table, so I
would like to move all the articles that were in that category into
categoryId=7.

I cannot just run a simple UPDATE SET categoryId=7 WHERE categoryId=8,
because that will violate the Primary Key constraint (you can't have *two*
rows with articleId 39 and categoryId 7). Here's what I want to finish up
with:

table: articles_categories - END POINT

articleId | categoryId
-----------------------
39 | 7
40 | 7

Here's what I've got so far.

******
STEP 1: copy all rows with categoryId=8 into a temporary table:
******

DROP TEMPORARY TABLE IF EXISTS ac_duplicates;
CREATE TEMPORARY TABLE ac_duplicates
SELECT * FROM articles_categories ac WHERE categoryId=8;

******
STEP 2: update all the rows in the duplicate table:
******

UPDATE ac_duplicates SET categoryId=7 WHERE categoryId=8;

******
STEP 3: JOIN the duplicate table to the original table and delete any
duplicate rows from the original table
******

Here's where I have the problem. I *can* do the join:

SELECT ac.* FROM articles_categories ac INNER JOIN ac_duplicates acd ON
acd.articleId=ac.articleId AND acd.categoryId=ac.categoryId;

But I *can't* work out how to do the DELETE:

**********
PROBLEM
**********

DELETE FROM articles_categories WHERE articleId IN (SELECT ac.articleId FROM
articles_categories ac INNER JOIN ac_duplicates acd ON
acd.articleId=ac.articleId AND acd.categoryId=ac.categoryId)

All I get is this error:
Error Code : 1093
You can't specify target table 'articles_categories' for update in FROM
clause

So if someone can help me write that DELETE, I can get what I want, because
the only remaining step will be very simple: to run my simple UPDATE on the
original table (no longer violating the Primary Key constraint).

TIA,

JON

May 14 '06 #1
7 9752
Jon Maz wrote:
Hi,

I have a MySql problem I hope someone can help me with. I'm trying to run
an update on a linking table, the update is running into a Primary Key
constraint violation, and in my workaround I've got stuck trying to write a
DELETE statement.

Here's the table I'm working on:

CREATE TABLE `articles_categories` (
`articleId` int(11) NOT NULL default '0',
`categoryId` int(11) NOT NULL default '0',
PRIMARY KEY (`articleId`,`categoryId`),
CONSTRAINT `articles_categories_ibfk_1` FOREIGN KEY (`articleId`) REFERENCES
`articles` (`articleId`),
CONSTRAINT `articles_categories_ibfk_2` FOREIGN KEY (`categoryId`)
REFERENCES `categories` (`categoryId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC

table: articles_categories - START POINT

articleId | categoryId
-----------------------
39 | 7
39 | 8
40 | 8

In my web app I am deleting categoryId=8 from the categories table, so I
would like to move all the articles that were in that category into
categoryId=7.

I cannot just run a simple UPDATE SET categoryId=7 WHERE categoryId=8,
because that will violate the Primary Key constraint (you can't have *two*
rows with articleId 39 and categoryId 7). Here's what I want to finish up
with:

table: articles_categories - END POINT

articleId | categoryId
-----------------------
39 | 7
40 | 7

Here's what I've got so far.

******
STEP 1: copy all rows with categoryId=8 into a temporary table:
******

DROP TEMPORARY TABLE IF EXISTS ac_duplicates;
CREATE TEMPORARY TABLE ac_duplicates
SELECT * FROM articles_categories ac WHERE categoryId=8;

******
STEP 2: update all the rows in the duplicate table:
******

UPDATE ac_duplicates SET categoryId=7 WHERE categoryId=8;

******
STEP 3: JOIN the duplicate table to the original table and delete any
duplicate rows from the original table
******

Here's where I have the problem. I *can* do the join:

SELECT ac.* FROM articles_categories ac INNER JOIN ac_duplicates acd ON
acd.articleId=ac.articleId AND acd.categoryId=ac.categoryId;

But I *can't* work out how to do the DELETE:

**********
PROBLEM
**********

DELETE FROM articles_categories WHERE articleId IN (SELECT ac.articleId FROM
articles_categories ac INNER JOIN ac_duplicates acd ON
acd.articleId=ac.articleId AND acd.categoryId=ac.categoryId)

All I get is this error:
Error Code : 1093
You can't specify target table 'articles_categories' for update in FROM
clause

So if someone can help me write that DELETE, I can get what I want, because
the only remaining step will be very simple: to run my simple UPDATE on the
original table (no longer violating the Primary Key constraint).

TIA,

JON

No, you can't reference a table you're deleting from in a subselect.

How about two steps:

UPDATE article_categories
SET categoryId=7
WHERE categoryId=8 AND
articleId NOT IN (SELECT articleId
FROM article_categories
WHERE categoryId = 7);

Changes any category id from 8 to 7 if there is not already a category of 7 for
that article.

DELETE FROM article_categories
WHERE cateogoryId = 8;

Deletes the remaining rows.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
May 14 '06 #2
Jon Maz wrote:
**********
PROBLEM
**********

DELETE FROM articles_categories WHERE articleId IN (SELECT ac.articleId FROM
articles_categories ac INNER JOIN ac_duplicates acd ON
acd.articleId=ac.articleId AND acd.categoryId=ac.categoryId)


MySQL supports a (proprietary) syntax for multi-table DELETE statements:

DELETE FROM ac
USING articles_categories AS ac
INNER JOIN ac_duplicates AS acd
ON acd.articleId=ac.articleId AND acd.categoryId=ac.categoryId;

This gets around the limitation that MySQL can't SELECT and DELETE from
the same table in one statement.

See http://dev.mysql.com/doc/refman/5.0/en/delete.html for more
information on multi-table deletes.

Regards,
Bill K.
May 14 '06 #3
Hi Jerry,

Your solution is certainly nice and simple & a big improvement on mine, but
I just ran into this error:

UPDATE articles_categories
SET categoryId=7
WHERE categoryId=8 AND
articleId NOT IN (SELECT articleId
FROM articles_categories
WHERE categoryId = 7);

Error Code : 1093
You can't specify target table 'articles_categories' for update in FROM
clause

Any ideas?

TIA,

JON

May 15 '06 #4
Jon Maz wrote:
Hi Jerry,

Your solution is certainly nice and simple & a big improvement on mine, but
I just ran into this error:

UPDATE articles_categories
SET categoryId=7
WHERE categoryId=8 AND
articleId NOT IN (SELECT articleId
FROM articles_categories
WHERE categoryId = 7);

Error Code : 1093
You can't specify target table 'articles_categories' for update in FROM
clause

Any ideas?

TIA,

JON



Sorry, that's right. MySQL doesn't allow you to update the table in the
subselect, either. Sometimes I hate the restrictions in MySQL! (I use DB2 for
non-web work - much more mature - but much more expensive).

The only other way I can think of doing this is to temporarily store the info in
your program then either delete or update, as appropriate. For instance:

$result = mysql_query('SELECT articleId ' .
'FROM articles_categories ' .
"WHERE categoryId = $newcategoryId");
$list = "";
while ($data = mysql_fetch_array($result)) {
if ($list != '')
$list .= ', ';
$list .= $data[0];
}
mysql_free_result($result);
$result = mysql_query('DELETE FROM articles_category ' .
"WHERE article_id IN ($list)";
$result = mysql_query('UPDATE articles_category ' .
"SET categoryId = $newcategoryId " .
"WHERE categoryId = $oldcategoryId");

Of course, use appropriate error checking.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
May 15 '06 #5
Hi Jerry,

Pity, your solution was beautifully simple. I'm gonna try to do all this in
SQL rather than resorting to php. Perhaps I can add a temporary table to
your solution and get it to work? Gonna have a play.

Alternatively there's Bill's suggestion in this thread, but if possible I'd
like to try to get this working with non-proprietary SQL first.

Cheers,

JON
May 15 '06 #6
Jon Maz wrote:
Hi Jerry,

Pity, your solution was beautifully simple. I'm gonna try to do all this in
SQL rather than resorting to php. Perhaps I can add a temporary table to
your solution and get it to work? Gonna have a play.

Alternatively there's Bill's suggestion in this thread, but if possible I'd
like to try to get this working with non-proprietary SQL first.

Cheers,

JON


Yes, a temporary table just might do it.

The only other thing I might suggest is to lock the table so no one else can
update it while you're doing this. Results may not be just what you wish.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
May 15 '06 #7
Hi Bill,

Thanks for your suggestion, it's certainly the most compact solution. But
in the end I managed to get it done using Jerry's UPDATE then DELETE
solution with the addition of a temporary table to get round that MySql
error.

Cheers,

JON
May 17 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: jaysonsch | last post by:
Hello! I am having some problems with a database query that I am trying to do. I am trying to develop a way to search a database for an entry and then edit the existing values. Upon submit, the...
0
by: Lajos Kuljo | last post by:
Eine kleine Dokumentation. Gruss Joska MySQL Syntax SELECT select_expression,...
0
by: Lenz Grimmer | last post by:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi, MySQL 4.0.14, a new version of the popular Open Source/Free Software Database, has been released. It is now available in source and binary...
0
by: Mike Chirico | last post by:
Interesting Things to Know about MySQL Mike Chirico (mchirico@users.sourceforge.net) Copyright (GPU Free Documentation License) 2004 Last Updated: Mon Jun 7 10:37:28 EDT 2004 The latest...
1
by: aleccolvin | last post by:
ON DUPLICATE KEY UPDATE is new as of MySQL 4.1.0, but the web server that I'm using has MySQL 4.0.24 How would I implement ON DUPLICATE KEY UPDATE with an old version of MySQL? Thank you,...
7
by: Steve B. | last post by:
Does anyone know why the DA Update() would throw an exception? I moved the database but I updated the Conn and the DA, currently (trying)removing/replacing DS. Is there a another direction I...
8
by: Nick | last post by:
I have a table with columns (product_id,related_product_id,related_counter) If product A is related to product B then a record should be created, if the record already exists then the...
5
by: strawberry | last post by:
In the function below, I'd like to extend the scope of the $table variable such that, once assigned it would become available to other parts of the function. I thought 'global $table;' would solve...
6
Atli
by: Atli | last post by:
This is an easy to digest 12 step guide on basics of using MySQL. It's a great refresher for those who need it and it work's great for first time MySQL users. Anyone should be able to get...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.