Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在node.js中导入sql文件并对PostgreSQL执行_Javascript_Sql_Node.js_Postgresql_Node Postgres - Fatal编程技术网

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

Javascript 在node.js中导入sql文件并对PostgreSQL执行,javascript,sql,node.js,postgresql,node-postgres,Javascript,Sql,Node.js,Postgresql,Node Postgres,我正在寻找一种有效的方法来获取原始sql文件并对postgres数据库同步执行它,类似于通过psql运行它 我有一个创建所有数据库、导入数据等的sql文件。我需要使用node.js执行此操作,但找不到任何自动执行此操作的模块。对于node.js应用程序本身,我们使用node postgres('pg')、knex.js和bookshelf.js。我想pg是最好的选择 我能想到的另一种方法是读取完整文件,用分号分割,用空格替换换行符,修剪任何重复的空格,然后以顺序而不是异步执行的方式将其逐个送入p

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

我有一个创建所有数据库、导入数据等的sql文件。我需要使用node.js执行此操作,但找不到任何自动执行此操作的模块。对于node.js应用程序本身,我们使用node postgres('pg')、knex.js和bookshelf.js。我想pg是最好的选择

我能想到的另一种方法是读取完整文件,用分号分割,用空格替换换行符,修剪任何重复的空格,然后以顺序而不是异步执行的方式将其逐个送入pg。如果这真的是最有效的方法,而且还没有库可以解决这个问题,我有点惊讶。我有点犹豫要不要跳进去,因为SQL语法本身可能有点挑战性,我可能会不小心把它搞乱

事先作出一些澄清:

  • psql
    无法使用,因为它未安装在目标计算机上
  • 我选择以sql本机形式开发和控制sql语句,因为DBA使用和操作它要容易得多

我已经编写了以下适用于我的案例的函数。如果不是因为:

  • 使用批处理来管理并发性
  • 考虑棘手的PostgreSQL复制案例
代码段:

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语句,则此操作都会失败。

在传递到
客户端时,您可以用分号分隔后续查询。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);
    });
});
客户端支持开箱即用地运行SQL文件:

const createPool = require('@databases/pg');
const {sql} = require('@databases/pg');

const db = createPool();

db.query(sql.file('my-file.sql')).catch(ex => {
  console.error(ex);
  process.exitCode = 1;
}).then(() => db.dispose());
它还支持在对
db.query的单个调用中包含多个语句:

const createPool = require('@databases/pg');
const {sql} = require('@databases/pg');

const db = createPool();

db.query(sql`
  INSERT INTO users (name) VALUES (${'Forbes'});
  SELECT * FROM users;
`)).then(
  results => console.log(results)
).catch(ex => {
  console.error(ex);
  process.exitCode = 1;
}).then(() => db.dispose());

在本例中,每个语句都按顺序运行,并返回最后一个语句的结果。

这比您最初想象的要困难,因为您需要在SQL中区分文本和关键字。举一个简单的例子,用分号拆分不能处理
insert-into-table值(“;”)我最初尝试过,但发现了一些问题:*SQL文件中传统的换行符和制表符无法填充到client.query中,(通过一些额外的步骤可以解决)*每个查询的错误处理都非常困难(我承认我在这里的示例中也没有提到这一点)@rgareth我对SQL文件中的换行符和制表符完全没有任何问题。您可以将一些
\n
s(甚至
\r\n
s)和
\t
s添加到我的示例中,它仍然可以工作。这对我的ibm\u db lib很有效。我也面临着同样的问题,但我想到了一个问题。关于SQL注入呢?您可以添加关于什么是
批处理
的详细信息吗?关于导入带有函数的脚本呢?虽然您的回答对我有所帮助,但您可以提到
@数据库
包是由您创建的:smiley:…此外,文档(在您的网站上)还可以改进,以包含更多示例,例如,我(作为Node JS新手)很难找到放置连接选项的位置,因为您的所有示例都在
createConnectionPool()
中使用单个字符串,但是,我可以在其中放置一个具有支持的连接选项的对象。继续努力!感谢@Tukusejsirs的反馈如果您对文档有改进建议,我希望您能在PR提交。您需要编辑的所有文件都在这里: