【问题标题】:How to insert multiple rows with a parameter?如何使用参数插入多行?
【发布时间】:2015-07-22 18:11:00
【问题描述】:

我正在尝试使用 ionic 框架在 SQLite 中插入多行。单行插入工作正常。

即使我跑了

 INSERT INTO categories (category_id, category_name,category_type) VALUES (1,"test",1),(2,"test again", 2); 

这也很好用。 但是当我尝试创建一个动态字符串时,它给了我错误“无法准备语句(1 靠近”?“:语法错误)”。

.success((function (result) {
                 var query = "INSERT INTO categories (category_id, category_name,category_type) VALUES ?";
                 var data = [];
                 result.forEach(function (category) {
                         data.push([category.id, category.category_name, category.category_type]);
                     });
    $cordovaSQLite.execute(db, query,[data]).then(function (res) {
         console.log("inserted");
     }, function (err) {
   console.dir(err);
    });

【问题讨论】:

  • 你加了一个?即使您说将插入三列。这行不通。
  • 我将数据作为数组传递

标签: javascript angularjs node.js sqlite ionic-framework


【解决方案1】:

向您的插入添加多个参数,就像您在测试查询中所做的一样(您提到的第一个),然后将所有参数作为一维数组传递:

.success((function (result) {
                 var query = "INSERT INTO categories (category_id, category_name,category_type) VALUES ";
                 var data = [];
                 var rowArgs = [];
                 result.forEach(function (category) {
                         rowArgs.push("(?, ?, ?)");
                         data.push(category.id);
                         data.push(category.category_name);
                         data.push(category.category_type);
                     });
                 query += rowArgs.join(", ");
    $cordovaSQLite.execute(db, query,[data]).then(function (res) {
         console.log("inserted");
     }, function (err) {
   console.dir(err);
    });

此代码将产生如下查询:

INSERT INTO categories (category_id, category_name,category_type) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?), (?, ?, ?);

您的数据数组大小为 12,其中数组中的每 3 个条目将是要插入的一行数据。

这些数字只是示例,它们取决于result 的大小。

【讨论】:

  • 在语句字符串中获取 '?' 的错误编号与参数计数不匹配
  • 我的循环执行了 40 次
  • console.log(data.length);console.log(query); - 看看一切是否正常
  • 长度为184,查询为INSERT OR IGNORE INTO类别(category_id, user_id, category_name,category_type) VALUES
  • 您不必将其粘贴到此处。只计算“?”的数量在查询中,看看它是否等于 184。提示:使用console.log((query.match(new RegExp("\\?", "g")) || []).length);
【解决方案2】:

这似乎是一种方法:

var query = "INSERT INTO categories (category_id,category_name,category_type) VALUES (?,?,?)";

...

.success((function (result) {

$cordovaSQLite.transaction(function(tx){

   result.forEach(function (category) {
      tx.executeSql(query, [category.id, category.category_name, category.category_type]);
   });
}).success(function(){

  .....
});

我也见过这种方法:

$cordovaSQLite.execute("BEGIN IMMEDIATE TRANSACTION");
result.forEach(function (category) {
    $cordovaSQLite.executeSql(query, [category.id, category.category_name, category.category_type]);
       });
$cordovaSQLite.execute("COMMIT TRANSACTION");

【讨论】:

  • 我猜这种方法似乎不太好。如果我有 10000 个循环,它将在 db 中插入每一行 10000 次。我想一次插入所有记录。 +1 第二种方法
  • @HituBansal。第二种方法发生了什么?
  • @HituBansal,当您说插入 1000 次时,您的意思是它从客户端到服务器进行 1000 次往返,还是进行 1 次往返,然后将行写入 1000 次不同的时间那一次往返?
  • 它将循环 1 次,我将获得 1000 行。我说的是客户端。根据你的代码。 $cordovaSQLite.executeSql, tx.executeSql 会执行 1000 次。即将行插入数据库。我非常接近 Googie 的答案。
  • @HituBansal,如果它进行 1 次往返并插入 1000 次,这正是它应该如何工作的。往返的费用很高。您仍然需要为 1000 行插入 1000 次。这永远不会改变。
【解决方案3】:

不能使用数组作为参数值。

你必须为三列创建一个带有三个参数的 SQL 命令字符串,并多次执行。

为确保效率,您必须在单个事务中完成所有 INSERT。

【讨论】:

  • 多次执行不是优化方式。我们不能单次插入吗?
  • AFAIK 这些 JavaScript 框架都不支持准备好的语句。
  • @DaveAlperovich:我也不同意 CL 的观点
  • @DaveAlperovich 我不是在谈论事务(就事务而言,我同意你的观点),而是关于 execute() 是否可以处理任意数量的行。 JavaScript 没有 Python 的 executemany() 等价物。
  • 嗯,他可以通过 Googie 的回答几乎实现了他的要求。但这似乎是 XY problem
【解决方案4】:

在任何情况下,在代码中编写原始 sql 查询都是一种不好的做法。是否可以将某些节点 ORM 与离子框架一起使用?比如node-orm2:https://github.com/dresende/node-orm2

在这种情况下,您的解决方案将如下所示:

var data = [];
result.forEach(function (category) {
    data.push({'id' : category.id, 'name' : category.category_name, 'type' : category.category_type});
});

Category.create(data, function (err, items) {
    // err - description of the error or null
    // items - array of inserted items
});

【讨论】:

    【解决方案5】:

    离子 2、角度 2 和打字稿

    import {Platform, NavController, NavParams, Storage, SqlStorage} from 'ionic-angular'`;
    
    //SqlStorage uses SQLite or WebSQL (development only!) to store data in a
    // persistent SQL store on the filesystem.
    //automatically
    
    public  getDB() {
    
            // if (this.platform.is('cordova')) {
            // } else {
            this.db = new Storage(SqlStorage, {name: this.db_name});
            this.db = this.db._strategy._db;
            // }
            return this.db;
        }
    
    
    
    query(sql:any, params:any = []) {
    return new Promise((resolve, reject) => {
    
                    try {
    
                        console.log('query try');
    
                        this.getDB().transaction((transaction) => {
    
                            transaction.executeSql(sql, params, (transaction, success) => {
                                // resolve(this.fetchAll(success));
                                resolve(success);
    
                            }, (transaction, error) => {
    
                                reject(error);
    
                            });
    
                        });
    
    
                    } catch (error) {
                        console.log("Unable to open database,", +error);
                        reject(error);
                    }
    
                });
    }
    

    【讨论】:

      【解决方案6】:

      @Googie

      感谢您的解决方案。 但是我在插入数据时遇到了问题,结果发现这一行:

      $cordovaSQLite.execute(db, query,[data])...

      是问题所在。解决方案是编写不带括号的数据,如下所示:

      $cordovaSQLite.execute(db, query, data)...

      因为data 已经是一个数组了。

      认为这可能对其他人有所帮助。

      干杯

      【讨论】:

        猜你喜欢
        • 2018-01-15
        • 1970-01-01
        • 2013-01-23
        • 1970-01-01
        • 1970-01-01
        • 2020-03-30
        • 1970-01-01
        • 1970-01-01
        • 2014-08-12
        相关资源
        最近更新 更多