SQL-запрос: Удалить все записи из таблицы кроме последнего N?

Невозможно получить вывод system(3). Ну, вы можете перенаправить вывод любой команды в файл, а затем открыть и прочитать этот файл, но более разумным подходом является использование popen(3).

popen(3) заменяет system(3) и он позволяет вам читать вывод команды (или, в зависимости от флагов, которые вы передаете, вы можете записать на вход команды).

Вот пример, который выполняет ls(1) и печатает результат:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *ls_cmd = popen("ls -l", "r");
    if (ls_cmd == NULL) {
        fprintf(stderr, "popen(3) error");
        exit(EXIT_FAILURE);
    }

    static char buff[1024];
    size_t n;

    while ((n = fread(buff, 1, sizeof(buff)-1, ls_cmd)) > 0) {
        buff[n] = '\0';
        printf("%s", buff);
    }

    if (pclose(ls_cmd) < 0)
        perror("pclose(3) error");

    return 0;
}
78
задан Milen A. Radev 23 February 2009 в 21:57
поделиться

8 ответов

Вы не можете удалить записи тот путь, при этом основной вопрос - это, Вы не можете использовать подзапрос для определения значения ПРЕДЕЛЬНОГО пункта.

Это работает (протестированный в MySQL 5.0.67):

DELETE FROM `table`
WHERE id NOT IN (
  SELECT id
  FROM (
    SELECT id
    FROM `table`
    ORDER BY id DESC
    LIMIT 42 -- keep this many records
  ) foo
);

промежуточный подзапрос требуется. Без него мы столкнулись с двумя ошибками:

  1. ошибка SQL (1093): Вы не можете указать целевую таблицу 'таблица' для обновления в ИЗ пункта - MySQL не позволяет Вам обращаться к таблице, которую Вы удаляете из прямого подзапроса.
  2. ошибка SQL (1235): Эта версия MySQL еще не поддерживает 'ПРЕДЕЛ & IN/ALL/ANY/SOME подзапрашивают' - Вы не можете использовать ПРЕДЕЛЬНЫЙ пункт в прямом подзапросе оператора NOT IN.

, К счастью, с помощью промежуточного подзапроса позволяет нам обходить оба из этих ограничений.

<час>

Nicole указала, что этот запрос может быть значительно оптимизирован для определенных вариантов использования (таких как этот). Я рекомендую читать , которые отвечают также, чтобы видеть, соответствует ли это Вашему.

126
ответ дан Nicole 6 November 2019 в 03:02
поделиться

Почему не

DELETE FROM table ORDER BY id DESC LIMIT 1, 123456789

Просто удаляют все кроме первой строки (порядок является DESC!), с помощью очень очень большого количества в качестве второго ПРЕДЕЛЬНОГО аргумента. Посмотрите здесь

-1
ответ дан craesh 6 November 2019 в 03:02
поделиться

Это должно работать также:

DELETE FROM [table] INNER JOIN (SELECT [id] FROM (SELECT [id] FROM [table] ORDER BY [id] DESC LIMIT N) AS Temp) AS Temp2 ON [table].[id] = [Temp2].[id]
0
ответ дан achinda99 6 November 2019 в 03:02
поделиться
DELETE FROM table WHERE ID NOT IN
(SELECT MAX(ID) ID FROM table)
2
ответ дан Dave Swersky 6 November 2019 в 03:02
поделиться

УДАЛИТЕ таблицу FROM, ГДЕ идентификатор НЕ В (ИЗБРАННАЯ идентификационная таблица FROM идентификатор ORDER BY, desc ОГРАНИЧИВАЮТ 0, 10)

0
ответ дан Mike Reedell 6 November 2019 в 03:02
поделиться

Если Ваш идентификатор является возрастающим, затем используют что-то как

delete from table where id < (select max(id) from table)-N
5
ответ дан isherwood 6 November 2019 в 03:02
поделиться
DELETE  i1.*
FROM    items i1
LEFT JOIN
        (
        SELECT  id
        FROM    items ii
        ORDER BY
                id DESC
        LIMIT 20
        ) i2
ON      i1.id = i2.id
WHERE   i2.id IS NULL
8
ответ дан Quassnoi 6 November 2019 в 03:02
поделиться

К сожалению для всех ответов, данных другими людьми, Вы не можете DELETE и SELECT от данной таблицы в том же запросе.

DELETE FROM mytable WHERE id NOT IN (SELECT MAX(id) FROM mytable);

ERROR 1093 (HY000): You can't specify target table 'mytable' for update 
in FROM clause

, И при этом MySQL не может поддерживать LIMIT в подзапросе. Это ограничения MySQL.

DELETE FROM mytable WHERE id NOT IN 
  (SELECT id FROM mytable ORDER BY id DESC LIMIT 1);

ERROR 1235 (42000): This version of MySQL doesn't yet support 
'LIMIT & IN/ALL/ANY/SOME subquery'

лучший ответ, который я могу придумать, должен сделать это на двух этапах:

SELECT id FROM mytable ORDER BY id DESC LIMIT n; 

Собирают идентификатор и превращают их в разделенную от запятой строку:

DELETE FROM mytable WHERE id NOT IN ( ...comma-separated string... );

(Обычно интерполяция отдельного от запятой списка в SQL-оператор представляет некоторый риск Внедрения SQL, но в этом случае значения не прибывают из недоверяемого источника, они, как известно, являются значениями идентификаторов от самой базы данных.)

примечание: , Хотя это не сделало задания в единственный запрос, иногда более простое, get-it-done решение является самым эффективным.

9
ответ дан Bill Karwin 6 November 2019 в 03:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: