在node.js中导入sql文件并对PostgreSQL执行

rga*_*eth 18 javascript sql postgresql node.js node-postgres

我正在寻找一种有效的方法来获取一个原始的sql文件并让它与postgres数据库同步执行,类似于你运行它psql.

我有一个sql文件,它创建所有数据库,导入数据等.我需要使用node.js执行此操作,但找不到任何自动执行此操作的模块.对于node.js应用程序本身,我们使用node-postgres('pg'),knex.js和bookshelf.js.我认为虽然pg最适合这个.

我能想到的一个替代方案是读取整个文件,用分号分隔,用空格替换换行符,修剪任何重复的空格,然后以顺序执行的方式将其反馈到pg中,而不是异步执行.如果这是真正最有效的方式,并且如果还没有解决此问题的库存在,我会感到有些惊讶.我有点犹豫不决,因为SQL语法本身有点挑战,我可能会不小心把它混为一谈.

事先澄清一些:

  • psql 不能使用,因为它没有安装在目标机器上
  • 我选择以sql本机形式开发和源代码控制sql语句,因为DBA使用和操作它更容易

OhJ*_*eez 30

您可以在传递给分号时用分号分隔后续查询 client.query

这样可行:

var pg = require('pg');

pg.connect('postgres://test:test@localhost/test', function(err, client, done){
        client.query('CREATE TABLE test (test VARCHAR(255)); INSERT INTO test VALUES(\'test\') ');
        done();
});
Run Code Online (Sandbox Code Playgroud)

因此,这也有效:

var pg = require('pg');
var fs = require('fs');

var sql = fs.readFileSync('init_database.sql').toString();

pg.connect('postgres://test:test@localhost/test', function(err, client, done){
    if(err){
        console.log('error: ', err);
        process.exit(1);
    }
    client.query(sql, function(err, result){
        done();
        if(err){
            console.log('error: ', err);
            process.exit(1);
        }
        process.exit(0);
    });
});
Run Code Online (Sandbox Code Playgroud)


rga*_*eth 11

我写了以下函数,适用于我的情况.如果不是这样的话会更简单:

  • 使用batch管理并发
  • 有棘手的PostgreSQL COPY案例需要考虑

代码段:

function processSQLFile(fileName) {

  // Extract SQL queries from files. Assumes no ';' in the fileNames
  var queries = fs.readFileSync(fileName).toString()
    .replace(/(\r\n|\n|\r)/gm," ") // remove newlines
    .replace(/\s+/g, ' ') // excess white space
    .split(";") // split into all statements
    .map(Function.prototype.call, String.prototype.trim)
    .filter(function(el) {return el.length != 0}); // remove any empty ones

  // Execute each SQL query sequentially
  queries.forEach(function(query) {
    batch.push(function(done) {
      if (query.indexOf("COPY") === 0) { // COPY - needs special treatment
        var regexp = /COPY\ (.*)\ FROM\ (.*)\ DELIMITERS/gmi;
        var matches = regexp.exec(query);
        var table = matches[1];
        var fileName = matches[2];
        var copyString = "COPY " + table + " FROM STDIN DELIMITERS ',' CSV HEADER";
        var stream = client.copyFrom(copyString);
        stream.on('close', function () {
          done();
        });
        var csvFile = __dirname + '/' + fileName;
        var str = fs.readFileSync(csvFile);
        stream.write(str);
        stream.end();
      } else { // Other queries don't need special treatment
        client.query(query, function(result) {
          done();
        });
      }
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您在除终止SQL语句之外的任何地方使用分号,则会失败.