Что такое Prepared Statement (подготовленное выражение) при работе с базами данных в Node.js?

«Что такое Prepared Statement (подготовленное выражение) при работе с базами данных в Node.js?» — вопрос из категории Базы данных, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Prepared Statement (подготовленное выражение) — это предварительно скомпилированный SQL-запрос, в котором данные (параметры) отделены от самой структуры запроса. В Node.js это основной механизм безопасного выполнения SQL-запросов.

Ключевые преимущества:

  1. Защита от SQL-инъекций: Это самое важное. Параметры передаются отдельно и корректно экранируются драйвером БД, что делает атаки путём подстановки恶意 SQL-кода невозможными.
  2. Повышение производительности: При многократном выполнении одного и того же запроса с разными параметрами (например, в цикле) СУБД может скомпилировать план запроса один раз и переиспользовать его.
  3. Удобство и читаемость: Код становится чище, так как параметры явно передаются в виде массива или объекта.

Пример использования с популярными драйверами Node.js:

1. С mysql2 (для MySQL/MariaDB): Используются плейсхолдеры ?.

import mysql from 'mysql2/promise';

const connection = await mysql.createConnection({ /* конфиг */ });

const userId = 42;
const status = 'active';

// Запрос с подготовленным выражением
const sql = 'SELECT * FROM users WHERE id = ? AND status = ?';
const [rows] = await connection.execute(sql, [userId, status]); // Параметры передаются массивом

console.log(rows);

2. С pg (для PostgreSQL): Используются позиционные плейсхолдеры $1, $2, ....

import { Client } from 'pg';

const client = new Client();
await client.connect();

const newPrice = 99.99;
const productId = 15;

// Запрос с подготовленным выражением
const sql = 'UPDATE products SET price = $1 WHERE id = $2 RETURNING *';
const result = await client.query(sql, [newPrice, productId]); // Параметры передаются массивом

console.log(result.rows[0]); // Обновлённая запись
await client.end();

3. С ORM Sequelize: ORM автоматически генерирует подготовленные выражения.

const user = await User.findOne({
  where: {
    id: userId,       // Эти значения будут подставлены
    status: 'active'  // как параметры подготовленного выражения
  }
});

Важно: Всегда используйте подготовленные выражения или методы ORM для подстановки пользовательских данных в SQL-запросы. Прямая конкатенация строк ('SELECT ... WHERE id = ' + userId) — это критическая уязвимость безопасности.