SQLite:未触发外键“ON DELETE SET NULL”操作

dtcbnfnu  于 2022-12-29  发布在  SQLite
关注(0)|答案(2)|浏览(226)
    • 为什么ON DELETE SET NULL在通过应用程序代码删除行时会失败,但在手动执行SQL语句时会正常工作?**

我有一个todo表和一个category表,todo表有一个category_id外键引用category表中的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()
})

这个方法成功地删除了类别,但问题是相关的todo项没有将其category_id属性设置为null,因此它们最终得到的类别ID不再存在。如果我打开数据库GUI并手动执行删除类别的查询... DELETE FROM category WHERE id=1 ..."ON DELETE SET NULL"钩子将成功触发。任何具有category_id=1的待办事项现在都设置为null。
完整的应用程序源代码可在here中找到。

1tu0hz3e

1tu0hz3e1#

想明白了多亏了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: {}
}
yzxexxkh

yzxexxkh2#

FYI和其他偶然发现类似问题的人,您不仅需要PRAGMA foreign_keys = ON用于子表,还需要用于父表。
当我只为一个处理子表的程序设置PRAGMA foreign_keys = ON时,ON UPDATE CASCADE被启用,但ON DELETE SET NULL仍然被禁用,最后我发现我忘记了另一个处理父表的程序的PRAGMA foreign_keys = ON

相关问题