2014-03-25 24 views
9

我正在寻找一种有效的方法来获取原始sql文件,并使其同步执行postgres数据库,类似于如果您通过psql运行它。在node.js中导入sql文件并针对PostgreSQL执行

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

我能想到的另一种方法是读取完整文件,用分号分隔它,用空格替换换行符,修剪任何重复的空格,然后以顺序执行的方式将它们逐个馈送到pg中,不是异步的。如果这真的是最有效的方式,并且如果还没有图书馆可以解决这个问题,我有点惊讶。我有点犹豫是否可以进入它,因为SQL语法本身可能有点难度,我可能会意外地将它混淆起来。

提前一些澄清:

  • psql不能使用,因为它不是在目标机器
  • 我选择了开发和源代码控制在SQL天然形式的SQL语句上安装,因为这是一个很大DBA更容易使用和操作它
+0

它比你首先想到的更难因为您需要区分SQL中的关键字和关键字。作为一个简单的例子,_split by semicolons_不能与'插入表值(';');' –

回答

7

我已经写了以下函数,它为我的案件工作。这本来是更简单的,如果不是因为:

  • 使用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(); 
     }); 
     } 
    }); 
    }); 
} 

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

+0

你可以添加什么'批次'是什么细节? –

+0

https://github.com/visionmedia/batch – rgareth

16

你传递给client.query

这一工程时,可以只用分号分隔随之而来的疑问:

var pg = require('pg'); 

pg.connect('postgres://test:[email protected]/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:[email protected]/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); 
    }); 
}); 
+0

我最初尝试过,但发现问题: *传统上在SQL文件中发现的换行符和标签无法填充到client.query中,(可以通过一些额外的步骤解析) * Very每个查询都很难处理(我承认这里也没有列出我的例子) – rgareth

+0

@rgareth我完全没有任何问题,无论是SQL文件中的换行符还是选项卡。你可以在我的例子中添加一些'\ n's(甚至'\ r \ n's)和'\ t's,它仍然可以工作。 – OhJeez

+0

为我工作的ibm_db lib。我也面临同样的问题,但是我想起了一个问题。怎么样SQL注入? – user2670818

相关问题