繁体   English   中英

Knex.JS 自动更新触发器

[英]Knex.JS Auto Update Trigger

我正在使用Knex.JS迁移工具。 但是,在创建表时,我希望有一个名为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_atupdated_at列默认为记录创建的时间,这很好。 但是,当该记录更新时,我希望updated_at列显示它自动更新的新时间。

我不想用原始的 postgres 写。

谢谢!

使用 Postgres,你需要一个trigger 这是我成功使用的方法。

添加功能

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

您可以使用时间戳创建 knex 迁移:

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_atupdated_at列,每个列都包含一个初始时间戳。

要保持updated_at列最新,您需要knex.raw

table.timestamp('updated_at').defaultTo(knex.raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));

要跳过knex.raw解决方案,我建议使用像Objection.js这样的高级 ORM。 使用Objection.js,您可以实现自己的BaseModel ,然后更新updated_at列:

东西.js

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

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

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

module.exports = Something;

基础模型

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;

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

这不是 Knex 的功能。 Knex 仅创建列,但不会为您保持最新状态。

但是,如果使用 Bookshelf ORM,则可以指定表具有时间戳,并且它将按预期设置和更新列:

这是我在 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'))

exports.up = (knex) => { return knex.raw( create or replace function table_name_update() RETURNS trigger AS $$ begin new.updated_at = now(); RETURN NEW; end; $$ language 'plpgsql'; create or replace trigger tg_table_name_update on table_name before update for each row execute table_name_update(); ) };

exports.down = (knex) => { return knex.raw( drop table if exists table_name; drop function if exists table_name_update; ) };

可以直接使用这个功能

table.timestamps()

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM