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

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

我有一个创build所有数据库,导入数据等sql文件我需要执行此使用node.js,但无法find任何模块,这会自动执行此操作。 对于node.js应用程序本身,我们使用node-postgres('pg'),knex.js和bookshelf.js。 我认为,尽pipe这是最好的。

我可以想到的另一种方法是读取完整的文件,用分号分隔,用空格replace换行符,修剪任何重复的空格,然后按照连续执行而不是asynchronous的方式逐个提交给pg。 如果这真的是最有效的方法,而且如果还没有图书馆来解决这个问题的话,我有点惊讶。 我有点犹豫,跳入它看到SQL语法本身可能是一个有点具有挑战性,我可能会意外地混搭起来。

事先澄清一下:

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

当传递给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(); }); 

因此,这也是有效的:

 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); }); }); 

我写了下面的函数,适用于我的情况。 如果不是这样的话,情况会简单得多:

  • 使用batch来pipe理并发
  • 有棘手的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(); }); } }); }); } 

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