【问题标题】:Updating multiple rows with node-mysql, NodeJS and Q使用 node-mysql、NodeJS 和 Q 更新多行
【发布时间】:2014-10-22 12:16:34
【问题描述】:

我正在使用 node-mysql、node-js 和 Q Promise。

我已使用上述方法成功更新、删除和插入单行。以及在我的测试用例场景中的单个语句中插入多行。

但是,我需要在单个查询或 for 循环中使用不同的值(批处理模式)更新多行。

关于如何在 mysql2 中使用准备好的语句(应该在 node-mysql 上改进)的信息非常稀少,没有示例,尽管这应该是自然的选择,以及补偿 node-js 异步性质的承诺.

另外,我已经在各种测试场景中成功使用了defered.makeNodeResolver()。

我正在尝试使用 where 子句和更改条件更新单个查询中的多行。

当我更新一行时它正在工作。但是,当我尝试使用单个查询更新多行时,记录不会更新。

我准备切换到使用 for 循环来执行多个更新,然后聚合结果并将其从服务器发送回客户端,这将是我的第二个首选。如果没有太多的性能影响,我不明白为什么不应该这样做。但我还没有找到任何这样做的例子。

var values = [
    { users: "tom", id: 101 },
    { users: "george", id: 102 }
    ];

    // var params = [values.users, values.id ];

    var sql = 'UPDATE tabletest SET users = ? WHERE id = ?;';


    connection.query(sql, [{users: values[0].users}, {id: values[0].id }], defered.makeNodeResolver());

上面显示的代码实际上并没有更新多行。我想我的语法有错误。

但无论如何,在这种特殊情况下,最好的方法是什么?准备好的语句、for 循环中的重复查询还是存储过程?

【问题讨论】:

  • 您是否尝试仅使用[values[0].users,values[0].id] 作为query() 的第二个参数?
  • 你是对的。我发现了一个语法错误。谢谢。我更改为以下内容: var sql = 'UPDATE tabletest SET ?在哪里 ?;';和 var query = connection.query(sql, [{users: values[0].users}, {id: values[0].id }], defered.makeNodeResolver());但它仍然只更新一行,而不是两者。它不应该循环遍历值对象吗?
  • 我不确定这是否适用于 UPDATE,但它可能适用于 INSERT。
  • 显然它只会更新第一行。我想知道最好的方法是什么? for 循环、准备好的语句或存储过程,另一种选择?肯定有人已经解决了这个问题。
  • @KisLeye 您是否找到了一种有效的方法?循环遍历并为每个对象发送单独的查询听起来不像是正确的方法,因为这里的大多数人都说调用堆栈最多可以达到 10k 条记录。

标签: node.js angularjs promise node-mysql


【解决方案1】:

你可以这样做:

var values = [
  { users: "tom", id: 101 },
  { users: "george", id: 102 }
];
var queries = '';

values.forEach(function (item) {
  queries += mysql.format("UPDATE tabletest SET users = ? WHERE id = ?; ", item);
});

connection.query(queries, defered.makeNodeResolver());

要使用多语句功能,您必须为您的连接启用它:

var connection = mysql.createConnection({
  ...
  multipleStatements: true,
});

【讨论】:

  • 但是作者声称多语句功能还处于实验阶段!我没有看到任何关于以这种方式更新/插入 10K 记录的反馈。
  • 这个答案有什么进展吗?我希望明天做类似的事情,并考虑将查询连接在一起。
【解决方案2】:

你应该这样做

UPDATE DB.table
SET table.row = newValue WHERE table.someColumn in ('columnVal1', 'columnVal2');

例如

UPDATE DB.Students
SET result = "pass" WHERE rollNo in (21, 34, 50);

【讨论】:

  • OP 正在讨论从 NodeJS 更新
  • 这对我有帮助,因为我正在尝试在前端执行此操作,并且只发送一个 id 数组,它会按照预期的方式进行操作
【解决方案3】:

不知道这个问题是否仍然相关,但我会给我 2 美分:

我找到的解决方案是使用Promise.all

基本上你需要构建一个promise数组,其中每个promise都是一个更新语句:

const getUpdatePromise = (row) => {
  return new Promise( (resolve, reject) => {
    mysqlConnection.query('UPDATE tableName SET foo = ? WHERE bar = ?', [row[0], row[1], (error, results, fields) => {
      if (error) reject(error)
      resolve(results)
    });
  })
}

您将这个新的 Promise 添加到一个数组中,并将包含所有更新语句的最终数组传递给 Promise.all 函数。

它对我有用。希望它适用于其他人。

【讨论】:

    【解决方案4】:

    let query = "";
    query += "UPDATE `DBNAME` SET `field1` = `Value`, `field2` = CASE";
    `Field3Array`.forEach((item, index) => {
     query += " WHEN `field3` = '" + item + "' THEN '" + `Field2Array[index]` + "'";
    });
    query += " END";
    query += " WHERE `field3` IN (" + "'" + `Field3Array`.join("','") + "'" + ")";
    
    sql.query(query, function (err, rows) {
        if (err) {
            console.log(err)
        } else {
            console.log(rows)
        }
    });
    

    在这里,field1 & field 2 需要更新,field3 是'where'子句。 结果无疑是成功的。 我希望这个答案对使用mysql查询一次更新多行中的多个字段有很大帮助。

    【讨论】:

    • 逃跑怎么办?
    • 返回 res.status(200).send({});
    【解决方案5】:

    我认为您不能(至少轻松/有效地)以您尝试的方式更新多行。您基本上必须遍历您的 values 并为每个对象执行 UPDATE。

    【讨论】:

      【解决方案6】:

      这段代码取自 node.js 的 vcl.js,它是用 typescript 编写的,并在单个事务中提供了多个更新、删除、插入语句。

      export class SQLStatment {
          sql: string;
          params: Object
      }
      
      var dbError: string;
      var execCount: number = 0;
      function DBexecuteBatchMYSQLSingle(connection: any, SQLStatmentArray: Array<SQLStatment>, index: number, callback: () => void) {
          execCount++;
          connection.query(SQLStatmentArray[index].sql, SQLStatmentArray[index].params, function (err, rows, fields) {
              if (err) dbError = err;
              if (index + 1 == SQLStatmentArray.length) callback();
              else {
                  if (!dbError) {
                      DBexecuteBatchMYSQLSingle(connection, SQLStatmentArray, index + 1, function () {
                          if (index == 0) callback();
                      });
                  }
              }
          });
      }
      
      function DBBatchUpdateMYSQL(SQLStatmentArray: Array<SQLStatment>, callback?: (err) => void) {
          var mysql = require('mysql');
          var connection = mysql.createConnection({
              host: "host",user: "user",database: "db",
              port: 1022, password: "pass"});
          dbError = null;
          execCount = 0;
          connection.beginTransaction(function (err) {
              if (err && callback) callback("Database error:" + err);
              else {
                  DBexecuteBatchMYSQLSingle(connection, SQLStatmentArray, 0, () => {
                      if (dbError) {
                          connection.rollback(function () {
                              if (callback) callback("Database error:" + dbError);
                          });
                      } else {
                          connection.commit(function (err) {
                              if (callback) callback(null);
                          })
                      }
                  });
              }
          });
      }
      

      【讨论】:

      • 递归调用应该可以工作。但是,如果要更新/插入 10K 行,可能会遇到“最大回调堆栈”问题。
      【解决方案7】:

      使用multipleStatements: true 的更简单的解决方案:

       function multiupsert(table, cadena) {
      return new Promise((resolve, reject) => {   
      
      
          var queries = '';
          cadena.forEach(function (item) {
               console.log(item)
              queries += `UPDATE ${table} SET descripcion = '${item.descripcion}',costo = '${item.costo}',estado = '${item.estado}' WHERE id = ${item.id} ; `
            });
            
            let conesM=getConectionMulti();
            conesM.connect();
            conesM.query(queries, (err1, result, fields) => {
              if (err1) return reject(err1)
                  resolve(result.insertId);  
                  console.log(result);
                  conesM.end();   
              });
      
      })
      

      }

      【讨论】:

        猜你喜欢
        • 2020-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-13
        • 1970-01-01
        • 2019-11-10
        • 2011-08-18
        • 1970-01-01
        相关资源
        最近更新 更多