我正在使用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
列显示自动更新的新时间。
我不想用原始的帖子写。
谢谢!
答案 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;
答案 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'列,并相应地更新它们