• SQLAlchemy and MySQL TIMESTAMP


    列的默认值

    注意,在使用 db.create_all() 进行初始化创建表的时候,如果为 Column 指定了 default 的值,并不会影响创建的表中的对应列的默认值。这些 default 的值仅仅是在使用 SQLAlchemy 系统插入值的时候会提供默认值。如果你希望影响 MySQL 中 Column 的默认值,必须使用 server_default 来指定。

    例如要设置一个 Colmun 默认值为0 ,则需要设定 server_default=text('0') 。

    MySQL 的默认行为

     使用下面的代码创建一个默认值不为空的 TIMESTAMP Column :

    updatetime = db.Column(db.TIMESTAMP(True), nullable=False)
    

    如果对一个 TIMESTAMP Column 使用 nullable=False ,MySQL 会自动加入on update CURRENT_TIMESTAMP 。这是 MySQL 的默认行为:sysvar_explicit_defaults_for_timestamp 。 请关注下面的 updatetime Field :

    mysql> desc bonus;
    +------------+------------+------+-----+-------------------+-----------------------------+
    | Field      | Type       | Null | Key | Default           | Extra                       |
    +------------+------------+------+-----+-------------------+-----------------------------+
    | bid        | int(11)    | NO   | PRI | NULL              | auto_increment              |
    | price      | int(11)    | NO   |     | 0                 |                             |
    | share      | int(11)    | NO   |     | 0                 |                             |
    | updatetime | timestamp  | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
    | createtime | timestamp  | NO   |     | CURRENT_TIMESTAMP |                             |
    +------------+------------+------+-----+-------------------+-----------------------------+

    然而,Extra 中包含 on update CURRENT_TIMESTAMP 的 Column, 在每次更新该 Recored 的时候,updatetime 都会自动更新。

    所以,如果需要给时间戳类型加入默认值,但不在每次更新的时候自动更新时间戳,可以这样做:

    # 条目的更新时间。每次更新条目的时候,本字段会自动更新时间戳
    updatetime = db.Column(db.TIMESTAMP(True), nullable=False)
    # 条目的创建时间。每次更新条目的时候,本字段不会自动更新时间戳
    createtime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('NOW()'))
    # 或者
    createtime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('CURRENT_TIMESTAMP'))

    调整默认行为的顺序

    SqlAlchemy TIMESTAMP ‘on update’ extra 中提到 on update CURRENT_TIMESTAMP 必须是第一个 TIMESTAMP 列。对这点我并不认同,经过测试,我的结论如下:

    如果你希望通过设定非空让 MySQL 自动生成 on update CURRENT_TIMESTAMP ,则 必须 将该列作为第一个 TIMESTAMP 列。

    class Bonus(db.Model):
        __tablename__ = 'bonus'
        bid = db.Column(db.INT, primary_key=True, autoincrement=True)
        # 总充值
        price = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 总分红
        share = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 更新时间
        updatetime = db.Column(db.TIMESTAMP(True), nullable=False)
        # 创建时间
        createtime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('NOW()'))

    如果调换顺序如下:

    class Bonus(db.Model):
        __tablename__ = 'bonus'
        bid = db.Column(db.INT, primary_key=True, autoincrement=True)
        # 总充值
        price = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 总分红
        share = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 创建时间
        createtime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('NOW()'))
        # 更新时间
        updatetime = db.Column(db.TIMESTAMP(True), nullable=False)

    会报错:

    sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1067, “Invalid default value for ‘updatetime’") [SQL: ‘ CREATE TABLE bonus ( bid INTEGER NOT NULL AUTO_INCREMENT, agent BIGINT NOT NULL, master BIGINT NOT NULL, price INTEGER NOT NULL DEFAULT 0, share INTEGER NOT NULL DEFAULT 0, createtime TIMESTAMP NOT NULL DEFAULT NOW(), updatetime TIMESTAMP NOT NULL, PRIMARY KEY (bid), FOREIGN KEY(agent) REFERENCES account (gameuid), FOREIGN KEY(master) REFERENCES account (gameuid) ) ’]

    如果你一定要把 updatetime 作为第二个 timestamp 列,可以这样做:

    class Bonus(db.Model):
        __tablename__ = 'bonus'
        bid = db.Column(db.INT, primary_key=True, autoincrement=True)
        # 总充值
        price = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 总分红
        share = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 创建时间
        createtime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('NOW()'))
        # 更新时间
        updatetime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))

    效果如下:

    +------------+------------+------+-----+-------------------+-----------------------------+
    | Field      | Type       | Null | Key | Default           | Extra                       |
    +------------+------------+------+-----+-------------------+-----------------------------+
    | bid        | int(11)    | NO   | PRI | NULL              | auto_increment              |
    | agent      | bigint(20) | NO   | MUL | NULL              |                             |
    | master     | bigint(20) | NO   | MUL | NULL              |                             |
    | price      | int(11)    | NO   |     | 0                 |                             |
    | share      | int(11)    | NO   |     | 0                 |                             |
    | createtime | timestamp  | NO   |     | CURRENT_TIMESTAMP |                             |
    | updatetime | timestamp  | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
    +------------+------------+------+-----+-------------------+-----------------------------+

    使用 default

    我们也可以把默认值设置为空,然后通过 SQLAlchemy Column 提供的 default 在 python 层面自动加入默认值:

    class Bonus(db.Model):
        __tablename__ = 'bonus'
        bid = db.Column(db.INT, primary_key=True, autoincrement=True)
        # 总充值
        price = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 总分红
        share = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 创建时间
        createtime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('NOW()'))
        # 更新时间
        updatetime = db.Column(db.TIMESTAMP(True), nullable=True, default=func.utcnow())

     效果如下。在这种情况下,MySQL 中没有设定 updatetime 的默认值,但是在给 Column 赋值的时候,python 会使用 utcnow 自动为其加入默认值。这是在 SQLAlchemy 层面实现的,并不是在 MySQL 中实现的。

    +------------+------------+------+-----+-------------------+----------------+
    | Field      | Type       | Null | Key | Default           | Extra          |
    +------------+------------+------+-----+-------------------+----------------+
    | bid        | int(11)    | NO   | PRI | NULL              | auto_increment |
    | agent      | bigint(20) | NO   | MUL | NULL              |                |
    | master     | bigint(20) | NO   | MUL | NULL              |                |
    | price      | int(11)    | NO   |     | 0                 |                |
    | share      | int(11)    | NO   |     | 0                 |                |
    | createtime | timestamp  | NO   |     | CURRENT_TIMESTAMP |                |
    | updatetime | timestamp  | YES  |     | NULL              |                |
    +------------+------------+------+-----+-------------------+----------------+

    MySQL 版本的限制

    另外,很多文章提到了 使用 server_default=text('0') 作为默认值。在 MySQL5.7上,这个默认值是不可用的:

    class Bonus(db.Model):
        __tablename__ = 'bonus'
        bid = db.Column(db.INT, primary_key=True, autoincrement=True)
        # 总充值
        price = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 总分红
        share = db.Column(db.INTEGER, nullable=False, server_default=text('0'))
        # 更新时间
        updatetime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('0'))
        createtime = db.Column(db.TIMESTAMP(True), nullable=False, server_default=text('NOW()'))

    sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1067, “Invalid default value for ‘updatetime’") [SQL: ‘ CREATE TABLE bonus ( bid INTEGER NOT NULL AUTO_INCREMENT, agent BIGINT NOT NULL, master BIGINT NOT NULL, price INTEGER NOT NULL DEFAULT 0, share INTEGER NOT NULL DEFAULT 0, updatetime TIMESTAMP NOT NULL DEFAULT 0, createtime TIMESTAMP NOT NULL DEFAULT NOW(), PRIMARY KEY (bid), FOREIGN KEY(agent) REFERENCES account (gameuid), FOREIGN KEY(master) REFERENCES account (gameuid) ) ’]

  • 相关阅读:
    SQLServer中Case的用法
    SqlServer Convert 函数应用
    探讨SQL Server中Case 的不同用法
    SWF文字查询及高亮显示——第二步:实现文字查询高亮显示基本思路篇
    SWF文字查询及高亮显示——第三步:实现文字查询高亮显示及解决MovieClip帧切换时关键字无法高亮显示的问题
    我平时整理的一个生成机器码的类(转载)
    SWFTools (pdf2swf) to properly work with Flex (精彩转载)
    让Flash的swf文件在客户端不缓存(IIS配置)(强烈推荐)
    开始整SWF文字高亮显示——第一步:解析PDFToFlex源文件(修改补充版)
    解决PDFToFlex源程序的小BUG——页面控制的最后两页无法正常切换问题
  • 原文地址:https://www.cnblogs.com/wangcheng9418/p/12871255.html
Copyright © 2020-2023  润新知