【问题标题】:Create database in Knex migration在 Knex 迁移中创建数据库
【发布时间】:2018-09-16 08:49:33
【问题描述】:

我认为从第一次 db 交互开始使用迁移是个好主意,所以我想创建一个迁移来创建数据库。

knexfile.js

'use strict';

require('dotenv').config({ path: 'process.env' });

const config =  {
  client: 'pg',
  connection: {
    host: process.env.DB_URL,
  },
};


module.exports = config;

迁移文件:

'use strict';

exports.up = function(knex, Promise) {
  return knex.raw('CREATE DATABASE asd');
};

exports.down = function(knex, Promise) {
  return knex.raw('DROP DATABASE asd');
};

exports.config = {
  transaction: false
};

到目前为止它工作正常,但是当我将database 添加到 knexfile 配置时,由于 Knex 尝试连接到不存在的数据库,它无法迁移。

我还尝试使用新的 Knex 实例进行此单一迁移,例如:

exports.up = function(_, Promise) {
  // Remove database from config so Knex won't try to connect
  // to a non existing database.
  const config = require(process.cwd() + '/knexfile');
  config.connection.database = null;
  const knex = require('knex')(config);

  return knex.raw('CREATE DATABASE asd');
};

但是 knex 在迁移之前已经初始化,所以它失败并出现同样的错误:

error: database "asd" does not exist

关于如何从 Knex 迁移创建数据库的任何想法?我愿意接受任何有关数据库创建的最佳实践,它们可以处理不同环境的数据库 url。

【问题讨论】:

    标签: sql postgresql migration knex.js


    【解决方案1】:

    Knex 并不真正支持轻松创建数据库。

    首先运行迁移必须创建表,其中包含已运行迁移的信息,因此数据库必须在执行迁移之前存在。

    通常您希望使用不同的配置文件来创建数据库,用户具有足够的权限来创建数据库并连接到例如名为postgrestemplate1 的数据库。

    您应该可以通过创建简单的脚本来做到这一点,这可以确保在运行迁移之前创建数据库。

    还有工具knex-db-manager(主要由我编写)可能有助于创建数据库所有者用户/数据库的任务。

    【讨论】:

      【解决方案2】:

      我已经添加了一个postinstall 脚本来运行这样的脚本:

      'use strict';
      
      async function createDatabase() {
        const config = require(process.cwd() + '/knexfile');
        config.connection.database = null;
        const knex = require('knex')(config);
      
        await knex.raw('CREATE DATABASE asd');
        await knex.destroy();
      }
      
      createDatabase();
      

      这样,我没有将此步骤存储为迁移,但我并没有真正看到想要删除整个数据库的用例。

      您如何看待这种方法?

      【讨论】:

      • 常见用例是运行集成测试的临时数据库
      【解决方案3】:

      由于事先不知道数据库,因此最简单的方法是使用迁移 API 创建您自己的脚本。应该可以动态指定数据库名称

      另存为migrate.js

      const Knex = require('knex')
      
      // You can dynamically pass the database name
      // as a command-line argument, or obtain it from
      // a .env file
      const databaseName = 'database_name'
      
      const connection = {
        host: 'localhost',
        user: 'root',
        password: 'password'
      }
      
      async function main() {
        let knex = Knex({
          client: 'mysql',
          connection
        })
        
        // Lets create our database if it does not exist
        await knex.raw('CREATE DATABASE IF NOT EXISTS ??', databaseName)
        
      
        // Now that our database is known, let's create another knex object
        // with database name specified so that we can run our migrations
        knex = Knex({
          client: 'mysql',
          connection: {
            ...connection,
            database: databaseName,
          }
        })
      
        // Now we can happily run our migrations
        await knex.migrate.latest()
      
        // Done!!
      }
      
      main().catch(console.log).then(process.exit)
      

      您现在可以运行您的脚本

      node migrate.js
      

      您可以使用.env 文件来存储您的配置或将它们作为命令行参数传递

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-29
        • 2021-01-17
        相关资源
        最近更新 更多