问题
I have two tables with identical structure. Table A contains all the current ads, Table B contains the archived ads. Column 1 (ad_id) is Primary Key, AI, INT. Table engine is MyISAM.
I need to copy all the table A ads preceding a certain date to the archive, table B. My goal is that all fields except ad_id are duplicated, ad_id should get auto-incremented. Here is what I have attempted:
INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
Table B has many thousands of ads, Table A gets flushed often enough that the unique id field has low numbers that often duplicate the id's in Table B. So MySQL chucks a wobbly and tells me I have a Duplicate entry '8577' for key 'PRIMARY'
.
So I made several attempts to get past that:
First I tried selecting the individual columns to insert, setting ad_id
to NULL:
INSERT INTO B(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT (NULL, `ad_advertiser`, `ad_ln`, `ad_expire`)
FROM A
WHERE YEAR( ad_expire ) <= 2012
That results in the error #1241 - Operand should contain 1 column(s)
, which goes away if I use the wildcard * selector, but then I get the duplicate error.
Next I tried SELECT LAST_INSERT_ID()
, which always returns 0.
Then I tried a few using ON DUPLICATE KEY UPDATE
, but I can't seem to get that to work.
I even tried to grab the highest id with:
SELECT @max := max(ad_id) FROM B;
INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
ON DUPLICATE KEY UPDATE ad_id = @max + 1
This works for exactly one row, then results in a duplicate entry again (since @max is a static variable).
What am I doing wrong here? Am I making this way too difficult?
回答1:
in your case why not use ?
INSERT INTO B(`ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT (`ad_advertiser`, `ad_ln`, `ad_expire`)
FROM A
WHERE YEAR( ad_expire ) <= 2012
回答2:
you may drop the primary key constraint on your ad_id
of your table B
using th following command.
ALTER TABLE B DROP PRIMARY KEY
Then try your usual query i.e.
INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
UPDATE 1
if you dont want to have multiple ad_id
then you may directly try this query
INSERT INTO `B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
ON DUPLICATE KEY UPDATE
ad_advertiser = VALUES(ad_advertiser),
ad_ln = VALUES(ad_ln),
ad_expire = VALUES(ad_expire);
Here is the SQL Fiddle
来源:https://stackoverflow.com/questions/14700664/how-to-insert-into-select-with-on-duplicate-key