gpt4 book ai didi

python - SqlAlchemy TIMESTAMP 'on update' 额外

转载 作者:行者123 更新时间:2023-11-28 22:40:23 25 4
gpt4 key购买 nike

我在 python3.4.3 上使用 SqlAlchemy 来管理 MySQL 数据库。我正在创建一个表:

from datetime import datetime

from sqlalchemy import Column, text, create_engine
from sqlalchemy.types import TIMESTAMP
from sqlalchemy.dialects.mysql import BIGINT
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
class MyClass(Base):

__tablename__ = 'my_class'

id = Column(BIGINT(unsigned=True), primary_key=True)
created_at = Column(TIMESTAMP, default=datetime.utcnow, nullable=False)
updated_at = Column(TIMESTAMP, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
param1 = Column(BIGINT(unsigned=True), server_default=text('0'), nullable=False)

当我创建这个表时:

engine = create_engine('{dialect}://{user}:{password}@{host}/{name}'.format(**utils.config['db']))
Base.metadata.create_all(engine)

我得到:

mysql> describe my_class;
+----------------+---------------------+------+-----+---------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------------------+-----------------------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| param1 | bigint(20) unsigned | NO | | 0 | |

现在的问题是我不希望我的 created_at 属性上有任何 on_update 服务器默认值,它的目的实际上是只在创建记录时写入,而不是在每次更新时写入,如类声明中所述。

从我所做的几个测试中,我注意到如果我在 created_at 之前插入另一个类型为 TIMESTAMP 的属性,那么这个属性会在更新时获取 CURRENT_TIMESTAMP 额外的,而 created_at 则没有,如所希望的那样。这表明 SqlAlchemy 在映射声明中找到的第一个 TIMESTAMP 属性获得了 on update CURRENT_TIMESTAMP 额外的,尽管我没有看到这种行为的任何原因。

我也试过:

created_at = Column(TIMESTAMP, default=datetime.utcnow, server_onupdate=None, nullable=False)

created_at = Column(TIMESTAMP, default=datetime.utcnow, server_onupdate=text(''), nullable=False)

但问题依旧。有什么建议吗?

最佳答案

显然问题与 SqlAlchemy 无关,而与底层 MySQL 引擎有关。默认行为是在表中的第一个 TIMESTAMP 列上设置 on update CURRENT_TIMESTAMP

描述了此行为 here .据我所知,一个可能的解决方案是使用 --explicit_defaults_for_timestamp=FALSE 标志启动 MySQL。可以找到另一个解决方案here .我还没有尝试过任何一种解决方案,我会在解决问题后立即更新此答案。

编辑:我尝试了第二种方法,它不是很方便,但它有效。在我的例子中,我创建了一组没有 created_at 属性的表,然后我按照上面的链接中的描述更改了所有剩余的表。

类似的东西:

_no_alter = set(['tables', 'which', 'do not', 'have', 'a created_at', 'column'])
Base.metadata.create_all(engine)
for table in Base.metadata.tables.keys():
if table not in _no_alter:
engine.execute(text('ALTER TABLE {} MODIFY created_at TIMESTAMP NOT NULL DEFAULT 0'.format(table)))

EDIT2:另一种(更简单的)方法是在 SqlAlchemy 中为列设置 server_default 值:

created_at = Column(TIMESTAMP, default=datetime.utcnow, nullable=False, server_default=text('0'))

关于python - SqlAlchemy TIMESTAMP 'on update' 额外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33743379/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com