Я создаю таблицу с использованием 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
?
При использовании 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)
Вы можете использовать экземпляр 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)