angle-up arrow-clockwise arrow-counterclockwise arrow-down-up arrow-left at calendar card-list chat check envelope folder house info-circle pencil people person person-plus phone plus question-circle search tag trash x

SQLAlchemy datetime расчёты со стороны сервера

24 июня 2019 возле Peter

Почему вы должны стараться избегать расчетов со стороны клиента, если SQLAlchemy только...

post main image
Original photo unsplash.com/@nputra.

Вы найдете множество примеров SQLAlchemy datetime вычислений, например, с помощью timedelta функции Python's'. Почему? Я не понимаю этого, за исключением того, что это просто. Но правильно ли это?

Предположим, нам нужны все пользовательские записи или объекты, созданные два часа назад, и запись / определение объекта таково:

class User(Base):

    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    created_on = Column(DateTime, server_default=func.now(), index=True)
    email = Column(String(100), server_default='', index=True)

Затем, если бы мы могли использовать для выбора записей / объектов, добавленных за последние 10 минут, мы могли бы сделать что-то вроде этого:

from datetime import datetime, timedelta

now = datetime.now()
two_hours_ago = now - timedelta(hours=2)

# return all users created less then 2 hours ago
db.query(User).filter(User.created_on > two_hours_ago).all()

Генерируется:

SELECT user.id AS user_id, user.created_on AS user_created_on, user.email AS user_email
FROM user 
WHERE user.created_on > %(created_on_1)s
INFO sqlalchemy.engine.base.Engine {'created_on_1': datetime.datetime(2019, 6, 25, 7, 31, 58, 630959)}

Это только работает, дает достоверные результаты, если:

  • сервер базы данных работает на том же сервере, на котором запущен Python код.
  • сервер базы данных работает на сервере, отличном от сервера Python кода, и время на обоих серверах идеально синхронизировано.

Допустим, у вас есть отдельный сервер базы данных, и время работы этого сервера составляет 2 минуты без синхронизации. Тогда вы получаете неправильные, неполные результаты. Я пишу запросы на стороне сервера в течение многих лет и удивлен, что этому уделяется мало внимания в SQLAlchemy вопросах и ответах.

Единственный способ получить правильный результат - это использование datetime штампов записей сервера БД и добавление или вычитание из них. С MariaDB / MySQL вы можете использовать интервал заявление:

SELECT user.* FROM user WHERE created_on > (NOW() - INTERVAL 2 HOUR)

К сожалению, я не смог найти решение, SQLAlchemy которое было бы действительным для всех баз данных. SQLAlchemy имеет text() объект, он передает значение запросу. С помощью , SQLAlchemy запрос становится:

from sqlalchemy import text

two_hours_ago = text('NOW() - INTERVAL 2 HOURS')

# return all users created less then 2 hours ago
db.query(User).filter(User.created_on > two_hours_ago).all()

Генерируется:

SELECT user.id AS user_id, user.created_on AS user_created_on, user.email AS user_email
FROM user 
WHERE user.created_on > NOW() - INTERVAL 2 HOUR

Имейте в виду, что этот запрос может работать не на всех системах баз данных. Он работает с MariaDB / MySQL , но он определенно не работает с SQLite.

Если вы разрабатываете приложение и запускаете все на одном компьютере, то всегда помните, что в будущем вам может понадобиться запуск базы данных на отдельном сервере. Поэтому неплохо было бы разработать свои запросы для данной ситуации.

Ссылки / кредиты

Flask-sqlalchemy query datetime intervals
https://stackoverflow.com/questions/30495935/flask-sqlalchemy-query-datetime-intervals

SQLAlchemy datetime operations on server side
https://stackoverflow.com/questions/12540175/sqlalchemy-datetime-operations-on-server-side

SQLAlchemy default DateTime
https://stackoverflow.com/questions/13370317/sqlalchemy-default-datetime

Using DATEADD in sqlalchemy
https://stackoverflow.com/questions/15572292/using-dateadd-in-sqlalchemy/15573750#15573750

Подробнее:
SQLAlchemy

Оставить комментарий

Комментируйте анонимно или войдите в систему, чтобы прокомментировать.

Комментарии

Оставьте ответ

Ответьте анонимно или войдите в систему, чтобы ответить.