Knex.JS自动更新触发器

时间:2016-04-19 20:33:59

标签: javascript postgresql knex.js

我正在使用Knex.JS迁移工具。但是,在创建表时,我希望有一个名为<activity android:name=".MainActivity" android:theme="@style/AppTheme.NoActionBar" /> 的列在数据库中更新记录时自动更新。

例如,这是一个表:

updated_at

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列显示自动更新的新时间。

我不想用原始的帖子写。

谢谢!

5 个答案:

答案 0 :(得分:19)

班尼的回答是完全正确的。但是,我注意到你特别提到了Postgres,在这种情况下,他的knex.raw语法对你不起作用。这是我成功使用的一种方法。

添加功能

如果您按设定顺序拥有多个迁移文件,则可能需要人为地更改文件名中的日期戳,以使其首先运行(或者只是将其添加到第一个迁移文件中)。如果无法回滚,则可能需要通过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')

请注意,删除表格足以摆脱触发器:我们不需要显式的DROP TRIGGER

这一切似乎都是很多工作,但是如果你想要避免使用ORM,那么一旦你完成它就会非常“一劳永逸”,并且很方便。

答案 1 :(得分:7)

您可以使用timestamps创建knex迁移:

else:
    Item.objects.create(item=forageitem, owner=User.objects.get(id = request.session['id']), description=item[forageitem], amount=1)
    messages.success(request, "You found a " + forageitem +".")
    return redirect("/dashboard")

使用timestamps将创建一个数据库架构,该架构会添加exports.up = (knex, Promise) => { return Promise.all([ knex.schema.createTable('table_name', (table) => { table.increments(); table.string('name'); table.timestamps(false, true); table.timestamp('deleted_at').defaultTo(knex.fn.now()); }) ]); }; exports.down = (knex, Promise) => { return Promise.all([ knex.schema.dropTableIfExists('table_name') ]); }; created_at列,每个列都包含一个初始时间戳。

要使updated_at列保持最新状态,您需要updated_at

knex.raw

要跳过table.timestamp('updated_at').defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')); 解决方案,我建议使用像Objection.js这样的高级ORM。使用Objection.js,您可以实施自己的knex.raw,然后更新BaseModel列:

<强> Something.js

updated_at

<强> BaseModel

const BaseModel = require('./BaseModel');

class Something extends BaseModel {
  constructor() {
    super();
  }

  static get tableName() {
    return 'table_name';
  }
}

module.exports = Something;

来源:http://vincit.github.io/objection.js/#timestamps

答案 2 :(得分:0)

这不是Knex的功能。 Knex只创建列,但不会让它保持最新状态。

但是,如果你使用Bookshelf ORM,你可以指定一个表有时间戳,它将设置&amp;按预期更新列:

答案 3 :(得分:0)

这是我在Mysql 5.6+中实现的方法

我不使用table.timestamps的原因是因为我使用DATETIME而不是时间戳。

table.dateTime('created_on')
        .notNullable()
        .defaultTo(knex.raw('CURRENT_TIMESTAMP'))

table.dateTime('updated_on')
        .notNullable()
        .defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))

答案 4 :(得分:-1)

您可以直接使用此功能

table.timestamps()

这将默认创建'created_at'和'updated_at'列,并相应地更新它们

https://knexjs.org/#Schema-timestamps