You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用expo-sqlite时主键非空约束报错问题排查

Expo-SQLite插入数据时NOT NULL约束错误的解决方案

你的理解是对的:SQLite的主键可以配置为自动自增,插入新行时无需手动提供id值。问题出在你的建表语句语法上,而非expo-sqlite包本身。

问题根源

SQLite中,只有当主键字段被定义为INTEGER PRIMARY KEY(语义上匹配该关键字即可,SQLite不严格区分大小写)时,才会自动为该字段生成自增的整数值。而你的建表语句里,id字段只是integer类型+主键约束,属于普通非空主键,不会自动生成值,所以插入时不传入id就会触发NOT NULL约束错误。

另外你的transactions表外键引用了不存在的test_categories表,应该改为categories,这也是潜在问题。

修正后的建表代码

修改两个表的建表语句,将id字段改为自增主键:

useEffect(() => {
    // Create new tables if no database exist
    db.transaction((tx) => {
      tx.executeSql(
        'create table if not exists categories (id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar(255));',
        [],
        () => {},
        (tx, err) => {
          console.log('建表错误(categories)', err);
          return true;
        }
      );
      tx.executeSql(
        'create table if not exists transactions (id INTEGER PRIMARY KEY AUTOINCREMENT, tx_datetime datetime, tx_value varchar(255), note varchar(255), tx_day integer, tx_month integer, tx_year varchar(255), category integer, tx_type integer default 0, foreign key (category) references categories (id));',
        [],
        () => {},
        (tx, err) => {
          console.log('建表错误(transactions)', err);
          return true;
        }
      );
    });
  }, []);

补充说明

  • INTEGER PRIMARY KEY已经足够让SQLite自动生成自增id,AUTOINCREMENT关键字是可选的——它会强制id严格递增且不重用已删除行的id(默认情况下,SQLite可能会重用已删除的id值),可根据业务需求选择是否添加。
  • 修正外键引用的表名后,transactions表的外键约束才能正常生效。

验证插入操作

修改建表语句后,你原来的插入代码就能正常执行,无需传入id字段:

db.transaction((tx) => {
    tx.executeSql(
      'insert into categories(name) values("testing");',
      [],
      () => console.log("插入成功"),
      (tx, err) => {
        console.log('插入错误', err);
        return true;
      }
    );
  });

内容的提问来源于stack exchange,提问作者jted95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:01:17