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

На каком уровне выполняется default?

2.0 Middle🔥 181 комментариев

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

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

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

На каком уровне выполняется DEFAULT

Вопрос о уровне выполнения DEFAULT касается баз данных, а конкретно — когда вычисляется значение по умолчанию для колонки. Это критически важно понимать при проектировании схемы и написании приложений.

DEFAULT на уровне БД

DEFAULT выполняется на уровне базы данных, когда вы вставляете запись без указания значения для колонки с DEFAULT.

# Модель SQLAlchemy
from sqlalchemy import Column, Integer, String, DateTime
from datetime import datetime

class User(Base):
    __tablename__ = "users"
    
    id = Column(Integer, primary_key=True)
    name = Column(String(100))
    # DEFAULT выполнится на уровне БД
    created_at = Column(DateTime, default=datetime.utcnow)
    status = Column(String(20), default="active")

Есть различие между default в SQLAlchemy и server_default в миграциях.

default (клиентский уровень)

Это Python-функция, которая вызывается на уровне приложения:

# Выполняется в Python приложении
from datetime import datetime

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True)
    created_at = Column(DateTime, default=datetime.utcnow)

Когда вы создаёте объект без created_at, SQLAlchemy вызовет datetime.utcnow() перед вставкой.

server_default (серверный уровень)

Это SQL-выражение, которое выполняется на уровне БД:

# Выполняется в самой БД
class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True)
    # server_default — SQL выражение
    created_at = Column(DateTime, server_default="CURRENT_TIMESTAMP")
    status = Column(String(20), server_default="active")

Миграция Goose:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    status VARCHAR(20) DEFAULT active
);

Практическое различие

Клиентский default:

  • Вычисляется в Python перед отправкой запроса в БД
  • Полезен для генерации UUID, вызова функций
  • Не срабатывает при прямых SQL INSERT запросах

Серверный server_default:

  • Вычисляется непосредственно БД
  • Гарантирует значение даже при прямых SQL запросах
  • Работает быстрее для простых операций

Пример с обоими вариантами

from datetime import datetime, timezone
from uuid import uuid4

class Post(Base):
    __tablename__ = "posts"
    
    # ID генерируется в Python (нет server_default)
    id = Column(String(36), primary_key=True, default=lambda: str(uuid4()))
    
    # Время создания вычисляется в БД (гарантирует точность)
    created_at = Column(DateTime(timezone=True), server_default="CURRENT_TIMESTAMP")
    
    # Статус — простое значение из БД
    status = Column(String(20), server_default="draft")
    
    # Счётчик обновлений в Python
    version = Column(Integer, default=1)

Рекомендации

  • Используйте server_default для временных меток (CURRENT_TIMESTAMP)
  • Используйте default в Python для UUID, вычислений, функций
  • Будьте осторожны с datetime.utcnow() — это вычисляется в момент определения класса, а не при создании объекта. Используйте лямбду или функцию
  • Для критичных данных используйте оба: Python поддержит, БД гарантирует
  • При прямых SQL запросах полагайтесь только на server_default

Понимание этого различия критично для избежания ошибок в работе с временными метками и статусами записей.