3

我正在尝试从公司表中获取 id,其中该 id 尚未在 crawlLog 表中。然后我需要将该 companyId 插入到 crawlLog 表中。

我需要在一次调用中执行此操作,以便并行爬虫在其他爬虫选择了一个 url 但尚未将其插入爬网日志后不会拉取相同的 url。我不想因为产生其他问题而锁定表。

我从以下两个查询中收到此错误:

You can't specify target table 'crawlLog' for update in FROM clause

这是我尝试做同样事情的两个查询。

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()
)

我也试过这个,但得到同样的错误:

INSERT INTO crawlLog (companyId, timeStartCrawling)
VALUES
(
    (
        SELECT id
        FROM companies
        WHERE id NOT IN
        (
            SELECT companyId
            FROM crawlLog
        )
        LIMIT 1
    ),
    now()
)
4

4 回答 4

3

为什么使用子选择?INSERT INTO ... SELECT 存在:

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

这样它就不应该抱怨在 INSERT 和 SELECT 部分都使用表

于 2011-07-08T21:06:09.143 回答
1

您无法更新正在查询的行。有一种方法可以强制 MySQL 隐式使用临时表:

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
    )
)
于 2011-07-08T21:01:05.243 回答
1

这有效,似乎是最简单的解决方案:

在我的问题中使用两个语句中较简单的一个,我按照@Tocco 在评论中的建议为内部 crawlLog 表创建了一个别名,然后在 VALUES() 中删除了必要的封装。

INSERT INTO crawlLog (companyId, timeStartCrawling)
SELECT id, now()
FROM companies
WHERE id NOT IN
(
    SELECT companyId
    FROM crawlLog AS crawlLogAlias
)
LIMIT 1
于 2011-07-08T21:01:34.510 回答
0

在临时表中进行选择,然后从临时表中插入选择。您不能在同一语句中插入表并从中进行选择,因此请使用临时表和两个语句。

于 2011-07-08T20:59:05.497 回答