迁移中的knex.raw(...)似乎不起作用

时间:2018-05-23 17:48:44

标签: knex.js

我使用knex和MySql。这是我的迁移文件:

const { onUpdateTrigger } = require('../../../../knexfile')
const { onInsertTrigger } = require('../../../../knexfile')

exports.up = function (knex, Promise) {

    return knex.schema.createTable('users', (table) => {

        console.info("------> Creating table");
        table.increments('id').unsigned().primary();
        table.string('username').unique().notNullable();
        table.string('password').notNullable();
        table.timestamp('modified').notNullable();
        table.timestamp('created').notNullable().defaultTo(knex.raw('NOW()'));
    }).then(function () {

        console.info("------> Creating trigger");
        knex.raw(onUpdateTrigger('users'));
        knex.raw(onInsertTrigger('users'));
    });
};

exports.down = function (knex, Promise) {
    return knex.schema.dropTable('users');
};

knexfile.js如下:

...

development: {
    client: 'mysql',
    connection: {
        host: 'localhost',
        user: 'pbrause',
        password: '********',
        database: 'mydb',
        charset: 'utf8',
        multipleStatements : true
    },
    debug: true,
    migrations: {
        directory: __dirname + '/src/server/db/migrations'
    },
    seeds: {
        directory: __dirname + '/src/server/db/seeds'
    }
},

...

onInsertTrigger: function(table) {
    `DELIMITER $$
     CREATE TRIGGER \`mydatabase\`.\`${table}_BEFORE_INSERT\`
            BEFORE INSERT ON \`${table}\`
            FOR EACH ROW
     BEGIN
         SET new.modified = NOW();
     END$$
     DELIMITER ;`
},

onUpdateTrigger: function(table) {
    `DELIMITER $$
     CREATE TRIGGER \`mydatabase\`.\`${table}_BEFORE_UPDATE\`
            BEFORE UPDATE ON \`${table}\`
            FOR EACH ROW
     BEGIN
         SET new.modified = NOW();
     END$$
     DELIMITER ;`
}
...

我尝试了两种变体 - 一种是SQL代码在knex.raw(...)语句中,以及您在上面看到的方式。在这两种情况下都不会创建触发器,并且knex调试输出告诉我这些“原始”语句不会被执行。在这两种情况下都能正确创建表。

知道为什么这不起作用?

1 个答案:

答案 0 :(得分:1)

首先,你要调用knex.raw()并行,而不必等待它们的执行完成:

}).then(function () {

    console.info("------> Creating trigger");
    knex.raw(onUpdateTrigger('users'));
    knex.raw(onInsertTrigger('users'));
});

从那时起应该使用knex.schema.raw或返回承诺:

}).then(function () {
    console.info("------> Creating on update trigger");
    return knex.raw(onUpdateTrigger('users'));
}).then(function () {
    console.info("------> Creating on insert trigger");
    return knex.raw(onInsertTrigger('users'));
});

return knex.schema.createTable('users', (table) => {
    console.info("------> Creating table");
    table.increments('id').unsigned().primary();
    table.string('username').unique().notNullable();
    table.string('password').notNullable();
    table.timestamp('modified').notNullable();
    table.timestamp('created').notNullable().defaultTo(knex.raw('NOW()'));
})
.raw(onUpdateTrigger('users'))
.raw(onInsertTrigger('users'));

另一个问题可能是knex.raw()(实际上db驱动程序不允许它正常)不支持默认将多个SQL语句作为单个查询发送到DB。

如果您使用的是mysql,可以通过为驱动程序https://github.com/mysqljs/mysql#connection-options设置multipleStatements : true配置选项来启用对它的支持。

编辑(真正回答为什么没有运行那些knex原始查询):

以上所有情况都属实,如果您以我建议的方式更改了代码,那么它已经解决了您的问题。

这些knex.raw()查询未运行的原因是因为您只构建查询,但从不执行它们(它们不会从promise中返回,它会自动触发查询,也不会调用{{ 1}}用于那些将查询显式发送到数据库的查询。

.then()