SQLite 中使用 RETURNING 子句获取插入行的 ID 和数据

sqlite 不支持 sql server 风格的 `output` 子句,但自 3.35.0 版本起原生支持标准 sql 的 `returning` 子句,可直接在 `insert` 后返回新插入行的指定字段(包括自增主键),完美替代 `output inserted.*`。

SQLite 是轻量级嵌入式数据库,其语法与 PostgreSQL/SQL Server 等有明显差异。你遇到的 SQLITE_ERROR: near "OUTPUT": syntax error 错误,根本原因是 OUTPUT 是 SQL Server 专有语法,SQLite 完全不识别。幸运的是,SQLite 从 3.35.0 版本(2025 年 3 月发布)开始正式支持 RETURNING 子句,它功能等效且更符合 SQL 标准。

✅ 正确写法(推荐):

INSERT INTO articles(
  creation_date, publish_date, last_modified_date,
  title, subtitle, article_text, likes, author_id, published
)
VALUES (
  CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP,
  ?, ?, ?, ?, ?, ?
)
RETURNING *;

⚠️ 注意事项:

  • RETURNING 必须紧跟在 VALUES(或 SELECT)子句之后,不能加逗号或分号隔开
  • RETURNING * 返回整行(含自增 rowid 或显式定义的 INTEGER PRIMARY KEY 字段),也可指定列,如 RETURNING id, title, created_at;
  • Node.js 中需确保使用的 SQLite 驱动(如 sqlite3)底层链接的是 ≥3.35.0 的 SQLite 库(可通过 sqlite3 --version 或 db.get('SELECT sqlite_version()') 验证);
  • 若使用较旧版本 SQLite(

? 进阶优化:简化时间戳逻辑
与其每次 INSERT 都显式传入 CURRENT_TIMESTAMP,不如在建表时设置默认值,既提升可读性,又避免应用层出错:

CREATE TABLE articles (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT NOT NULL,
  subtitle TEXT,
  article_text TEXT,
  likes INTEGER DEFAULT 0,
  author_id INTEGE

R, published BOOLEAN DEFAULT FALSE, creation_date TEXT DEFAULT CURRENT_TIMESTAMP, publish_date TEXT DEFAULT CURRENT_TIMESTAMP, last_modified_date TEXT DEFAULT CURRENT_TIMESTAMP );

随后插入语句可大幅精简,且 RETURNING 仍生效:

INSERT INTO articles(title, subtitle, article_text, likes, author_id, published)
VALUES (?, ?, ?, ?, ?, ?)
RETURNING id, title, creation_date;

? 总结:

  • ✅ 永远用 RETURNING 替代 OUTPUT(后者在 SQLite 中非法);
  • ✅ 优先通过 DEFAULT CURRENT_TIMESTAMP 减少冗余参数;
  • ✅ 生产环境务必检查 SQLite 版本兼容性;
  • ✅ RETURNING 是原子操作,线程安全,无需额外事务封装。

这样修改后,你的 global.db.all(...) 将成功返回插入后的完整行数据,rows[0].id 即为新生成的主键值。