旁注

用 SQLite 记了一年账

技术约 300 字

去年八月开始用 SQLite 记账,到现在正好一年。之前试过几个记账 App,要么广告多,要么导出麻烦,最后还是回到一个文件、一张表。

表结构

CREATE TABLE txn (
  id       INTEGER PRIMARY KEY,
  day      TEXT NOT NULL,      -- 'YYYY-MM-DD'
  amount   INTEGER NOT NULL,   -- 单位:分,支出为负
  account  TEXT NOT NULL,
  category TEXT NOT NULL,
  memo     TEXT
);
CREATE INDEX txn_day ON txn(day);

有两个决定后来证明是对的:

  • 金额用整数存“分”。浮点数加减几百次之后迟早会冒出一分钱的误差,对账时非常烦人。
  • 日期存成 ISO 格式的文本。SQLite 没有真正的日期类型,但 YYYY-MM-DD 这样的字符串可以直接比较、排序,也能交给日期函数处理。

常用的几条查询

按月汇总支出:

SELECT strftime('%Y-%m', day) AS month,
       -SUM(amount) / 100.0   AS spent
FROM txn
WHERE amount < 0
GROUP BY month
ORDER BY month;

某个分类最近三个月的明细:

SELECT day, amount / 100.0, memo
FROM txn
WHERE category = '餐饮'
  AND day >= date('now', 'start of month', '-2 months')
ORDER BY day DESC;

各账户余额(每个账户的期初余额也记成一笔收入):

SELECT account, SUM(amount) / 100.0 AS balance
FROM txn
GROUP BY account;

一年下来

能坚持下来,关键是录入要足够省事。我写了个很短的命令行函数,敲 t 35.5 餐饮 午饭 一行就记一笔,账户默认填最常用的那个。每周日晚上花十分钟,对着账单核一遍。

数据本身倒没带来什么惊人的发现,无非是外卖比想象中多,书买得比读得快。但每个月看一眼汇总,花钱的时候心里有个数。

备份方式很朴素:每周把数据库文件复制一份到移动硬盘。一整年的账本也才几百 KB。