Как мне переписать этот запрос MySQL, чтобы он не выдавал эту ошибку: Вы не можете указать целевую таблицу 'crawlLog' для обновления в предложении FROM? - PullRequest
3 голосов
/ 09 июля 2011

Я пытаюсь получить идентификатор из таблицы компаний, где идентификатор еще не находится в таблице 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()
)

Ответы [ 5 ]

3 голосов
/ 09 июля 2011

Зачем использовать подвыбор? 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

1 голос
/ 09 июля 2011

Это работает и кажется самым простым решением:

Используя более простое из двух утверждений в моем вопросе, я создал псевдоним для внутренней таблицы crawlLog, как предложено @Tocco в комментариях, а затем удалилнеобходимая инкапсуляция в VALUES ().

INSERT INTO crawlLog (companyId, timeStartCrawling)
SELECT id, now()
FROM companies
WHERE id NOT IN
(
    SELECT companyId
    FROM crawlLog AS crawlLogAlias
)
LIMIT 1
1 голос
/ 09 июля 2011

Вы не можете обновить строки, которые запрашиваете .Существует способ заставить 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
    )
)
0 голосов
/ 09 июля 2011

Сделайте выбор во временной таблице, затем вставьте выбор из временной таблицы. Вы не можете вставить в таблицу и выбрать из нее в одном и том же операторе, поэтому используйте временную таблицу и два оператора.

0 голосов
/ 09 июля 2011

В MySQL вы не можете изменять ту же таблицу, которую используете в части SELECT. Это поведение задокументировано по адресу: http://dev.mysql.com/doc/mysql/en/UPDATE.html

Оригинальный ответ: MySQL Ошибка 1093 - Невозможно указать целевую таблицу для обновления в предложении FROM

...