问题
I'm trying to get an id from a companies table where the id is not yet in the crawlLog table. Then I need to insert that companyId into the crawlLog table.
I need to do this in one call so that parallel crawlers don't pull the same url after some other crawler has selected a url, but hasn't inserted it into the crawl log yet. I don't want to lock tables because of other problems that generates.
I get this error from both queries below:
You can't specify target table 'crawlLog' for update in FROM clause
Here are two queries i've tried to do the same thing.
INSERT INTO crawlLog (companyId, timeStartCrawling)
VALUES
(
(
SELECT companies.id FROM companies
LEFT OUTER JOIN crawlLog
ON companies.id = crawlLog.companyId
WHERE crawlLog.companyId IS NULL
LIMIT 1
),
now()
)
I've also tried this, but get the same error:
INSERT INTO crawlLog (companyId, timeStartCrawling)
VALUES
(
(
SELECT id
FROM companies
WHERE id NOT IN
(
SELECT companyId
FROM crawlLog
)
LIMIT 1
),
now()
)
回答1:
Why use a Subselect? INSERT INTO ... SELECT exists:
INSERT INTO crawlLog (companyId, timeStartCrawling)
SELECT companies.id, NOW()
FROM companies
LEFT OUTER JOIN crawlLog
ON companies.id = crawlLog.companyId
WHERE crawlLog.companyId IS NULL
LIMIT 1
And that way it should not complain about using a table both in the INSERT and SELECT part
回答2:
You can't update rows which you are querying. There is a way to force MySQL to use a temporary table implicitly:
INSERT INTO crawlLog (companyId, timeStartCrawling)
VALUES
(
SELECT id, when FROM
(
SELECT companies.id AS id, now() AS when FROM companies
LEFT OUTER JOIN crawlLog
ON companies.id = crawlLog.companyId
WHERE crawlLog.companyId IS NULL
LIMIT 1
)
)
回答3:
This works and seems like the simplest solution:
Using the simpler of the two statements in my question, I created an alias for the inner crawlLog table as suggested by @Tocco in the comments, and then removed the necessary encapsulation in VALUES().
INSERT INTO crawlLog (companyId, timeStartCrawling)
SELECT id, now()
FROM companies
WHERE id NOT IN
(
SELECT companyId
FROM crawlLog AS crawlLogAlias
)
LIMIT 1
回答4:
Do the select into a temp table, then insert selecting from the temp table. You can't insert into a table and select from it in the same statement, so use a temp table and two statements.
回答5:
In MySQL, you can't modify the same table which you use in the SELECT part. This behaviour is documented at: http://dev.mysql.com/doc/mysql/en/UPDATE.html
Original Answer: MySQL Error 1093 - Can't specify target table for update in FROM clause
来源:https://stackoverflow.com/questions/6630338/how-do-i-rewrite-this-mysql-query-so-it-doesnt-throw-this-error-you-cant-spec