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

Можно ли назвать запрос любым именем?

1.2 Junior🔥 141 комментариев
#Python Core#REST API и HTTP

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

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

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

Именование запросов в базах данных

Ответ зависит от контекста. Если говорить о именовании параметров запроса, то есть строгие ограничения. Если о переменных в коде, то почти любое имя допустимо при соблюдении соглашений. Разберемся подробнее.

1. Параметры SQL запросов (именованные параметры)

Если ты используешь именованные параметры в SQL, не все имена допустимы:

import psycopg2

conn = psycopg2.connect('dbname=mydb')
cursor = conn.cursor()

# ✅ ПРАВИЛЬНЫЕ имена параметров
cursor.execute(
    "SELECT * FROM users WHERE id = %(user_id)s AND name = %(user_name)s",
    {'user_id': 1, 'user_name': 'Alice'}
)

# ✅ Допустимые символы: буквы, цифры, подчёркивание
cursor.execute(
    "SELECT * FROM users WHERE id = %(user_id_123)s",
    {'user_id_123': 1}
)

# ❌ НЕПРАВИЛЬНО: начиная с цифры
cursor.execute(
    "SELECT * FROM users WHERE id = %(123_user_id)s",  # SyntaxError!
    {'123_user_id': 1}
)

# ❌ НЕПРАВИЛЬНО: специальные символы
cursor.execute(
    "SELECT * FROM users WHERE id = %(user-id)s",  # SyntaxError!
    {'user-id': 1}
)

2. Правила именования параметров по базам данных

PostgreSQL (psycopg2)

import psycopg2

conn = psycopg2.connect('dbname=mydb')
cursor = conn.cursor()

# PostgreSQL позволяет несколько стилей параметризации

# 1. Позиционные параметры ($1, $2, ...)
cursor.execute(
    "SELECT * FROM users WHERE id = $1 AND name = $2",
    (1, 'Alice')
)

# 2. Именованные параметры (%(name)s)
cursor.execute(
    "SELECT * FROM users WHERE id = %(id)s AND name = %(name)s",
    {'id': 1, 'name': 'Alice'}
)

# 3. Правила для имён:
# - Начинаются с буквы или подчёркивания
# - Содержат буквы, цифры, подчёркивания
# - Чувствительны к регистру (если заключены в кавычки)

# ✅ Правильные имена
params = {
    'user_id': 1,
    '_id': 2,
    'userId': 3,
    'id123': 4,
    'ID': 5  # Буквы разных регистров
}

SQLite

import sqlite3

conn = sqlite3.connect(':memory:')
cursor = conn.cursor()

# SQLite использует свои стили параметризации

# 1. Позиционные параметры (?)
cursor.execute(
    "SELECT * FROM users WHERE id = ? AND name = ?",
    (1, 'Alice')
)

# 2. Именованные параметры (:name)
cursor.execute(
    "SELECT * FROM users WHERE id = :id AND name = :name",
    {'id': 1, 'name': 'Alice'}
)

# 3. Правила для SQLite:
# Более свободные, чем PostgreSQL
# Работают с подчёркиванием и буквами

params = {
    'user_id': 1,
    'user-id': 2,  # Дефис работает в SQLite!
    'user.id': 3,   # Точка тоже
}

MySQL

import mysql.connector

conn = mysql.connector.connect(
    host='localhost',
    user='root',
    password='password',
    database='mydb'
)
cursor = conn.cursor()

# MySQL использует %s для всех параметров

# Позиционные параметры
cursor.execute(
    "SELECT * FROM users WHERE id = %s AND name = %s",
    (1, 'Alice')
)

# MySQL НЕ поддерживает именованные параметры встроенно
# Вместо этого нужно использовать dict и форматирование
query = "SELECT * FROM users WHERE id = %(id)s AND name = %(name)s"
params = {'id': 1, 'name': 'Alice'}
cursor.execute(query, params)

3. Правила именования в переменных кода

# В коде переменные для запросов можешь называть по своему

# ✅ ПРАВИЛЬНЫЕ и понятные имена
user_id = 1
user_name = 'Alice'
query_params = {'id': user_id, 'name': user_name}

# ✅ Snake_case для Python переменных
sql_query = "SELECT * FROM users WHERE id = %(id)s"
db_cursor = conn.cursor()
result = db_cursor.execute(sql_query, query_params)

# ❌ ПЛОХИЕ имена (непонятные)
q = "SELECT * FROM users WHERE id = %(id)s"
cp = {'id': 1}

# ❌ Не следуй PEP8
SqlQuery = "SELECT * FROM users"  # CamelCase неправильно для переменных
sqlQuery = "SELECT * FROM users"  # camelCase неправильно для Python

4. SQLAlchemy (ORM) — именование более свободное

from sqlalchemy import create_engine, text
from sqlalchemy.orm import Session
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import declarative_base

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    email = Column(String)

engine = create_engine('postgresql://localhost/mydb')

# SQLAlchemy преобразует имена автоматически
with Session(engine) as session:
    # ✅ Любые имена параметров работают
    query = text(
        "SELECT * FROM users WHERE id = :my_custom_id AND name = :my_custom_name"
    )
    result = session.execute(
        query,
        {"my_custom_id": 1, "my_custom_name": "Alice"}
    )

# ✅ Для ORM это вообще не критично
user = session.query(User).filter(User.id == 1).first()
print(user.name)

5. Подготовленные выражения (Prepared Statements)

Подготовленные выражения — это рекомендуемый способ для защиты от SQL инъекций:

import psycopg2
from psycopg2.extras import execute_values

conn = psycopg2.connect('dbname=mydb')
cursor = conn.cursor()

# Подготовленное выражение с именованными параметрами
prepared_query = """
    SELECT * FROM users 
    WHERE id = %(user_id)s 
    AND email = %(user_email)s
"""

# Для подготовленных выражений имена строже
params = {
    'user_id': 1,
    'user_email': 'alice@example.com'
}

cursor.execute(prepared_query, params)
result = cursor.fetchall()

# ✅ Если используешь execute_values для множественных вставок
data = [
    ('Alice', 'alice@example.com'),
    ('Bob', 'bob@example.com'),
    ('Charlie', 'charlie@example.com')
]

query = "INSERT INTO users (name, email) VALUES %s"
execute_values(cursor, query, data)
conn.commit()

6. Ограничения именования по базам данных

# PostgreSQL
postgres_valid_names = [
    'user_id',        # ✅ Буквы и подчеркивание
    '_id',            # ✅ Начинается с подчеркивания
    'id123',          # ✅ Буквы и цифры
    'ID',             # ✅ Заглавные буквы
]

postgres_invalid_names = [
    '123id',          # ❌ Начинается с цифры
    'user-id',        # ❌ Дефис
    'user.id',        # ❌ Точка
    'user id',        # ❌ Пробел
    'user@id',        # ❌ @ символ
]

# SQLite (более свободный)
sqlite_valid_names = [
    'user_id',
    'user-id',
    'user.id',
    '_id',
    'id123',
]

# MySQL
mysql_reserved_words = [
    'SELECT',         # ❌ Зарезервированное слово
    'INSERT',         # ❌
    'UPDATE',         # ❌
    'user',           # ⚠️ Может быть проблема
]

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

# ✅ ПРАВИЛЬНЫЙ подход
from typing import Dict, Any
import psycopg2

def get_user_by_id_and_email(
    user_id: int,
    user_email: str,
    cursor: psycopg2.extensions.cursor
) -> Dict[str, Any]:
    """
    Получить пользователя по ID и email.
    
    Параметры для запроса:
    - user_id: ID пользователя (именуется как 'uid')
    - user_email: Email пользователя (именуется как 'uemail')
    """
    query = """
        SELECT * FROM users 
        WHERE id = %(uid)s 
        AND email = %(uemail)s
    """
    
    # Именованные параметры (защита от SQL инъекций)
    params = {
        'uid': user_id,
        'uemail': user_email
    }
    
    cursor.execute(query, params)
    return cursor.fetchone()

# ✅ Соглашение по именованию параметров
query_params = {
    'user_id': 1,           # Полное имя
    'email': 'test@test.com',
    'count_limit': 10,
}

# ✅ Документация
query = """
    SELECT * FROM users 
    WHERE id = %(user_id)s 
    LIMIT %(count_limit)s
"""

8. Сравнение стилей параметризации

СтильБдПримерБезопасность
Позиционный (?)SQLiteWHERE id = ?✅ Высокая
Позиционный ($1, $2)PostgreSQLWHERE id = $1✅ Высокая
Именованный (%(name)s)PostgreSQL, SQLiteWHERE id = %(id)s✅ Высокая
Именованный (:name)SQLite, OracleWHERE id = :id✅ Высокая
String formattingВсеf"WHERE id = {id}"❌ SQL инъекции!

Вывод

Можно ли назвать запрос любым именем?

  1. Параметры запроса — НЕТ, есть ограничения

    • Начинаются с буквы или подчёркивания
    • Содержат буквы, цифры, подчёркивания
    • Разные БД имеют разные правила
  2. Переменные в коде — ДА, но следуй PEP8

    • snake_case для переменных
    • Понятные имена
    • Избегай однолитерных имён (кроме циклов)
  3. Главное правило — НИКОГДА не форматируй SQL через f-strings

    # ❌ SQL инъекция
    query = f"SELECT * FROM users WHERE id = {user_id}"
    
    # ✅ Параметризованный запрос
    query = "SELECT * FROM users WHERE id = %(user_id)s"
    cursor.execute(query, {'user_id': user_id})