【问题标题】:mysql and python datetimemysql和python日期时间
【发布时间】:2013-04-04 21:21:54
【问题描述】:

我正在尝试使用sqlalchemy 包通过python 将记录插入mysql 数据库。

我在 mysql 中有 datetime 类型的列,这些列已经通过加载表内联命令接受了以下格式的数据:

'2013-04-03 00:05:00-05:00'

注意这是由 python 中的pytz 模块生成的。使用load table inline <file_name> 命令通过mysql 控制台加载具有完全相同格式的日期时间戳的600,000 行没有问题。 MySql 在加载时接受它们,但我不确定它是否维护时区信息。这对我来说真的没关系,因为我还有 3 个其他列,它们代表我感兴趣的其他时区的日期时间。所以我知道哪一列代表 EST/EDT 或 CST/CDT,如果我愿意,我可以根据它进行查询.我不会在 mysql 中进行任何时区转换,因为我已经有代表感兴趣时区的列。

这是按照mysql的文档:

The DATETIME type is used for values that contain both date and time parts. MySQL
retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format. The supported
range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'. 

问题是pytz 模块在我尝试插入的日期时间戳中提供有关时区的信息。我实际上有 4 列(EST, UTC, EST/EDT and CST/CDT),所以它们的时区信息都嵌入在日期时间戳中。

注意我没有使用自定义 INSERT 查询。这是 sqlalchemy 执行多次插入的默认方式:

执行插入的函数如下所示:

def insert_data(data_2_insert, table_name):
    # Connect to database using SQLAlchemy's create_engine()
    engine = create_engine('mysql://blah:blah@localhost/db_name')
    # Metadata is a Table catalog. 
    metadata = MetaData()
    my_table = Table(table_name, metadata, autoload=True, autoload_with=engine)
    column_names = tuple(c.name for c in my_table.c)
    final_data = [dict(zip(column_names, x)) for x in data_2_insert]
    ins = my_table.insert()
    conn = engine.connect()
    conn.execute(ins, final_data)
    conn.close()

错误信息:

   Traceback (most recent call last):
      File "script.py", line 191, in <module>
        main()
      File "script.py", line 39, in main
        insert_data(file_csv, table_name)
      File "script.py", line 58, in insert_data
        conn.execute(ins, final_data)
      File "/usr/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 824, in execute
        return Connection.executors[c](self, object, multiparams, params)
      File "/usr/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 874, in _execute_clauseelement
        return self.__execute_context(context)
      File "/usr/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 894, in __execute_context
        self._cursor_executemany(context.cursor, context.statement, context.parameters, context=context)
      File "/usr/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 960, in _cursor_executemany
        self._handle_dbapi_exception(e, statement, parameters, cursor, context)
      File "/usr/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 931, in _handle_dbapi_exception
        raise exc.DBAPIError.instance(statement, parameters, e, connection_invalidated=is_disconnect)
    sqlalchemy.exc.OperationalError: (OperationalError) (1292, "Incorrect datetime value: '2013-04-03 00:05:00-05:00' for column 'rtc_date_est' at row 1")

【问题讨论】:

  • 最后一部分似乎坏了:2013-04-03 00:05:00-05:00,那里不应该有-05:00,对吧?我想 sqlalchemy 在这种情况下不会做太多类型检查。
  • 最初,我的数据在EST。但我需要在其他两个时区(EST/EDT and CST/CDT)。我不想每次需要运行日期查询时都在 sql 中执行对话,因为我会经常这样做。因此,它是存储与性能的权衡。因此,在 python 中,我获取日期时间字符串,通过pytz.timezone('EST') 将其分配给 EST 时区,然后执行 3 次转换 - 到 'US/Eastern''US/Central'utc。所以'-05:00' 是为了表明它是EST。同样,+00:00UTC-04:00EST/EDT-05:00CST/CDT
  • 我尝试插入 mysql 的对象中存在“-05:00”扩展名。注意,mysql 不会抱怨这一点,因为我是通过加载表成功的。所以这是 sqlalchemy 的一个问题。我如何在不重新编写方法的情况下实现我的目标。感谢您的帮助。
  • 也许我应该放弃sqlalchemy,直接通过mysqldb包与mysql通信?
  • 无需放弃 sqlalchemy,但您必须告诉它您要使用时间戳:docs.sqlalchemy.org/en/rel_0_8/core/… 另外,我无法从堆栈跟踪中看到它,但是您要插入的内容,实际上是一个日期时间对象还是一个字符串?

标签: python mysql insert sqlalchemy


【解决方案1】:

SQLAlchemy 似乎不遵守 MySQL DATETIME 格式。 SQLAlchemy 正在尝试将时区感知格式放入 MySQL DATETIME 中,该格式不支持基于每行的时区 AFAIK。

解决方案是从您的日期时间对象中删除时区信息。将它们转换为与 MySQL 默认值(UTC、EST 等)匹配的时区后,执行以下操作:

date_value = date_value.replace(tzinfo=None)

其中 date_value 是最终传递给 SQLAlchemy 对象的日期时间对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-03
    • 2013-06-16
    • 2015-05-29
    • 2013-06-30
    • 2012-04-28
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多