42

Is there a way to have sequelize create the database I'm trying to connect to if it doesn't exist?

I have a raw MySQL instance and I get this error back:

ER_BAD_DB_ERROR: Unknown database 'mytest'

I'd like to handle that error, use the creds I provided (or a different set of creates with create permissions), and run CREATE DATABASE mytest.

Dave Briand
  • 1,684
  • 1
  • 16
  • 16
  • 7
    I don't think this feature exists in sequelize, but I too would like a feature like this. Nothing is more annoying than getting started on an existing project and needing to set up a database before you can even run the app. I don't want to put my coworkers through any setup whatsoever. Download and go is the way to go. – Spencer Aug 25 '15 at 18:00

6 Answers6

25

I may have a reasonable solution. I am sure it could be written more cleanly though.

For this example I'm using Postgres, the answer would be slightly different for MySQL. I'm heavily borrowing from this answer: node-postgres create database

In database.js I have the following init function

var Sequelize = require('sequelize'),
    pg = require('pg');

module.exports.init = function(callback) {
    var dbName = 'db_name',
        username = 'postgres',
        password = 'password',
        host = 'localhost'

    var conStringPri = 'postgres://' + username + ':' + password + '@' + host + '/postgres';
    var conStringPost = 'postgres://' + username + ':' + password + '@' + host + '/' + dbName;

    // connect to postgres db
    pg.connect(conStringPri, function(err, client, done) { 
        // create the db and ignore any errors, for example if it already exists.
        client.query('CREATE DATABASE ' + dbName, function(err) {
            //db should exist now, initialize Sequelize
            var sequelize = new Sequelize(conStringPost);
            callback(sequelize);
            client.end(); // close the connection
        });
    });
};

The init function is creating the database before sequelize is called. It first opens a connection to postgres and creates the database. If the database already exists, an error will be thrown which we are ignoring. Once it is created we initialize sequelize and send it to the callback. Importantly, if the database already exists it will not be overwritten.

In app.js I receive the database instance and send it over to whichever module needs it, in this case it is passport.

require('./server/config/database.js').init(function(database) {
  require('./server/config/passport.js')(passport, database);
});
ZygD
  • 22,092
  • 39
  • 79
  • 102
Spencer
  • 1,527
  • 1
  • 10
  • 23
  • Good thinking for looking into node-pg. I'll check node-mysql and see if something similar exists. Will come back and mark answered if it works. – Dave Briand Aug 26 '15 at 11:45
  • You say "If the database already exists, an error will be thrown which we are ignoring". Does this mean that if the database already exists that it will be overwritten? Or that it will just found and used? – steven_noble Apr 15 '16 at 03:03
  • @steven_noble No, if the DB already exists then CREATE DATABASE will throw an error telling you that. It won't overwrite an existing database. You can test this out with a dummy DB name and log out the error to see what it says and does. – Spencer Apr 15 '16 at 14:25
9

I ended up using the mysql2 package, here is what I did..

    const mysql = require('mysql2/promise');
    
    mysql.createConnection({
        user     : config.sequelize.username,
        password : config.sequelize.password
    }).then((connection) => {
        connection.query('CREATE DATABASE IF NOT EXISTS myRandomDb;').then(() => {
            // Safe to use sequelize now
        })
    })

After that I can connect to that database using sequelize.

Lee Goddard
  • 10,680
  • 4
  • 46
  • 63
nikksan
  • 3,341
  • 3
  • 22
  • 27
7

In my case I was using sqlite, but the idea was the same. I needed to create the database first with sqlite3.

const sqlite = require('sqlite3');
const db = new sqlite.Database('/path/to/database.sqlite');
const sequelize = new Sequelize('database', '', '', {
  dialect: 'sqlite',
  storage: '/path/to/database.sqlite',
  ...
});
Grant
  • 1,822
  • 1
  • 21
  • 30
7

I didn't have this problem with Postgresql but I did have with mysql. Solution was creating a pre-migrate script and trigger it before the sequelize migration, here's part of my package.json :

"db:pre-migrate": "node scripts/createDB.js",
"db:migrate": "npm run db:pre-migrate && node_modules/.bin/sequelize db:migrate",

and similarly to what was proposed in some answer here, you could create this createDB.js using modules like node-postgres or mysql(or any other that connects to mysql with raw queries):

const mysql = require('mysql2/promise');

const dbName = process.env.DB_SCHEMAS || "YOUR_DB";

mysql.createConnection({
    host: process.env.DB_HOST || "127.0.0.1",
    port: process.env.DB_PORT || "3306",
    user     : process.env.DB_USER || "root",
    password : process.env.DB_PASSWORD || "root",
}).then( connection => {
    connection.query(`CREATE DATABASE IF NOT EXISTS ${dbName};`).then((res) => {
        console.info("Database create or successfully checked");
        process.exit(0);
    })
})
Marco Barcellos
  • 196
  • 2
  • 4
7

Shortly: In my case, I got this error when running tests for the first time. To resolve that, I just added the command npx sequelize-cli db:create before running jest.


After adding the command in my test script, the package.json looks like this:

  "scripts": {
    "test": "npx sequelize-cli db:create && jest"
  }

You should see this message at the beggingnig of nmp test exexution:

Loaded configuration file "config/config.json".
Using environment "development".
Database orders created.

Sequelize knows to create a database called "orders" because I mentioed it in "config/config.json".

{
  "development": {
    "username": "root",
    "password": "pswd",
    "database": "manager",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "port": "3307"
  },
elirandav
  • 1,913
  • 19
  • 27
  • This is the only way that works for me, as of Postgres 13. Thanks! – Tsar Bomba Jun 28 '21 at 20:52
  • I am not able to create database using command `npx sequelize-cli db:create` what i am doing wrong i am just installed sequelize using dialect is postgres . i am running first command `npx sequelize-cli init` after that i am creating database using command but it says ` password authentication failed for user "migrationRoot"` – Harpreet Singh Jul 16 '21 at 16:03
  • it means the user or password is wrong. the user/password is usually determined when you set up the database or its container @Harpritsingh – elirandav Jul 17 '21 at 16:04
  • Actually after two days of search i found in sequelize its not support for create and drop See this https://github.com/sequelize/sequelize/issues/8082) @KernelMode – Harpreet Singh Jul 18 '21 at 18:43
0

You can try:

import { Sequelize } from 'sequelize';

// user must have permission to create databases.
const sequelize = new Sequelize('postgres://user:pass@localhost:5432/postgres');

async function creatDatabase(dbName: string) {
  let res;
  try {
    res = await sequelize.getQueryInterface().createDatabase(dbName);
  } catch(e) {
    console.log(e);
  }
  return res;
}

creatDatabase('secondDB');
Tony
  • 51
  • 1
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 04 '22 at 06:13