首页 > 解决方案 > SQLite:外键“ON DELETE SET NULL”操作未触发

问题描述

为什么ON DELETE SET NULL通过应用程序代码删除行时失败,但在手动执行 SQL 语句时行为正确?

我有一个待办事项表和一个类别表。todo 表有一个在类别表category_id中引用的外键,id它是使用“ON DELETE SET NULL”操作创建的。

create table `category` (
  `id` integer not null primary key autoincrement,
  `name` varchar(255) not null
);
create table `todo` (
  `id` integer not null primary key autoincrement,
  `title` varchar(255) not null,
  `complete` boolean not null default '0',
  `category_id` integer,
  foreign key(`category_id`) references `category`(`id`) on delete SET NULL on update CASCADE
);

我的应用程序中还有一个端点,允许用户删除一个类别。

categoryRouter.delete('/:id', async (req, res) => {
  const { id } = req.params
  await req.context.models.Category.delete(id)
  return res.status(204).json()
})

此路由成功删除了类别,但问题是相关的待办事项没有将它们的category_id属性设置为 null,因此它们最终会得到一个不再存在的类别 id。奇怪的是,如果我打开我的数据库 GUI 并手动执行查询以删除一个类别... DELETE FROM category WHERE id=1... "ON DELETE SET NULL" 钩子成功触发。任何有的待办事项category_id=1现在都设置为空。

完整的应用程序源可以在这里找到。

标签: sqlsqliteexpressknex.jsobjection.js

解决方案


想通了,感谢 MikeT。

显然,默认情况下 SQLite 已关闭外键支持。哇!

要启用 FK,我必须从这里更改我的代码......

const knex = Knex(knexConfig.development)
Model.knex(knex)

对这个...

const knex = Knex(knexConfig.development)
knex.client.pool.on('createSuccess', (eventId, resource) => {
  resource.run('PRAGMA foreign_keys = ON', () => {})
})
Model.knex(knex)

或者,我可以在knexfile.js...

module.exports = {
 development: {
   client: 'sqlite3',
   connection: {
     filename: './db.sqlite3'
   },
   pool: {
     afterCreate: (conn, cb) => {
       conn.run('PRAGMA foreign_keys = ON', cb)
     }
   }
 },
 staging: {},
 production: {}
}

推荐阅读