Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Удаление элементов из базы данных: полный гайд
Удаление данных — критическая операция в работе с БД. Нужно учитывать целостность данных, транзакции, каскадные удаления и логирование.
Базовое удаление
Простой DELETE запрос:
const pool = require("./db");
async function deleteCarById(carId) {
const query = "DELETE FROM cars WHERE id = $1";
const result = await pool.query(query, [carId]);
return result.rowCount;
}
Удаление с проверкой существования
Безопасное удаление с валидацией:
async function safeDeleteCar(carId) {
const client = await pool.connect();
try {
await client.query("BEGIN");
const checkResult = await client.query(
"SELECT id FROM cars WHERE id = $1 FOR UPDATE",
[carId]
);
if (checkResult.rows.length === 0) {
throw new Error(`Автомобиль с ID ${carId} не найден`);
}
const deleteResult = await client.query(
"DELETE FROM cars WHERE id = $1",
[carId]
);
await client.query("COMMIT");
return { success: true, deletedRows: deleteResult.rowCount };
} catch (error) {
await client.query("ROLLBACK");
throw error;
} finally {
client.release();
}
}
Каскадное удаление
Удаление с зависимостями:
CREATE TABLE cars (
id SERIAL PRIMARY KEY,
owner_id INT NOT NULL,
FOREIGN KEY (owner_id) REFERENCES owners(id) ON DELETE CASCADE
);
DELETE FROM owners WHERE id = $1;
В коде:
async function deleteOwnerWithCars(ownerId) {
const client = await pool.connect();
try {
await client.query("BEGIN");
await client.query("DELETE FROM cars WHERE owner_id = $1", [ownerId]);
const result = await client.query("DELETE FROM owners WHERE id = $1", [ownerId]);
await client.query("COMMIT");
return result.rowCount;
} catch (error) {
await client.query("ROLLBACK");
throw error;
} finally {
client.release();
}
}
Мягкое удаление (Soft Delete)
Часто вместо физического удаления используют флаг:
CREATE TABLE cars (
id SERIAL PRIMARY KEY,
model VARCHAR(100),
deleted_at TIMESTAMP NULL
);
async function softDeleteCar(carId) {
const query = "UPDATE cars SET deleted_at = NOW() WHERE id = $1";
await pool.query(query, [carId]);
}
async function getActiveCars() {
const query = "SELECT * FROM cars WHERE deleted_at IS NULL";
return pool.query(query);
}
async function restoreCar(carId) {
const query = "UPDATE cars SET deleted_at = NULL WHERE id = $1";
await pool.query(query, [carId]);
}
Пакетное удаление
Удаление нескольких элементов эффективно:
async function deleteCarsByIds(carIds) {
if (carIds.length === 0) return 0;
const placeholders = carIds.map((_, i) => `$${i + 1}`).join(",");
const query = `DELETE FROM cars WHERE id IN (${placeholders})`;
const result = await pool.query(query, carIds);
return result.rowCount;
}
Логирование удалений
Важно логировать критические операции:
async function deleteCarWithAudit(carId, userId) {
const client = await pool.connect();
try {
await client.query("BEGIN");
const carResult = await client.query(
"SELECT * FROM cars WHERE id = $1",
[carId]
);
if (carResult.rows.length === 0) {
throw new Error("Машина не найдена");
}
const car = carResult.rows[0];
await client.query(
"INSERT INTO audit_log (action, entity_type, entity_id, old_data, user_id, created_at) VALUES ($1, $2, $3, $4, $5, NOW())",
["DELETE", "cars", carId, JSON.stringify(car), userId]
);
await client.query("DELETE FROM cars WHERE id = $1", [carId]);
await client.query("COMMIT");
} catch (error) {
await client.query("ROLLBACK");
throw error;
} finally {
client.release();
}
}
Лучшие практики
- Используй транзакции для сложных удалений
- Проверяй существование перед удалением
- Рассмотри мягкое удаление для критичных данных
- Логируй удаления для аудита
- Настрой CASCADE/RESTRICT правильно в констрейнтах
- Используй FOR UPDATE при конкурентном доступе
Правильное удаление — это не просто DELETE, а целая стратегия безопасности данных.