簡體   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