简体   繁体   中英

How to implement nested query in sqlite3

So i have this 2-layer query in node.js, each query could return multiple results. My code actually just ignores that for now. This is the best i can get, it seems working.

  1. How to correct it please, i don't know how to callback for the 2nd one.

  2. Also the db.close() is always called before the 2nd query finishes, even i have serialize().

    var getInfo1Db = function(callback) { var db = new sqlite3.Database("DB.sqlite3");

     var cnt = 0; var info1JsonObj = []; db.all("select * from Info1DB", function(err, rows) { db.serialize(function() { for(var ii=0, len=rows.length; ii<len; ii++) { var t2 = rows[ii].info1; var doorId = ... db.all("select * from DoorDB where ObjectID=" + doorId, function(err, row2) { if(err) { } else { var doorName = row2[0]... var info1JsonElem = { "DoorName" : doorName }; info1JsonObj.push(info1JsonElem); cnt++; if(cnt === rows.length) { callback(null, info1JsonObj); } } } ); // for the only door info based on door id } // for each row of info1 db.close(); // why this finishes before the 2nd db.all } ); // end of serialize });

    };

How about using 2 function to do these ?

function db_query1(your_param,...., callback){
  // database operation
   db.run( sql , [param,...] , function(err,rows){
      if(err) // return
      else{
         // get rows with callback
         callback(null, rows);
      }
   });
}

function db_query2(your_param,...., callback){
  // database operation
   db.run( sql , [param,...] , function(err,rows){
      if(err) // return
      else{
         // get rows with callback
         callback(null, rows);
      }
   });
}

And call these function:

db_query1(....,function(err,result1){
   if(err) ...// return 
   // do the things with result1
   // And then call query2
   db_query2(....,function(err,result2){
      if(err) ...// return 
      // do the things with result1
   });
});

Hope this will help :)

You can use Promises.all , an array and the second callback for node sqlite3 db.each() that is executed when all rows have been fetched. Node Sqlite3 db.each usage to simplify the nested query and

I cannot really get the meaning of the variables you are using thus I assume that each row in Info1DB has a one-to-many relationship with DoorDB on the field doorId .

async function getInfo (callback) {
    sql = "select * from Info1DB;";
    numVersions = 0;
    countVersions = 0;
    info1JsonObj = [];
    db.serialize(function() {
        db.each(sql, [], (err, info1Row) => {
            sql = "select * from DoorDB where ObjectID=?;";
                info1Row.doors = [];
            doorId = ...
            db.each(sql, [doorId], (err, doorRow) => {
                info1Row.doors.push(new Promise((resolve, reject) => {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(doorRow);
                    }
                }));
            }, (err, num) => {
                Promise.all(info1Row.doors)
                    .then((doors) => {
                        info1Row.doors = doors;
                        info1JsonObj.push(info1Row);
                        countVersions++;
                        if (countVersions == numVersions) {
                            callback(null, info1JsonObj);
                        }
                    }).catch((err) => {
                        callback(err, null);
                    });
            });
        }, (err, versions) => {
            numVersions = versions;
        });
    });
}

You can't implement nested query in sqlite3's normal way. ( I mean you even can't do it in the callback hell way, because the sqlite3 need to close the connection before another query called. otherwise you will always got error)

You have to use Promise , async and await to do this. ( it's worth to spend 30 minutes to learn these 3 words )

Step1. define a async function like this:

async query_1() {
  new Promise(resolve => {

      db = ...
      db.serialize( () => {
        db.get('select .. from ... where id = 1', [], (error, row) => {
           // here is the KEY: put the result into resolve 
           // this equals to the "return" statement in non-sync method.
           resolve(row)
        }
      })
      db.close()
  })
}

and also implement your query_2 function like this:

async query_2() {
  let query_1_result = await this.query_1()

  db = ...
  db.serialize( () => {
    db.get('select .. from ... where dependency_id = ' + query_1_result, [], (error, row) => {
       // other code here...
    }
  })
  db.close()
}

refer to my answer: https://stackoverflow.com/a/67881159/445908

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM