SqlAlchemy mysql 毫秒或微秒精度
SqlAlchemy mysql millisecond or microsecond precision
我一直在冒险尝试让分数时间分辨率在我的数据库中正常工作。我使用 python 方法 datetime.now()
来创建日期对象。然后我将这些对象存储在一个映射到 COLUMN(DATETIME(9))
的字段中,该字段来自 SqlAlchemy 的库。最初,我收到一条错误消息,指出我的数据被截断了。这是因为我使用的是 mysql 5.5。我已经更新到 5.6.19 并且不再收到数据截断错误。
但是,数据库实际上仍然不包含小数时间条目。例如,这是实例化 datetime.now() 对象时的值:
2015-04-17 16:31:12.804444
以上正是我所期望的。内存中的对象具有微秒分辨率。现在,将其保存到 mysql 数据库后,如果我打开 mysql 命令行客户端并使用 select 语句 return 行,我会看到以下值:
2015-04-17 16:31:13
显然,该值正在四舍五入到最接近的秒数。这很糟糕,我不知道是什么原因造成的!
如果相关,我正在使用 mysql-connector-python==2.0.3
更新:
我也尝试使用 COLUMN(DATETIME(6))
,但得到了相同的行为。
我在下面包括模型,以防信息相关:
class User(Base):
__tablename__ = 'Users'
uid = Column(INT, primary_key=True, autoincrement=True)
dateCreated = Column(DATETIME(6))
def __init__(self, *args, **kwargs):
super(user, self).__init__(*args, **kwargs)
self.dateCreated = datetime.now()
更新:
佩德罗的建议不是问题,尽管它确实帮助我取得了进步,非常感谢。我尝试逐步执行 sql 连接器中的代码,直到到达 mysql 插入语句。该语句确实包含小数时间值。但是,在执行时,该值会四舍五入。当我对 table 进行描述时,我注意到日期时间类型只是 datetime
而实际上应该是 datetime(6)
。
我正在使用 SA 模型生成数据库本身,该模型明确声明了 Column(DATETIME(6))
和 Base.metadata.create_all(self.db, checkfirst=True)
,所以我不明白为什么 (6) 没有以实际的 table 结构。我想我很快就会弄清楚,我会 post 更新。
更新:
DATETIME 的构造函数不接受字段长度规范。它只需要时区参数。我不清楚如何指定日期时间字段的长度,因为对于像 varchar 这样的类型,只需将其传递给构造函数即可。潜水继续。
根据MySQL documentation,它最多只支持6位精度(微秒):
"MySQL 5.6.4 and up expands fractional seconds support for TIME, DATETIME, and TIMESTAMP values, with up to microseconds (6 digits) precision"
我不确定,但指定 9 位数可能会将列恢复为较小的默认精度。
这似乎是 MySQLdb 的未解决问题,而不是 MySQL 或 SQLAlchemy。
http://sourceforge.net/p/mysql-python/feature-requests/24/
您可以尝试使用另一个 MySQL 驱动程序库 -- 检查 SQLAlchemy documentation 支持的选项 -- 或者您可以尝试打开问题中建议的 monkeypatch。
我遇到的问题是,股票 SqlAlchemy DATETIME class 无法满足将 (6) 值传递到构造函数以表示小数时间值的 mysql 要求。相反,需要使用 sqlalchemy.dialects.mysql.DATETIME
class。此 class 允许使用 fsp
参数(小数秒参数。)因此,列声明实际上应如下所示:
dateCreated = Column(DATETIME(fsp=6))
感谢其他回复的人。它帮助指导我的调查,最终绊倒了这个深奥且非常混乱的区别。
为了在 MySQL 中强制使用小数秒精度,同时保持其他引擎的默认值,您可以修改 SQLAlchemy 为 MySQL.[=14= 编译 DateTime
类型的方式]
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.types import DateTime
from sqlalchemy.dialects.mysql import DATETIME
@compiles(DateTime, "mysql")
def compile_datetime_mysql(type_, compiler, **kw):
return "DATETIME(6)"
它基本上是告诉 sql alchemy 只为 mysql 编译具有自定义类型的 DateTime
,在我们的例子中返回 DATETIME(6)
其中参数值为 6是 fsp(小数秒精度 [来自 MySQL 5.6.4])
我一直在冒险尝试让分数时间分辨率在我的数据库中正常工作。我使用 python 方法 datetime.now()
来创建日期对象。然后我将这些对象存储在一个映射到 COLUMN(DATETIME(9))
的字段中,该字段来自 SqlAlchemy 的库。最初,我收到一条错误消息,指出我的数据被截断了。这是因为我使用的是 mysql 5.5。我已经更新到 5.6.19 并且不再收到数据截断错误。
但是,数据库实际上仍然不包含小数时间条目。例如,这是实例化 datetime.now() 对象时的值:
2015-04-17 16:31:12.804444
以上正是我所期望的。内存中的对象具有微秒分辨率。现在,将其保存到 mysql 数据库后,如果我打开 mysql 命令行客户端并使用 select 语句 return 行,我会看到以下值:
2015-04-17 16:31:13
显然,该值正在四舍五入到最接近的秒数。这很糟糕,我不知道是什么原因造成的!
如果相关,我正在使用 mysql-connector-python==2.0.3
更新:
我也尝试使用 COLUMN(DATETIME(6))
,但得到了相同的行为。
我在下面包括模型,以防信息相关:
class User(Base):
__tablename__ = 'Users'
uid = Column(INT, primary_key=True, autoincrement=True)
dateCreated = Column(DATETIME(6))
def __init__(self, *args, **kwargs):
super(user, self).__init__(*args, **kwargs)
self.dateCreated = datetime.now()
更新:
佩德罗的建议不是问题,尽管它确实帮助我取得了进步,非常感谢。我尝试逐步执行 sql 连接器中的代码,直到到达 mysql 插入语句。该语句确实包含小数时间值。但是,在执行时,该值会四舍五入。当我对 table 进行描述时,我注意到日期时间类型只是 datetime
而实际上应该是 datetime(6)
。
我正在使用 SA 模型生成数据库本身,该模型明确声明了 Column(DATETIME(6))
和 Base.metadata.create_all(self.db, checkfirst=True)
,所以我不明白为什么 (6) 没有以实际的 table 结构。我想我很快就会弄清楚,我会 post 更新。
更新: DATETIME 的构造函数不接受字段长度规范。它只需要时区参数。我不清楚如何指定日期时间字段的长度,因为对于像 varchar 这样的类型,只需将其传递给构造函数即可。潜水继续。
根据MySQL documentation,它最多只支持6位精度(微秒):
"MySQL 5.6.4 and up expands fractional seconds support for TIME, DATETIME, and TIMESTAMP values, with up to microseconds (6 digits) precision"
我不确定,但指定 9 位数可能会将列恢复为较小的默认精度。
这似乎是 MySQLdb 的未解决问题,而不是 MySQL 或 SQLAlchemy。
http://sourceforge.net/p/mysql-python/feature-requests/24/
您可以尝试使用另一个 MySQL 驱动程序库 -- 检查 SQLAlchemy documentation 支持的选项 -- 或者您可以尝试打开问题中建议的 monkeypatch。
我遇到的问题是,股票 SqlAlchemy DATETIME class 无法满足将 (6) 值传递到构造函数以表示小数时间值的 mysql 要求。相反,需要使用 sqlalchemy.dialects.mysql.DATETIME
class。此 class 允许使用 fsp
参数(小数秒参数。)因此,列声明实际上应如下所示:
dateCreated = Column(DATETIME(fsp=6))
感谢其他回复的人。它帮助指导我的调查,最终绊倒了这个深奥且非常混乱的区别。
为了在 MySQL 中强制使用小数秒精度,同时保持其他引擎的默认值,您可以修改 SQLAlchemy 为 MySQL.[=14= 编译 DateTime
类型的方式]
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.types import DateTime
from sqlalchemy.dialects.mysql import DATETIME
@compiles(DateTime, "mysql")
def compile_datetime_mysql(type_, compiler, **kw):
return "DATETIME(6)"
它基本上是告诉 sql alchemy 只为 mysql 编译具有自定义类型的 DateTime
,在我们的例子中返回 DATETIME(6)
其中参数值为 6是 fsp(小数秒精度 [来自 MySQL 5.6.4])