Postgres, мощная и универсальная система реляционных баз данных, не поддерживает предложение LIMIT непосредственно в операторе DELETE. Это может быть ограничением, если вы хотите удалить определенное количество строк из таблицы без написания сложных запросов или сценариев.
Итак, как можно добиться аналогичной функциональности в Postgres? Давайте рассмотрим два распространенных обходных пути.
Один из способов удалить ограниченное количество строк в Postgres — объединить оператор DELETE с условием WHERE, которое использует предложение IN вместе с подзапросом. Вот как вы можете удалить только 1 строку для идентификатора пользователя 2, аналогично приведенному выше примеру MySQL:
DELETE FROM quote
WHERE id IN (SELECT id FROM quote WHERE author_id = 2 LIMIT 1)
В этом примере вы используете подзапрос для выбора идентификаторов строк из таблицы котировок, которые вы хотите удалить, ограничивая набор результатов одной строкой. Затем вы используете оператор DELETE с предложением WHERE, которое указывает идентификаторы, которые необходимо удалить. Это эффективно ограничивает количество удаленных строк до 1 для идентификатора пользователя 2. Это больше похоже на конвейерную передачу в bash, где выходные данные одной команды используются в качестве входных данных для следующей команды.
Этот подход обеспечивает обходной путь для достижения желаемого результата, но важно отметить, что он может быть не самым эффективным решением для больших таблиц. Подзапрос в предложении IN может повлиять на производительность, особенно при работе с обширными наборами данных. Вам также нужно будет подумать об эффектах CASCADE, когда может показаться, что удаляется только одна строка, но из-за связанных строк и других строк, связанных с дочерними строками, он также может удалить сотни или тысячи строк.
Другой подход к выполнению ограниченной операции DELETE в Postgres — использование общего табличного выражения (CTE). CTE позволяет вам определить временный набор результатов, на который вы можете ссылаться в операторе DELETE. Вот как вы можете использовать его, чтобы удалить только 1 цитату для идентификатора автора 2:
WITH rows_to_delete AS (
SELECT id
FROM quot
WHERE author_id=2
LIMIT 1
)
DELETE FROM quoteWHERE id IN (SELECT id FROM rows_to_delete);
В этом решении вы сначала создаете CTE под названием «rows_to_delete», который выбирает идентификаторы удаляемых строк, ограниченный одной строкой для идентификатора автора 2. Затем вы используете оператор DELETE с предложением WHERE, которое ссылается на CTE для выполнить удаление.
Еще один пример:
BEGIN; -- начало транзакции
WITH batch_cursor AS (
SELECT id FROM state_transitions
ORDER BY id ASC
LIMIT 10000 --- 10k записей в пакете
)
FOR batch IN (SELECT * FROM batch_cursor)
LOOP
DELETE FROM large_table
WHERE id = batch.id;
END LOOP;
COMMIT; -- ФИКСАЦИЯ ТРАНЗАКЦИИ
Использование CTE может быть более эффективным и чистым способом достижения желаемого результата по сравнению с подходом с подзапросами. Он разделяет логику запроса на отдельные части, что упрощает чтение и обслуживание запроса. К этому методу применима та же логика каскадного удаления.