← Назад к вопросам

Для чего используется SQL?

1.6 Junior🔥 211 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Для чего используется SQL

Определение и назначение

SQL (Structured Query Language) — это стандартный язык для работы с реляционными базами данных. SQL позволяет создавать, читать, обновлять и удалять данные (CRUD операции).

История и универсальность

SQL был создан в 1974 году и стал стандартом ANSI в 1986 году. Сегодня SQL используется практически во всех реляционных СУБД:

  • PostgreSQL
  • MySQL
  • SQL Server
  • Oracle
  • SQLite
  • MariaDB

Основные операции (CRUD)

CREATE — создание новых данных:

INSERT INTO users (name, email, age) 
VALUES ('John Doe', 'john@example.com', 30);

READ — чтение/запрос данных:

SELECT id, name, email FROM users WHERE age > 25;

UPDATE — обновление существующих данных:

UPDATE users SET email = 'newemail@example.com' WHERE id = 1;

DELETE — удаление данных:

DELETE FROM users WHERE id = 5;

Основные операции SQL

DDL (Data Definition Language) — определение схемы:

-- Создание таблицы
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(255) UNIQUE,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Изменение таблицы
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- Удаление таблицы
DROP TABLE users;

-- Создание индекса
CREATE INDEX idx_email ON users(email);

DML (Data Manipulation Language) — работа с данными:

-- Вставка данных
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');

-- Выборка данных
SELECT * FROM users WHERE id = 1;

-- Обновление
UPDATE users SET name = 'Bob' WHERE id = 2;

-- Удаление
DELETE FROM users WHERE age < 18;

DQL (Data Query Language) — запросы данных:

SELECT u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id
HAVING COUNT(o.id) > 0
ORDER BY order_count DESC;

Использование SQL в Node.js приложениях

Прямое исполнение запросов:

const { Pool } = require('pg');
const pool = new Pool({
  user: 'postgres',
  password: 'password',
  host: 'localhost',
  port: 5432,
  database: 'myapp'
});

// Простой SELECT
const result = await pool.query('SELECT * FROM users WHERE id = $1', [1]);
console.log(result.rows);

// INSERT с параметрами (защита от SQL injection)
await pool.query(
  'INSERT INTO users (name, email) VALUES ($1, $2)',
  ['John', 'john@example.com']
);

ORM (Object-Relational Mapping):

// TypeORM/Sequelize генерируют SQL за вас
const user = await User.findById(1);
user.email = 'newemail@example.com';
await user.save();

// Под капотом выполняется SQL:
// UPDATE users SET email = 'newemail@example.com' WHERE id = 1

Практические примеры для бэкенда

Получить всех пользователей с количеством их заказов:

const users = await db.query(`
  SELECT 
    u.id,
    u.name,
    COUNT(o.id) as order_count,
    SUM(o.total) as total_spent
  FROM users u
  LEFT JOIN orders o ON u.id = o.user_id
  GROUP BY u.id
  ORDER BY total_spent DESC
`);

Найти активных пользователей (логинились за последний месяц):

const activeUsers = await db.query(`
  SELECT u.id, u.name, u.last_login
  FROM users u
  WHERE u.last_login > NOW() - INTERVAL '30 days'
  ORDER BY u.last_login DESC
`);

Получить статистику по категориям:

const stats = await db.query(`
  SELECT 
    c.name as category,
    COUNT(p.id) as product_count,
    AVG(p.price) as avg_price,
    MAX(p.price) as max_price
  FROM categories c
  LEFT JOIN products p ON c.id = p.category_id
  GROUP BY c.id
  ORDER BY product_count DESC
`);

Транзакция (несколько команд как одно):

const client = await pool.connect();
try {
  await client.query('BEGIN');
  
  // Создаём заказ
  const order = await client.query(
    'INSERT INTO orders (user_id, total) VALUES ($1, $2) RETURNING id',
    [userId, 150]
  );
  const orderId = order.rows[0].id;
  
  // Добавляем товары
  await client.query(
    'INSERT INTO order_items (order_id, product_id, qty) VALUES ($1, $2, $3)',
    [orderId, productId, 2]
  );
  
  // Уменьшаем количество товара
  await client.query(
    'UPDATE products SET stock = stock - 1 WHERE id = $1',
    [productId]
  );
  
  await client.query('COMMIT');
} catch (error) {
  await client.query('ROLLBACK');
  throw error;
} finally {
  client.release();
}

Фильтрация и поиск

WHERE условия:

-- Простое сравнение
SELECT * FROM users WHERE age > 18;

-- IN (множественные значения)
SELECT * FROM orders WHERE status IN ('pending', 'processing');

-- LIKE (поиск текста)
SELECT * FROM users WHERE name LIKE 'John%';

-- BETWEEN (диапазон)
SELECT * FROM transactions WHERE amount BETWEEN 100 AND 1000;

-- NOT NULL
SELECT * FROM users WHERE phone IS NOT NULL;

-- Комбинированные условия
SELECT * FROM orders 
WHERE user_id = 1 AND status = 'completed' AND created_at > '2024-01-01';

Агрегирование данных

-- Подсчёт записей
SELECT COUNT(*) as total_users FROM users;

-- Сумма значений
SELECT SUM(total) as revenue FROM orders WHERE status = 'completed';

-- Среднее значение
SELECT AVG(age) as avg_age FROM users;

-- Минимум/максимум
SELECT MIN(price) as cheapest, MAX(price) as expensive FROM products;

-- Группировка
SELECT 
  status,
  COUNT(*) as count,
  AVG(total) as avg_total
FROM orders
GROUP BY status;

Важность SQL для бэкенда

1. Производительность:

  • SQL запросы оптимизированы на уровне СУБД
  • Индексы ускоряют поиск
  • Агрегирование на уровне БД быстрее, чем в коде

2. Безопасность:

  • Параметризованные запросы защищают от SQL injection
  • Права доступа управляются на уровне БД

3. Консистентность:

  • Транзакции обеспечивают атомарность операций
  • Foreign keys предотвращают несоответствия данных

4. Масштабируемость:

  • База данных масштабируется независимо от приложения
  • Кэширование и реplication работают на уровне БД

Лучшие практики

// ПРАВИЛЬНО: параметризованные запросы
await db.query('SELECT * FROM users WHERE email = $1', [userEmail]);

// НЕПРАВИЛЬНО: строковая конкатенация
await db.query(`SELECT * FROM users WHERE email = '${userEmail}'`);

// ПРАВИЛЬНО: используй LIMIT для больших выборок
SELECT * FROM orders WHERE status = 'pending' LIMIT 100;

// НЕПРАВИЛЬНО: SELECT * без ограничений
SELECT * FROM huge_table;

// ПРАВИЛЬНО: используй индексы для часто запрашиваемых полей
CREATE INDEX idx_user_email ON users(email);

// ПРАВИЛЬНО: нормализуй данные
// НЕПРАВИЛЬНО: хранить JSON в таблице вместо отдельной таблицы

Заключение

SQL — это фундаментальный инструмент для бэкенд-разработчика. Он позволяет:

  • Эффективно хранить и извлекать данные
  • Выполнять сложные запросы и аналитику
  • Обеспечивать целостность и безопасность данных
  • Масштабировать приложение

Умение писать оптимальные SQL запросы — критичный навык для разработки production-приложений.