【问题标题】:SQL transaction with JS Array of Objects?带有JS对象数组的SQL事务?
【发布时间】:2019-12-08 22:52:03
【问题描述】:

假设我有一个对象数组

var array = [{"name":1},{"name":2},{"name":3},{"name":4},{"name":5},{"name":6}];

现在我创建一个逗号分隔列表

      let comma_seperated_list_response = array.map(a => "'" + a + "'").join(",");

    var sql= 'INSERT INTO DOWNLOAD_LIST(name) VALUES ?';

要将其传递给 sql.transaction?

   app.db.transaction(function (tx) {
        tx.executeSql(sql, [comma_seperated_list_response],
            function (tx2, results2) {   
                console.log({results2})
                debugger;
            }, app.onError);
    });

有没有其他方法可以循环遍历数组并逐个传递对象,或者我可以传递批量数组吗?当我通过 comma_seperated_list_response 它说错误对象对象

【问题讨论】:

标签: javascript sql


【解决方案1】:

如果数组中的每个对象都应该是表中的一行,那么您要做的是SQL Insert Multiple Rows。也就是说,我们只使用一个插入命令来插入多个对象。因此,每个对象可能有许多属性,不仅是名称,还有年龄等。

因此,对于每个对象,您必须使用值 (name, age) 创建 SQL 元组。

最后,在 SQL 脚本中,它们必须在如下命令中以逗号分隔的值列表分组:

INSERT INTO DOWNLOAD_LIST(name,age) VALUES 
(1,11),
(2,22),
(3,33),
(4,44),
(5,55),
(6,66);

一种可能的方法是如下代码:

var elements = [{
  "name": 1,
  "age":11
}, {
  "name": 2,
  "age": 22
}, {
  "name": 3,
  "age": 33
}, {
  "name": 4,
  "age": 44
}, {
  "name": 5,
  "age": 55
}, {
  "name": 6,
  "age": 66
}];

let attributes = ["name","age"]; 
let attributes_list = attributes.join(",");
let values = elements.map(
  element => {
    attributes = [element.name, element.age]
    return "(" + attributes.join(",") + ")";
  }
).join(",\n");
var sql = `INSERT INTO DOWNLOAD_LIST(${attributes_list}) VALUES ${values};`;
console.log(sql);

但是,这对于 SQL 注入来说仍然很脆弱。所以,让我们尝试类似于What are Best Practices for preventing SQL injection in node-mysql? 的这些建议:

    var elements = [{
      "name": 1,
      "age":11
    }, {
      "name": 2,
      "age": 22
    }, {
      "name": 3,
      "age": 33
    }, {
      "name": 4,
      "age": 44
    }, {
      "name": 5,
      "age": 55
    }, {
      "name": 6,
      "age": 66
    }];

    let attributes = ["name","age"];
    let binds = elements.map(
      (element,key) => {
        attributes = [':name_'+key, ':age_'+key]
        return "(" + attributes.join(",") + ")";
      }
    ).join(",\n");
    let attributes_list = attributes.join(",");
    
    let values = elements.map(
      (element,key) => {
        let key_name = ':name_' + key;
        let key_age = ':age_' + key;
        let obj = {};
        obj[key_name] = element.name;
        obj[key_age] = element.age;
        return obj;
      }
    );
    let valuescombined = values.reduce(
      (a,b) => {
         return {...a,...b};
      }
    );
    var sql = `INSERT INTO DOWNLOAD_LIST(${attributes_list}) VALUES ${binds};`;
    console.log(sql);
    console.log(valuescombined);

此命令应创建绑定 SQL 命令和指向每个值的值:

INSERT INTO DOWNLOAD_LIST(:name_5,:age_5) VALUES (:name_0,:age_0),
(:name_1,:age_1),
(:name_2,:age_2),
(:name_3,:age_3),
(:name_4,:age_4),
(:name_5,:age_5);
{
  ":name_0": 1,
  ":age_0": 11,
  ":name_1": 2,
  ":age_1": 22,
  ":name_2": 3,
  ":age_2": 33,
  ":name_3": 4,
  ":age_3": 44,
  ":name_4": 5,
  ":age_4": 55,
  ":name_5": 6,
  ":age_5": 66
}

【讨论】:

    【解决方案2】:

    您的问题是您想将一个对象(例如{"name":1})传递给您的地图,然后它将以'{"name":1}' 之类的方式结束,然后您应用连接,这是错误的。

    你想要的东西如下:

    var array = [{
      "name": 1
    }, {
      "name": 2
    }, {
      "name": 3
    }, {
      "name": 4
    }, {
      "name": 5
    }, {
      "name": 6
    }];
    let comma_seperated_list_response = array.map(a => "'" + a.name + "'").join(",");
    console.log(comma_seperated_list_response)
    var sql = 'INSERT INTO DOWNLOAD_LIST(name) VALUES ?';

    但如果你想像 SQL 调用那样分离变量和值,你可以这样做:

    var array = [{
      "name1": 1
    }, {
      "name2": 2
    }, {
      "name3": 3
    }, {
      "name4": 4
    }, {
      "name5": 5
    }, {
      "name6": 6
    }];
    
    let names = '';
    let values = '';
    
    array.forEach((entry, i, a) => {
      Object.keys(entry).forEach((k) => {
        let coma = ', ';
        if (i === a.length - 1) {
          coma = ''
        }
        names += `${k}${coma}`;
        values += `${entry[k]}${coma}`
      })
    })
    
    var sql = `INSERT INTO DOWNLOAD_LIST(${names}) VALUES (${values})`;
    console.log(sql)

    【讨论】:

      【解决方案3】:

          var elements = [{
            "name": "1",
            "age":11
          }, {
            "name": "2",
            "age": 22
          }, {
            "name": 3,
            "age": 33
          }, {
            "name": 4,
            "age": 44
          }, {
            "name": 5,
            "age": 55
          }, {
            "name": null,
            "age": 66
          }];
      
      
          let vals = elements.map(Object.values).map(a=>"(" +a+ ")").join(",");
          console.log("vals:"+vals);

      我现在使用将对象转换为数组的 Object.values 将代码减少到 2 行。但我仍然得到一个错误:[object Object]

      【讨论】:

        猜你喜欢
        • 2021-10-09
        • 2021-07-08
        • 2022-06-28
        • 2017-12-08
        • 2018-09-24
        • 2019-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多