我正在尝试用 python + sqlite3 替换我对 SAS 的使用;我正在尝试将我的数据从 SAS 数据集移动到 SQLite 数据库。我有许多时间字段在 python 中正确表示为 datetime.time 对象。由于 SQLite 是“轻型”的,我正在寻找有关使用什么格式在列中存储时间的建议。 (我知道我必须编写 python 适配器等来从列读取和写入对象。)这些是我需要考虑的功能:
- SQLite 处理查询中列的能力。 (例如,我能否选出出现在两次之间的行?)
- field 的大小。 (我的表通常有数亿行。)
- 人类可读性。 (我正在考虑将时间存储为整数:自午夜以来的微秒数。但这会使观察数据变得更加困难。)
有没有人满意地解决了这个问题?
最佳答案
有一个通用方法可以将任何可序列化的 Python 对象存储在 sqlite 表中。
- 使用
sqlite3.register_adapter
注册一个转换函数 将 Python 对象转换为 int、long、float、str(UTF-8 编码)、unicode 或 buffer。 - 使用
sqlite3.register_converter
注册一个函数 将文本转换为 Python 对象。输入始终是文本,因为 internally, sqlite stores everything as text.
以下是 datetime.time 对象的代码:
import sqlite3
import datetime as DT
def adapt_timeobj(timeobj):
return ((3600*timeobj.hour + 60*timeobj.minute + timeobj.second)*10**6
+ timeobj.microsecond)
def convert_timeobj(val):
val = int(val)
hour, val = divmod(val, 3600*10**6)
minute, val = divmod(val, 60*10**6)
second, val = divmod(val, 10**6)
microsecond = int(val)
return DT.time(hour, minute, second, microsecond)
# Converts DT.time to TEXT when inserting
sqlite3.register_adapter(DT.time, adapt_timeobj)
# Converts TEXT to DT.time when selecting
sqlite3.register_converter("timeobj", convert_timeobj)
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.cursor()
# declare timecol to be of type timeobj
cur.execute("create table test (timecol timeobj)")
cur.executemany("insert into test (timecol) values (?)",
[(DT.time(1,2,3,4), ), (DT.time(5,6,7,8),) ])
您可以在 SQL 中使用不等式,但请注意,比较的值是由 adapt_timeobj
返回的值,不是 datetime.time
对象。幸运的是,如果 adapt_timeobj
函数返回的整数可以按照与相应的 datetime.time
对象相同的顺序排序(如上所示),那么 SQL 中的不等式将起作用随心所欲。
cur.execute("select timecol from test where timecol < ?",
[DT.time(4,5,6)])
print(cur.fetchall())
# [(datetime.time(1, 2, 3, 4),)]
cur.execute("select timecol from test where timecol < ?",
[DT.time(8,0,0)])
print(cur.fetchall())
# [(datetime.time(1, 2, 3, 4),), (datetime.time(5, 6, 7, 8),)]
con.commit()
cur.close()
con.close()
注意:如果您查看编辑历史记录,您会看到 adapt_timeobj
和 convert_timeobj
的更简单替代方案,它将数据存储为 str
而不是 int
。它更简单,但将数据存储为 int
速度更快且内存效率更高。
关于python - 将 python datetime.time 存储在 sqlite3 列中的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27640857/