← 返回
精选科技行业动态#Datasette#LLM#SQLite#sqlite-utils#数据库迁移

sqlite-utils 4.0发布,引入数据库模式迁移功能

Simon Willison 博客(Atom)T2
03:3207/08 03:32社区阅读原文 ↗导出 MD ↓

评分

77
信息增量7 ×0.3

对于已有sqlite-utils使用经验的开发者,新功能细节有增量信息;但广为人知的背景信息较多。

内容质量9 ×0.2

文章结构清晰,包含代码示例、设计讨论和发布说明,质量高。

实用价值8 ×0.2

对使用sqlite-utils的开发者有直接实用价值,尤其是迁移和嵌套事务功能。

时效性10 ×0.15

发布于2026年7月7日,非常及时。

信源可信度10 ×0.15

作者是工具的原作者,信息可靠且权威。

基础分 85 × T2 信源权重 ×0.9 = 77

精选线 70已入选精选

精选理由

内容丰富且实用,详细介绍了迁移系统的设计思路和用法,并提供了与其他方案的比较。

AI 点评

「如果你是SQLite的深度用户,尤其是使用Datasette或LLM构建应用的开发者,这次更新绝对值得关注。迁移系统的加入让项目管理数据库模式变更变得更加安全和可追溯,而嵌套事务和复合外键的加入也填补了长期以来的功能缺口。」

速览

sqlite-utils 4.0 是该项目的第124个版本,也是自2020年3.0以来的首次大版本更新。主要新特性包括数据库模式迁移、嵌套事务(通过db.atomic()方法)和复合外键支持。迁移系统允许用户用Python文件定义一系列数据库变更,并通过命令行或Python API应用。此外还包含一些破坏性变更和CSV/TSV导入时自动检测列类型等功能。

  • 引入数据库模式迁移系统,支持定义和执行一系列数据库变更。
  • 新增嵌套事务支持,通过db.atomic()上下文管理器实现事务嵌套。
  • 添加复合外键支持,包括创建、转换和内省。
  • 包含破坏性变更,如upserts使用新的SQL语法,db.query()改为仅执行查询语句。

正文

今天早上我发布了 sqlite-utils 4.0,这是该项目的第124个版本,也是自2020年11月的 3.0 以来的首次主版本号提升。除了一些小而重要的破坏性变更(在 本升级指南 中描述)外,此版本引入了三个主要功能:数据库迁移、嵌套事务(通过新的 db.atomic() 方法)以及支持 复合外键。

使用 sqlite-utils 进行数据库模式迁移

模式迁移定义了对 SQLite 数据库进行的一系列更改,以及跟踪哪些迁移已应用并应用任何待处理迁移的机制。

迁移在 Python 文件中使用 sqlite-utils Python 库进行定义,该库包含一个强大的 table.transform() 方法,提供了 增强的 ALTER TABLE 功能,这些功能是 SQLite 的 ALTER TABLE 语句所不支持的。

(table.transform() 实现了 SQLite 文档推荐的模式——创建一个具有新模式的临时表,复制数据,然后删除旧表并将临时表重命名为原表。)

以下是一个示例迁移文件,它创建了一个名为 creatures 的表,在第二步中添加了一个额外的列,然后在第三步中更改了其中两列的类型:

from sqlite_utils import Migrations

migrations = Migrations("creatures")

@migrations()
def create_table(db):
    db["creatures"].create(
        {"id": int, "name": str, "species": str},
        pk="id",
    )

@migrations()
def add_weight(db):
    db["creatures"].add_column("weight", float)

@migrations()
def change_column_types(db):
    db["creatures"].transform(types={"species": int, "weight": str})

将其保存为 migrations.py,并在一个新数据库上像这样运行:

uvx sqlite-utils migrate data.db migrations.py

然后如果你检查该数据库的模式:

uvx sqlite-utils schema data.db

你会看到以下 SQL:

CREATE TABLE "_sqlite_migrations" (
   "id" INTEGER PRIMARY KEY,
   "migration_set" TEXT,
   "name" TEXT,
   "applied_at" TEXT
);
CREATE UNIQUE INDEX "idx__sqlite_migrations_migration_set_name"
    ON "_sqlite_migrations" ("migration_set", "name");
CREATE TABLE "creatures" (
   "id" INTEGER PRIMARY KEY,
   "name" TEXT,
   "species" INTEGER,
   "weight" TEXT
);

_sqlite_migrations 表用于跟踪哪些迁移函数已运行。上面的 creatures 表是应用所有三个迁移后的模式。

要查看迁移列表,包括待处理和已应用的,请运行以下命令:

uvx sqlite-utils migrate data.db migrations.py --list

输出:

Migrations for: creatures

  Applied:
    create_table - 2026-07-07 17:58:41.360051+00:00
    add_weight - 2026-07-07 17:58:41.360608+00:00
    change_column_types - 2026-07-07 18:01:15.802000+00:00

  Pending:
    (none)

如果你没有指定迁移文件,sqlite-utils migrate data.db 命令将扫描当前目录及其子目录,查找名为 migrations.py 的文件,并应用在其中找到的任何 Migrations() 实例。

你也可以 从 Python 代码中 使用 migrations.apply(db) 方法执行迁移,这对于构建管理自己数据库模式的工具(支持多个版本)非常有用。我自己的 LLM 工具 已经使用这种模式多年,如 llm/embeddings_migrations.py 所示。

先前工作

我最喜欢的实现仍然是 Django 的迁移,由 Andrew Godwin 基于他早期的项目 South 开发。有趣的是:Andrew、Russ Keith-Magee 和我在2008年首届 DjangoCon 上的 Schema Evolution 小组讨论 中展示了各自处理 Django 模式迁移的方法!我的尝试叫做 dmigrations,由我在伦敦 Global Radio 的团队共同开发。

Django 的迁移可以从模型定义自动生成,并包括回滚到先前版本的能力。sqlite-utils 的方法有意更简单:与 Django 不同,sqlite-utils 鼓励程序化创建表,而不是使用模型定义 ORM,因此我们没有什么可以用来自动生成迁移。

我决定跳过回滚功能,因为根据我的经验,这是一个很少使用的功能。对于 SQLite 项目,实现回滚的一种简单方法是在应用迁移之前创建数据库文件的副本!

从 sqlite-migrate 迁移

sqlite-utils 迁移的设计已经有三年的历史了——我最初将其作为名为 sqlite-migrate 的独立包发布,但从未超过 beta 版本。

我在足够多的地方使用了这个包,以至于我对这个设计很有信心,因此我决定将其提升为 sqlite-utils 的一个功能,使其默认可用于不断增长的 sqlite-utils/Datasette/LLM 生态系统中的所有其他工具。

我发布了 最后一个版本的 sqlite-migrate,它改为依赖 sqlite-utils>=4,并将 __init__.py 文件替换为以下内容:

from sqlite_utils import Migrations

__all__ = ["Migrations"]

任何依赖于 sqlite-migrate 的现有项目都应能继续工作,无需修改。

sqlite-utils 4.0 中的其他一切

以下是此版本的发布说明,附带一些内联注释:

4.0 版本包含一些轻微的不向后兼容的修复(因此主版本号升级),并引入了三个主要新功能: 数据库迁移,提供了一个结构化机制,用于随时间推移演变项目模式。(#752)

我认为迁移是标志性的新功能,因此写了这篇博客文章。

通过 db.atomic() 实现的嵌套事务支持,以及整个库中事务工作方式的诸多改进。(#755)

sqlite-utils 长期以来与数据库事务的关系一直很混乱,部分原因是我在 2018 年开始设计这个库时,对它们在 SQLite 本身中的工作方式还没有很好的感觉。

将迁移添加到核心库让我下定决心最终解决这个难题,因为事务使迁移系统更加安全和易于推理。

我最终围绕一个 db.atomic() 上下文管理器构建了它,看起来像这样:

with db.atomic():
    db.table("dogs").insert({"id": 1, "name": "Cleo"}, pk="id")
    db.table("dogs").insert({"id": 2, "name": "Pancakes"})

SQLite 支持 保存点,因此 db.atomic() 可以嵌套执行事务中的事务。这非常棒!

支持复合外键,包括通过 table.foreign_keys 创建、转换和内省。(#594)

这源于我让一个编码代理审查所有未解决的问题和 PR,找出应包含在 4.0 版本中的内容,因为如果以后添加它们将代表破坏性变更,它正确地识别出复合外键正是这类功能。

我从对 table.foreign_keys 内省方法做了一个破坏性变更开始,然后决定看看 Claude Fable 5 是否能处理将复合外键 创建 集成到库中的更繁琐工作。它帮助创建的 API 设计感觉 完全正确——与库的其他部分已经工作的方式一致。

其他值得注意的变化包括: Upserts 现在使用 SQLite 的 INSERT ... ON CONFLICT ... DO UPDATE SET 语法,自动检测现有表的主键,并拒绝缺少所需主键值的记录。(#652)

这是第一个促使我考虑进行破坏性变更 4.0 版本升级的变化。我构建这个是为了帮助支持 sqlite-chronicle,它使用触发器来跟踪表中已插入、更新或删除的行。

db.query() 现在立即执行,并拒绝不返回行的语句;对于写入和 DDL,请使用 db.execute()。

可能是 最具破坏性的破坏性变更——我不得不更新自己代码中的几个地方,将 db.query() 切换为 db.execute()。

CSV和TSV导入现在默认检测列类型,而插入到现有表时会保留这些表的列类型。(#679)

sqlite-utils insert data.db creatures creatures.csv --detect-types 标志是后来添加的,用于根据CSV中的数据自动检测列类型(text, integer, real)。它本应是默认行为,而发布4.0意味着我可以做到这一点。

table.extract() 和 extracts= 不再为全空值创建查找表记录。(#186)

此版本解决的最早问题——底层bug(由我)于2020年10月提交。

详见《从3.x升级到4.0》了解向后不兼容的变更。 4.0预发布周期中提供的功能和修复的详细发布说明可在4.0a0、4.0a1、4.0rc1、4.0rc2、4.0rc3和4.0rc4中找到。

升级指南完全由Claude Fable 5、Claude Opus 4.8和GPT-5.5撰写。发布说明也是如此。

这类文档是我逐渐放心外包给机器人的。它不需要说服任何人任何事情,也不需要表达任何观点——它的任务是尽可能准确和详细。我已经仔细审阅了发布说明,可以确认它们准确且全面。

Claude Fable 5帮了大忙

我在一年多前发布了sqlite-utils 4.0的第一个alpha版本。我一直在拖延稳定版发布,因为需要做大量工作来追踪和清理许多其他小的设计缺陷,而主要版本号允许我承担这些工作。

Claude Fable 5(以及较小程度上的Opus 4.8和GPT-5.5)的帮助给了我所需的推动力,让我克服惰性,充分利用我可以投入这个库的时间。

Fable在API设计上具有非常好的品味,而且如果你给它一个更开放的目标,它会不懈地主动。我最成功的提示词是一个审查任务,我针对我认为的最后一个候选版本发布了该任务:

审查自上次标记的3.x版本以来主分支上的变更——我即将将它们作为sqlite-utils 4.0发布,这是一个稳定版本,承诺在很长一段时间内不会有向后不兼容的修复。 审查变更日志和升级指南,并编写临时代码脚本以尝试v4中的所有新功能——保存这些脚本但不要提交它们

我在Codex Desktop中用GPT-5.5 xhigh尝试了这一点,并在Claude Code中使用了Fable 5。

GPT-5.5 编写了5个Python脚本,但没有发现什么特别有趣的东西——其最终报告在此。

Fable 5 编写了12个脚本,识别出4个发布阻塞问题和10个额外问题在其报告中,并构建了一个简洁的组合重现脚本,运行时输出以下内容:

=== 1. Failed db.execute() write leaves an implicit transaction open ===
  in_transaction after failed write: True
  BUG: table 'other' silently lost when connection closed

=== 2. Leading ';' bypasses the query() first-token scanner ===
  BUG: raised OperationalError: no such savepoint: sqlite_utils_query
  BUG: row persisted despite rollback (count=1)

=== 3. Rejected write PRAGMA via query() still takes effect ===
  BUG: user_version=5 after 'rejected' statement (docs say no effect)

=== 4. Implicit compound FK resolves pk columns in table order, not PK order ===
  BUG: other_columns reported as ('b', 'a'), should be ('a', 'b')
  BUG: transform of valid data raised IntegrityError: FOREIGN KEY constraint failed

=== 5. ForeignKey (now a dataclass) is no longer hashable ===
  BUG: cannot use 'sqlite_utils.db.ForeignKey' as a set element (unhashable type: 'ForeignKey')

=== 6. Mixed ForeignKey objects and tuples in foreign_keys= rejected ===
  BUG: foreign_keys= should be a list of tuples

=== 7. insert --csv into an EXISTING table transforms its column types ===
  BUG: existing zip '01234' is now 1234 (column type: int)

=== 8. insert(pk=, alter=True) regression: InvalidColumns before alter runs ===
  BUG: InvalidColumns: Invalid primary key column ['id'] for table t with columns ['a']

=== 9. migrate --stop-before an already-applied migration applies everything ===
  BUG: m2 was applied despite --stop-before m1 (m1 already applied)

=== 10. ensure_autocommit_on() silently commits an open transaction ===
  BUG: row survived rollback (count=1) - transaction was committed

我发现自己同意几乎所有的建议。这是包含16个提交的PR,我们逐一解决了这些问题。

我毫不怀疑,sqlite-utils 4.0 的质量远高于我在没有最新前沿模型帮助的情况下所能构建的版本。

Tags: schema-migrations, projects, sqlite, ai, sqlite-utils, annotated-release-notes, generative-ai, llms, ai-assisted-programming, anthropic, claude, agentic-engineering, claude-mythos-fable

相关条目

89

五维评分

信息增量9 ×0.3

基于真实用户行为数据的研究成果,提供了关于AI如何改变工作内容的新定量证据。

内容质量8 ×0.2

结构清晰,关键发现明确,但可进一步深入细分行业差异。

实用价值8 ×0.2

为企业管理层、HR和组织设计者提供了直接可参考的数据洞察。

时效性10 ×0.15

研究刚于近日发布,紧贴当前AI应用热潮。

信源可信度10 ×0.15

来源为OpenAI官方研究,数据可靠且权威。

基础分 89 × T1 信源权重 ×1 = 89

精选线 60已入选精选

11:30OpenAI:News(RSS)T1RSS

精选OpenAI研究:AI正在重新定义工作边界

如果你关心AI对实际工作的影响,这篇研究不容错过。它不讨论理论,而是用数据展示ChatGPT用户如何使用AI扩展自己的任务范围,这对HR、管理者以及每个希望提升技能的职场人都有直接启发。

AI行业#ChatGPT#OpenAI#劳动力市场影响
87

五维评分

信息增量8 ×0.3

提供了来自 AI 原生企业内部 CFO 的一手经验,信息增量较高。

内容质量9 ×0.2

内容结构清晰,来自权威高管,质量上乘。

实用价值8 ×0.2

为财务高管提供了可落地的经验与注意事项,实用价值强。

时效性9 ×0.15

刚发布的官方内容,时效性高。

信源可信度10 ×0.15

信源为 OpenAI 官方博客,可靠性极高。

基础分 86.5 × T1 信源权重 ×1 = 87

精选线 60已入选精选

01:00OpenAI:News(RSS)T1RSS

精选OpenAI CFO 分享构建 AI 原生财务职能的五大经验

作为编辑,我认为这篇文章的价值在于它来自 AI 领军企业的财务一把手,而非外部咨询机构,因此更具实践参考性。推荐给财务数字化负责人、CFO 以及对 AI 转型感兴趣的从业者阅读。

金融行业#AI原生财务#AI投资回报率#OpenAI
87

五维评分

信息增量8 ×0.3

首次系统性报告智能体AI在科学计算中的具体应用案例,信息增量较高。

内容质量9 ×0.2

来自权威机构OpenAI,内容结构清晰,案例详实,质量上乘。

实用价值8 ×0.2

为科研人员和决策者提供了可操作的参考和路线图,实用价值显著。

时效性9 ×0.15

报告发布日期为近期,紧贴AI agent热门趋势,时效性强。

信源可信度10 ×0.15

OpenAI作为AI领域头部机构,其官方报告可信度极高。

基础分 86.5 × T1 信源权重 ×1 = 87

精选线 60已入选精选

01:00OpenAI:News(RSS)T1RSS

精选智能体AI时代下的科学计算:OpenAI发布新领域报告

这份报告是当前AI agent热潮中最务实的应用分析之一,尤其适合计算生物学和药物研发领域的从业者阅读。它回答了“AI agent除了写代码还能干什么”这个关键问题,直接展示了在复杂科学计算中的生产力提升。

AI行业#AI编码智能体#OpenAI#基因组学
87

五维评分

信息增量8 ×0.3

语音人类自然度评估标准新工具,信息增量高,此前缺乏同类开源基准。

内容质量9 ×0.2

内容详实,技术细节清晰,附带使用说明与开源代码,质量高。

实用价值9 ×0.2

直接可用于模型开发与对比,实用价值极高,尤其对语音相关团队。

时效性8 ×0.15

语音AI快速发展期,评测需求强烈,发布时机恰逢其时。

信源可信度10 ×0.15

Hugging Face官方博客,权威信源,工具已开源可验证。

基础分 87 × T1 信源权重 ×1 = 87

精选线 60已入选精选

08:00Hugging Face:Blog(RSS)T1RSS

精选Real World VoiceEQ:量化语音AI的人类自然度

值得关注的是,这个基准真正聚焦'人类自然度'这个软指标,而不是传统的语音识别率或MOS评分。对从事语音合成、语音克隆或语音交互的团队来说,这是一个非常实用的参考工具,可以快速定位模型在情感、韵律等层面上的不足。不过目前支持语言有限,期待后续扩展。

科技行业#Hugging Face#Real World VoiceEQ#自然度评估
85

五维评分

信息增量8 ×0.3

提出新颖的AI ROI量化框架,对当前缺乏标准化评估方法的企业具有较高的信息增量。

内容质量7 ×0.2

框架逻辑清晰,但缺乏具体案例或数据支撑,偏概念性介绍。

实用价值9 ×0.2

直接面向企业实际痛点,可操作性强,对投资决策有明确指导意义。

时效性10 ×0.15

在当前AI投资泡沫与理性化需求背景下,该内容极其及时。

信源可信度9 ×0.15

来自OpenAI官方渠道,由CFO署名,权威性高。

基础分 84.5 × T1 信源权重 ×1 = 85

精选线 60已入选精选

18:00OpenAI:News(RSS)T1RSS

精选OpenAI 推出AI时代记分卡:衡量投资回报的新方法

这篇博文直击当前AI行业的软肋——如何量化投入产出。对于正在或计划大规模部署AI的企业决策者而言,它能帮助避免盲目跟风。我个人建议结合自身业务场景尝试定义“有用工作”,避免指标设计流于形式。

科技行业#AI记分卡#AI部署策略#OpenAI
85

五维评分

信息增量8 ×0.3

提出了新颖的'每美元有用功'指标,对AI投资评估有较高信息增量。

内容质量7 ×0.2

逻辑清晰、结构完整,但缺少实际案例分析,略偏抽象。

实用价值9 ×0.2

为企业提供了可落地的衡量框架与治理建议,实用性强。

时效性9 ×0.15

发表于代理时代兴起之际,贴合当前企业AI投资焦虑点。

信源可信度10 ×0.15

来源为OpenAI官方博客,权威性高。

基础分 84.5 × T1 信源权重 ×1 = 85

精选线 60已入选精选

18:00OpenAI:News(RSS)T1RSS

精选代理时代如何管理AI投资:聚焦每美元有用功与高价值工作流

这篇文章对正在大规模部署AI代理的企业尤为重要。它提醒我们:单纯盯着API价格下降会陷入误区,真正要管理的是每单位工作的投资回报率。建议CTO和CFO联合阅读,并在内部建立量化评估机制。

AI行业#AI代理#OpenAI#ROI
85

五维评分

信息增量8 ×0.3

提出组织延迟这一概念,对AI落地实践有增量启发。

内容质量8 ×0.2

观点明确,逻辑清晰,引用权威信源。

实用价值9 ×0.2

对企业和组织管理者具有直接指导意义。

时效性8 ×0.15

当前AI快速迭代期,组织滞后问题紧迫。

信源可信度10 ×0.15

来源为OpenAI官方新闻,权威性高。

基础分 85 × T1 信源权重 ×1 = 85

精选线 60已入选精选

20:00OpenAI:News(RSS)T1RSS

精选设计能跟上AI的组织:组织延迟成为最大障碍

这篇文章真正值得关注的是提出了一个被忽视的瓶颈:技术再强,组织跟不上也是白搭。对CTO、CIO和转型负责人来说,这是比技术选型更重要的思考框架。

AI行业#AI#OpenAI#组织变革
84

五维评分

信息增量9 ×0.3

本文披露 Ruff 默认规则的大幅扩展及具体迁移方法,对 Python 开发者有较高信息增量

内容质量9 ×0.2

结构清晰,包含具体统计数据、命令示例和 AI 集成案例,质量上乘

实用价值10 ×0.2

提供了可立即执行的一行命令和修复策略,对真实开发场景有直接帮助

时效性10 ×0.15

文章发布于版本发布后两天,非常及时

信源可信度9 ×0.15

来自知名技术博主 Simon Willison,长期维护多个 Python 项目,信源可靠

基础分 93.5 × T2 信源权重 ×0.9 = 84

精选线 70已入选精选

06:44Simon Willison 博客(Atom)T2社区

精选Ruff v0.16.0 发布:默认规则从59条激增至413条,CI工作流需关注

对于 Python 开发者来说,这是一个不容错过的更新信号。Ruff 的默认规则大幅增加意味着我们不能再忽视代码中潜在的问题,而 AI 修复工具正好可以降低升级成本。尤其值得关注的是 Astral(OpenAI)正在将 AI 编码能力与静态分析工具深度整合,这可能是未来工程实践的常态。

科技产品#Astral#CI/CD#OpenAI

引用前请核对原文