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

Какой синтаксис у sql запроса?

1.3 Junior🔥 282 комментариев
#Основы Go

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Синтаксис SQL-запроса: от базовой структуры до особенностей Go

SQL (Structured Query Language) имеет **декларативный синтаксис**, где вы описываете *что* нужно получить, а не *как*. Основная структура большинства запросов строится вокруг ключевого слова **SELECT**, но полный синтаксис включает множество компонентов.

Базовый синтаксис SELECT-запроса

SELECT [DISTINCT] column1, column2, ...
FROM table_name
[WHERE condition]
[GROUP BY column1, column2, ...]
[HAVING group_condition]
[ORDER BY column1 [ASC|DESC], ...]
[LIMIT count];

Пример простейшего запроса:

SELECT id, name, email FROM users WHERE active = 1 ORDER BY created_at DESC LIMIT 10;

Ключевые компоненты SQL-синтаксиса

1. Клаузы (Clauses)

  • SELECT - указывает возвращаемые столбцы (можно использовать * для всех)
  • FROM - определяет таблицу(ы) для запроса
  • WHERE - фильтрует строки по условию
  • JOIN - объединяет таблицы (INNER, LEFT, RIGHT, FULL)
  • GROUP BY - группирует строки для агрегатных функций
  • HAVING - фильтрует сгруппированные данные
  • ORDER BY - сортирует результаты
  • LIMIT/OFFSET - ограничивает количество результатов

2. Агрегатные функции

SELECT 
    COUNT(*) as total,
    AVG(salary) as avg_salary,
    MAX(age) as max_age,
    SUM(price) as total_price
FROM employees;

3. JOIN-операции

-- INNER JOIN (только совпадающие строки)
SELECT u.name, o.order_date, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- LEFT JOIN (все строки из левой таблицы)
SELECT u.name, o.order_date
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

4. Подзапросы (Subqueries)

SELECT name, email
FROM users
WHERE id IN (SELECT user_id FROM orders WHERE amount > 1000);

-- Коррелированный подзапрос
SELECT name, (SELECT COUNT(*) FROM orders WHERE user_id = users.id) as order_count
FROM users;

Особенности SQL в контексте Go

В Go работа с SQL имеет свою специфику:

Использование плейсхолдеров для безопасности

// НЕПРАВИЛЬНО - уязвимо для SQL-инъекций
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", userName)

// ПРАВИЛЬНО - используем плейсхолдеры
query := "SELECT id, name, email FROM users WHERE active = ? AND age > ?"
rows, err := db.Query(query, true, 18)

Поддержка разных диалектов SQL

// PostgreSQL (использует $1, $2...)
query := "SELECT * FROM users WHERE id = $1 AND status = $2"

// MySQL/SQLite (использует ?)
query := "SELECT * FROM users WHERE id = ? AND status = ?"

// Именованные параметры (через sqlx)
query := "SELECT * FROM users WHERE name = :name AND age > :min_age"

Конструкция запросов динамически

func buildUserQuery(active *bool, minAge *int) (string, []interface{}) {
    var whereClauses []string
    var args []interface{}
    var argPos = 1
    
    if active != nil {
        whereClauses = append(whereClauses, fmt.Sprintf("active = $%d", argPos))
        args = append(args, *active)
        argPos++
    }
    
    if minAge != nil {
        whereClauses = append(whereClauses, fmt.Sprintf("age >= $%d", argPos))
        args = append(args, *minAge)
        argPos++
    }
    
    query := "SELECT * FROM users"
    if len(whereClauses) > 0 {
        query += " WHERE " + strings.Join(whereClauses, " AND ")
    }
    
    return query, args
}

Расширенные возможности SQL-синтаксиса

CTE (Common Table Expressions)

WITH active_users AS (
    SELECT id, name, email 
    FROM users 
    WHERE last_login > NOW() - INTERVAL '30 days'
),
user_orders AS (
    SELECT user_id, COUNT(*) as order_count
    FROM orders
    GROUP BY user_id
)
SELECT au.name, au.email, uo.order_count
FROM active_users au
LEFT JOIN user_orders uo ON au.id = uo.user_id;

Оконные функции (Window Functions)

SELECT 
    name,
    department,
    salary,
    AVG(salary) OVER (PARTITION BY department) as avg_department_salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_department
FROM employees;

Важные нюансы SQL для Go-разработчиков

  1. Экранирование идентификаторов - используйте двойные кавычки или бэктики в зависимости от СУБД

  2. Типы данных - соответствие между SQL-типами и Go-типами

  3. NULL-обработка - используйте sql.NullString, sql.NullInt64 и т.д.

  4. Транзакции - группировка запросов в транзакции для atomicity

    tx, err := db.Begin()
    _, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, fromID)
    _, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, toID)
    err = tx.Commit()
    
  5. Подготовленные выражения (Prepared Statements) для повторяющихся запросов:

    stmt, err := db.Prepare("SELECT * FROM users WHERE id = ?")
    defer stmt.Close()
    
    // Многократное использование
    stmt.Query(1)
    stmt.Query(2)
    

SQL-синтаксис может варьироваться между разными СУБД (PostgreSQL, MySQL, SQLite), но основные принципы остаются общими. В Go критически важно правильно обрабатывать параметры запросов для предотвращения инъекций и учитывать особенности конкретного драйвера базы данных.

Какой синтаксис у sql запроса? | PrepBro