javascript Knex.JS自动更新触发器

qxgroojn  于 2023-01-29  发布在  Java
关注(0)|答案(6)|浏览(147)

我使用的是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字体写作。
谢谢!

6tdlim6h

6tdlim6h1#

使用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,但是如果您不想使它复杂化,您可以在任何地方定义它。

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,它非常方便。

ruyhziif

ruyhziif2#

您可以使用时间戳创建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

ehxuflar

ehxuflar3#

这是我在Mysql 5.6+中的做法
我没有使用table.timestamps的原因是因为我使用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'))
jc3wubiy

jc3wubiy4#

这不是Knex的特性。Knex只创建列,但不为您保持最新。
但是,如果使用Bookshelf ORM,则可以指定表具有时间戳,并且它将按预期设置和更新列:

vatpfxk5

vatpfxk55#

出口增加=(千分之一)=〉{返回千分之一原始(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();)};
出口下降=(千分之一)=〉{返回千分之一原始(drop table if exists table_name; drop function if exists table_name_update;)};

kpbwa7wx

kpbwa7wx6#

您可以直接使用此功能

table.timestamps()

缺省情况下,这将创建“created_at”和“updated_at”列,并相应地更新它们
https://knexjs.org/#Schema-timestamps

相关问题