我有一个用于记录数据输入/输出的表:
CREATE TABLE io(iodate DATE, xt INTEGER, rv INTEGER)
它旨在按日期存储总传输数据。
要更新它,我使用了一堆查询(混合了伪代码和SQL):
SELECT * FROM io WHERE iodate=<today>
if no result:
INSERT INTO io(iodate, xt, rv) VALUES (...)
else:
UPDATE io SET rv+=<new_rv> xt+=<new_xt> WHERE iodate=<today>
我相信有更方便的方法来实现这一目标。有什么想法吗?
答案 0 :(得分:1)
假设iodate
列上的主键您可以使用INSERT OR REPLACE
,就像@Martijn_Pieters所说,但您可以通过2种方式执行此操作:
首先是查询当前数据,就像你一样,然后&#34;插入或替换&#34;:
SELECT * FROM io WHERE iodate = ?;
...
INSERT OR REPLACE INTO io VALUES (?, ?, ?);
要插入的参数应已包含xt
和rv
的当前值和新值的总和。
第二是在一个查询中执行所有操作,但无论如何选择都已完成,只是它在子查询中:
INSERT OR REPLACE INTO io
select iodate, xt + ?, rv + ? from (
SELECT iodate, xt, rv
FROM io
WHERE iodate = ?
union all
select ? as iodate, 0 as xt, 0 as rv
) limit 1;
第二个解决方案的主要缺点是您必须重复iodate
两次,因此参数应按以下顺序传递:<new_xt>, <new_rv>, <iodate>, <iodate>
,尽管它不会影响性能。
好处是它总是一个查询,无论该行是否已经在表中。
很难说哪一个更快。你必须自己测量它。
您还可以考虑使用SQLite的日期和时间功能,这样您就不必每次都通过iodate
。我怀疑您的应用程序将始终传递iodate
的当前数据,在这种情况下,您可以使用now()
函数iodate
或任何其他相关函数,因此它符合您的日期格式。请参阅有关可用日期和时间函数的SQLite文档。
答案 1 :(得分:0)
我担心Python sqlite3中没有你想要的快捷方式。您可以查看sqlite3 here的说明。
我建议你写这样的代码。 (与使用伪代码时一样。)
...
def findData():
SELECT * FROM io WHERE iodate=<today>
def updateData():
update operation
def insertData():
insert operation
[updateData() if findData() else insertData()]
...
由于更新/查找/插入是处理数据库时最常用的操作,因此将它们打包到函数中将是一个很好的解决方案。