3

IDがまだcrawlLogテーブルにない会社のテーブルからIDを取得しようとしています。次に、その companyId をcrawlLog テーブルに挿入する必要があります。

他のクローラーが URL を選択した後、並列クローラーが同じ URL をプルしないように、1 回の呼び出しでこれを行う必要がありますが、まだクロール ログに挿入していません。他の問題が発生するため、テーブルをロックしたくありません。

以下の両方のクエリからこのエラーが発生します。

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

同じことをしようとした2つのクエリを次に示します。

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

これは機能し、最も簡単な解決策のようです:

質問の 2 つのステートメントのうち単純な方を使用して、コメントで @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

選択を一時テーブルに実行してから、一時テーブルからの選択を挿入します。テーブルへの挿入とテーブルからの選択を同じステートメントで行うことはできないため、一時テーブルと 2 つのステートメントを使用します。

于 2011-07-08T20:59:05.497 に答える