SQLAlchemy / Pandas: невозможно вставить время по умолчанию в MySQL

0

Я создаю таблицу с использованием sqlalchemy, и я хочу установить временную метку по умолчанию в mysql, но она не может вставляться в mysql, мой код:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, Float, ForeignKey,TIMESTAMP

Base = declarative_base()
DBSession = sessionmaker(bind=engine)
session = DBSession()

class Book(Base):
    __tablename__ = 'book'
    bid = Column(Integer, primary_key=True)
    bname = Column(String(20))
    price = Column(Integer)

    student_id = Column(Integer, ForeignKey(Student.id))

    student = relationship(Student)
    insert_time = Column(TIMESTAMP(timezone=False),
                         default=datetime.datetime.now())

Base.metadata.create_all(engine)
books = pd.DataFrame({"bname": ['a','b','c','d'],
                      "price":[128,22,67,190],
                      'student_id':[1,1,3,2]})
books.to_sql('book',engine,if_exists='append',index=False)

посмотрите на таблицу insert_time поле insert_time равно null, а не datetime, как я с этим insert_time?

Теги:
pandas
sqlalchemy

2 ответа

2
Лучший ответ

При использовании SQLAlchemy вы должны стремиться понять, что происходит на Python и что в базе данных. Здесь вы определили значение по умолчанию для insert_time используя аргумент по default, по сравнению с использованием server_default, поэтому значение по умолчанию добавляется к значениям в Python, если не указано значение для столбца, и только если вы используете либо указанную модель или базовой Table.

Если вы создали таблицу на основе модели, которую вы указали, то значение по умолчанию для сервера отсутствует, а столбец имеет значение NULL. Это важно, потому что Pandas делает объемную вставку, используя свои собственные метаданные, поэтому она не знает о вашей по умолчанию стороне Python.

В MySQL - в зависимости от версии и флагов - столбец типа TIMESTAMP неявно NOT NULL отличие от любого другого типа, а первый столбец временной метки имеет значение по умолчанию для сервера CURRENT_TIMESTAMP, но SQLAlchemy явно выдает спецификатор NULL если nullable=False не указано, чтобы поведение соответствовало другим СУБД.

Наконец, вы, скорее всего, хотели передать функцию datetime.datetime.now по умолчанию, а не экземпляр datetime который вы получаете при построении класса при вызове функции:

    insert_time = Column(TIMESTAMP(timezone=False),
                         default=datetime.datetime.now)  # Don't call it, pass it

Вы также должны явно указать значение по умолчанию для сервера, если используете Pandas, как вы показали:

    # Having 'default' as well is a bit redundant.
    insert_time = Column(TIMESTAMP(timezone=False),
                         default=datetime.datetime.now,
                         server_default=text('CURRENT_TIMESTAMP'),
                         nullable=False)
2

Вы можете использовать экземпляр Datetime для TIMESTAMP

import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, Float, ForeignKey,DateTime

Base = declarative_base()
DBSession = sessionmaker(bind=engine)
session = DBSession()

class Book(Base):
    __tablename__ = 'book'
    bid = Column(Integer, primary_key=True)
    bname = Column(String(20))
    price = Column(Integer)

    student_id = Column(Integer, ForeignKey(Student.id))

    student = relationship(Student)
    insert_time = Column(Datetime,
                         default=datetime.datetime.now())

Base.metadata.create_all(engine)
books = pd.DataFrame({"bname": ['a','b','c','d'],
                      "price":[128,22,67,190],
                      'student_id':[1,1,3,2]})
books.to_sql('book',engine,if_exists='append',index=False)
  • 0
    Тем не менее, столбец все еще может иметь значение NULL, а (статический) по умолчанию не используется в пандах.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню