【问题标题】:Use NodeJS to run an SQL file in MySQL使用 NodeJS 在 MySQL 中运行 SQL 文件
【发布时间】:2014-04-12 04:11:39
【问题描述】:

我正在为 nodejs 使用 mysql 插件,到目前为止,它非常适合做我需要的一切。

但是我遇到了一个绊脚石。我创建了一个导出 mysql 池的 MySQL 提供程序:

var mysql = require('mysql');
var mysqlPool  = mysql.createPool({
  host     : '127.0.0.1',
  user     : 'root',
  password : ''
});

mysqlPool.getConnection(function(err, connection) {
  connection.query("INSERT INTO ....

我可以选择、创建、插入等一切都很好,但我遇到了一个任务,我想同时运行一个包含大约 10 个不同命令的小 SQL 字符串。我考虑过执行以下操作之一:

  1. 使用 mysql 对数据库执行 SQL 文件
  2. 运行query 并启用multipleStatements

我已经编写了一些代码来将mysql 作为子进程执行,但我真的很想避免这样做:

var cp = require("child_process");
var cmdLine = "mysql --user=autobuild --password=something newdb < load.sql";
cp.exec(cmdLine, function(error,stdout,stderr) {
    console.log(error,stdout,stderr);
});  

选项二的问题是我宁愿不为每个查询启用多个语句,只为这个特定的一个。我曾考虑过创建一个新的连接,但只是在想其他方法可以做到这一点。

TL;DR? 使用 NodeJS 和 MySQL 如何在数据库中执行以下操作:

CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20) );

CREATE TABLE sofa (name VARCHAR(20), owner VARCHAR(20) );

CREATE TABLE table (name VARCHAR(20), owner VARCHAR(20) );

非常感谢任何分享他们想法的人

【问题讨论】:

    标签: mysql node.js


    【解决方案1】:

    您可以使用名为multipleStatements的连接选项:

    // Works with the pool too.
    var connection = mysql.createConnection({multipleStatements: true});
    

    然后,您可以传递如下查询:

    connection.query('CREATE 1; CREATE 2; SELECT 3;', function(err, results) {
      if (err) throw err;
    
      // `results` is an array with one element for every statement in the query:
      console.log(results[0]); // [create1]
      console.log(results[1]); // [create2]
      console.log(results[2]); // [select3]
    });
    

    【讨论】:

    • 是否有将查询流式传输到 mysql 连接?此示例假定 multipleStatements 是一个可管理的缓冲区。
    • 请记住,当您使用 connection.execute() 函数时,多个语句将不起作用。因此,如果您不想使用 execute() 在同一连接上触发多个查询,则必须使用“connect() -> execute() -> end()”模式
    • 在创建触发器之前使用DELIMITER时不起作用。
    • @user1748217 您可以使用 Node 的 fs 模块从 .sql 文件中导入文本。然后,您可以将此文本作为.query 调用中的第一个参数传递。如果文件只有一个查询,这只会在默认情况下起作用。此解决方案确保您可以传递具有多个的文件。
    • 我还要注意,根据其文档,mysql Node 库似乎已经稍微改变了它的语法。现在您需要向它传递一个flag 属性,其值包括字符串“MULTI_STATEMENTS”。示例:const conn = mysql.createConnection({flags:"-MULTI_STATEMENTS"})
    【解决方案2】:

    这是一个大的.sql 文件友好的方式,可以在不使用multipleStatements 属性和大量缓冲区的情况下以编程方式对 MySQL 执行多个查询。请注意,这不是上传到 mysql 的最有效方式。

    var mysql = require('mysql');
    var fs = require('fs');
    var readline = require('readline');
    var myCon = mysql.createConnection({
       host: 'localhost',
       port: '3306',
       database: '',
       user: '',
       password: ''
    });
    var rl = readline.createInterface({
      input: fs.createReadStream('./myFile.sql'),
      terminal: false
     });
    rl.on('line', function(chunk){
        myCon.query(chunk.toString('ascii'), function(err, sets, fields){
         if(err) console.log(err);
        });
    });
    rl.on('close', function(){
      console.log("finished");
      myCon.end();
    });
    

    【讨论】:

      【解决方案3】:

      看起来有一个用于此目的的模块:execsql

      【讨论】:

      • 我在运行execsql的示例代码时得到Error: Cannot enqueue Query after invoking quit.
      【解决方案4】:

      这样就可以了:

      var express = require("express");
      var bodyParser = require("body-parser");
      var mysql = require('mysql');
      var fs = require('fs');
      
      var app = express();
      
      app.use(bodyParser.urlencoded({ extended: false }));
      app.use(bodyParser.json());
      app.use(express.static(__dirname));
      
      var defaultConnection = mysql.createConnection({
        host     : 'localhost',
        user     : 'root',
        password : '',
        database: 'utpDatabase'
      });
      
      function dbCall_file (endpoint, operation, settings, filename){
          app.post(endpoint, function(request, response){
              var data = request.body;
              var path = 'path/to/queries/' + filename
              var connection = (settings == 'default') ? defaultConnection : settings;
              var callback = function(arg){
                  var query = arg.replace(/{{[ ]{0,2}([a-zA-Z0-9\.\_\-]*)[ ]{0,2}}}/g, function(str, mch){ return data[mch]});
                  connection.query(query, function(err, rows){
                      if (!err){
                          var toClient = (operation == 'select') ? rows : {success: true};
                          response.send(toClient);
                      } else {
                          console.log(err);
                          response.send({error: err, query: query});
                      }
                  });
              };
      
              fs.readFile(path, 'utf8', function(err, data){
                  if (!err){
                      callback(data);
                  } else {
                      callback(err);
                  }
              });
      
          });
      };
      

      然后在你的 .sql 文件中将你的节点变量用双花括号包裹起来——例如,如果你想从你的 post call 中查询节点变量 data.firstName 的名字:

      SELECT * FROM users WHERE name={{ firstName }}
      

      【讨论】:

        猜你喜欢
        • 2010-11-11
        • 2011-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-20
        • 1970-01-01
        • 2014-07-08
        • 1970-01-01
        相关资源
        最近更新 更多