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

Knex.js配置MySQL updated_at自动更新触发器执行迁移报错如何解决

报错原因

你写的自定义函数和触发器语法是PostgreSQL数据库的专属语法,完全不兼容MySQL,具体不兼容点如下:

  • MySQL没有RETURNS trigger的函数定义语法,触发器逻辑不需要封装成独立函数,直接写在触发器声明中即可
  • $$是PostgreSQL的函数体定界符,MySQL不识别该语法
  • MySQL触发器不支持EXECUTE PROCEDURE调用自定义函数的用法,属于PostgreSQL专属特性
修复方案

有两种更适配MySQL的实现方案,推荐优先使用第一种,逻辑更简洁无需额外维护触发器:

方案1:直接使用MySQL原生字段属性(推荐)

MySQL的TIMESTAMP和DATETIME字段原生支持ON UPDATE CURRENT_TIMESTAMP属性,修改记录时会自动更新updated_at字段,完全不需要自定义函数和触发器。
只需要修改用户表迁移文件的updated_at字段定义即可:

exports.up = async (knex) => {
  await knex.schema.createTable('users', (table) => {
    table.increments('id')
    table.string('email').notNullable()
    table.string('password').notNullable()
    table.string('reset_token')
    table.timestamp('reset_expires')
    table.timestamp('created_at').defaultTo(knex.fn.now())
    // 新增.onUpdate()方法,knex会自动生成MySQL的ON UPDATE CURRENT_TIMESTAMP属性
    table.timestamp('updated_at').defaultTo(knex.fn.now()).onUpdate(knex.fn.now())
  })
  // 不需要再执行触发器创建逻辑
}

同时可以直接删除之前的自定义函数迁移文件,以及knexfile.js里的onUpdateTrigger相关代码即可。

方案2:自定义触发器实现

如果业务需求必须用触发器实现,修改knexfile.js里的onUpdateTrigger方法为MySQL兼容语法即可,无需额外创建自定义函数:

onUpdateTrigger: (table) => `
    CREATE TRIGGER ${table}_updated_at
    BEFORE UPDATE ON ${table}
    FOR EACH ROW
    SET NEW.updated_at = CURRENT_TIMESTAMP;
`

同时删除之前的自定义函数迁移文件即可,原用户表迁移代码不需要额外修改。

内容的提问来源于stack exchange,提问作者João Lucas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 20:36:01