Javascript Knex.JS自动更新触发器
我正在使用迁移工具。但是,在创建表时,我希望在处有一个名为Javascript Knex.JS自动更新触发器,javascript,postgresql,knex.js,Javascript,Postgresql,Knex.js,我正在使用迁移工具。但是,在创建表时,我希望在处有一个名为updated\u的列,当数据库中的记录更新时,该列会自动更新 例如,下面是一个表: knex.schema.createTable('table_name', function(table) { table.increments(); table.string('name'); table.timestamp("created_at").defaultTo(knex.fn.now()); table.ti
updated\u的列,当数据库中的记录更新时,该列会自动更新
例如,下面是一个表:
knex.schema.createTable('table_name', function(table) {
table.increments();
table.string('name');
table.timestamp("created_at").defaultTo(knex.fn.now());
table.timestamp("updated_at").defaultTo(knex.fn.now());
table.timestamp("deleted_at");
})
created_at
和updated_at
列默认为创建记录的时间,这是正常的。但是,当该记录被更新时,我希望updated_at
列显示自动更新的新时间
我宁愿不写原始的博士后
谢谢 您可以直接使用此功能
table.timestamps()
默认情况下,这将创建“created_at”和“updated_at”列,并相应地更新它们
这不是Knex的功能。Knex只创建列,但不为您保持最新
但是,如果使用书架表单,则可以指定表具有时间戳,并且它将按预期设置和更新列:
您可以使用以下方法创建knex迁移:
将创建一个数据库架构,其中在
处添加一个created\u列和在
处添加一个updated\u列,每个列都包含一个初始时间戳
要使列的保持最新,您需要knex.raw
:
table.timestamp('updated_at').defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
要跳过knex.raw
解决方案,我建议使用类似的高级ORM。使用,您可以实现自己的BaseModel
,然后在列更新updated\u:
Something.js
const BaseModel = require('./BaseModel');
class Something extends BaseModel {
constructor() {
super();
}
static get tableName() {
return 'table_name';
}
}
module.exports = Something;
BaseModel
const knexfile = require('../../knexfile');
const knex = require('knex')(knexfile.development);
const Model = require('objection').Model;
class BaseModel extends Model {
$beforeUpdate() {
this.updated_at = knex.fn.now();
}
}
module.exports = BaseModel;
来源:对于Postgres,您需要。这是我成功使用的一种方法
添加一个函数
如果您有多个按设定顺序排列的迁移文件,则可能需要人为地更改文件名中的日期戳,以使其首先运行(或仅将其添加到第一个迁移文件中)。如果无法回滚,则可能需要通过psql
手动执行此步骤。但是,对于新项目:
const ON_UPDATE_TIMESTAMP_FUNCTION = `
CREATE OR REPLACE FUNCTION on_update_timestamp()
RETURNS trigger AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
`
const DROP_ON_UPDATE_TIMESTAMP_FUNCTION = `DROP FUNCTION on_update_timestamp`
exports.up = knex => knex.raw(ON_UPDATE_TIMESTAMP_FUNCTION)
exports.down = knex => knex.raw(DROP_ON_UPDATE_TIMESTAMP_FUNCTION)
现在,该功能应可用于所有后续迁移
定义一个knex.raw
触发器辅助对象
如果可以避免的话,我发现不在迁移文件中重复大量SQL更具表现力。我在这里使用了knexfile.js
,但是如果您不想把它复杂化,您可以在任何地方定义它
module.exports = {
development: {
// ...
},
production: {
// ...
},
onUpdateTrigger: table => `
CREATE TRIGGER ${table}_updated_at
BEFORE UPDATE ON ${table}
FOR EACH ROW
EXECUTE PROCEDURE on_update_timestamp();
`
}
使用助手
最后,我们可以非常方便地定义自动更新触发器:
const { onUpdateTrigger } = require('../knexfile')
exports.up = knex =>
knex.schema.createTable('posts', t => {
t.increments()
t.string('title')
t.string('body')
t.timestamps(true, true)
})
.then(() => knex.raw(onUpdateTrigger('posts')))
exports.down = knex => knex.schema.dropTable('posts')
请注意,删除表就足以摆脱触发器:我们不需要显式的删除触发器
这一切看起来可能需要做很多工作,但一旦你完成了它,它就相当于“设置并忘记”,如果你想避免使用ORM,它非常方便。这是我在Mysql 5.6+中的做法
我没有使用table.timestamp的原因是我使用了DATETIME而不是timestamp
table.dateTime('created_on')
.notNullable()
.defaultTo(knex.raw('CURRENT_TIMESTAMP'))
table.dateTime('updated_on')
.notNullable()
.defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
我讨厌人们投票否决一个看起来很好、没有评论的答案。我怀疑timestamps()
并没有像文档中描述的那样工作,但可能他们只是心情不好或是其他什么。table.timestamps()
需要转换为table.timestamps(false,true)
以确保在未提供数据时使用当前时间戳。即使table.timestamps(false,true)使用code>时,它不会更新
列中的updated\u。Upvote for objective.js。node.js的ORM真不错,答案太棒了!它不仅有效,而且是如何向postgres添加函数的好例子。谢谢这是一个奇妙的解决方案,男孩,它是干净的。谢谢,里奇!回答得很好。是否需要在knexfile上编写方法onUpdateTrigger
。我只是发现使用(或接近)knexfile.js
存储这些东西更容易。
table.dateTime('created_on')
.notNullable()
.defaultTo(knex.raw('CURRENT_TIMESTAMP'))
table.dateTime('updated_on')
.notNullable()
.defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))