← Назад к вопросам
Можно ли назвать запрос любым именем?
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. Сравнение стилей параметризации
| Стиль | Бд | Пример | Безопасность |
|---|---|---|---|
| Позиционный (?) | SQLite | WHERE id = ? | ✅ Высокая |
| Позиционный ($1, $2) | PostgreSQL | WHERE id = $1 | ✅ Высокая |
| Именованный (%(name)s) | PostgreSQL, SQLite | WHERE id = %(id)s | ✅ Высокая |
| Именованный (:name) | SQLite, Oracle | WHERE id = :id | ✅ Высокая |
| String formatting | Все | f"WHERE id = {id}" | ❌ SQL инъекции! |
Вывод
Можно ли назвать запрос любым именем?
-
Параметры запроса — НЕТ, есть ограничения
- Начинаются с буквы или подчёркивания
- Содержат буквы, цифры, подчёркивания
- Разные БД имеют разные правила
-
Переменные в коде — ДА, но следуй PEP8
- snake_case для переменных
- Понятные имена
- Избегай однолитерных имён (кроме циклов)
-
Главное правило — НИКОГДА не форматируй 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})