node-mysql how to use result outside of an anonymous function - javascript

I have a query like below:
connection.query('SELECT * FROM `Users` WHERE `Id` = ?;', [Id], function (err, row) {
var a = row;
});
//how can I use variable `a` in here?

you really won't be able to. at least not easily.
var a;
connection.query('SELECT * FROM `Users` WHERE `Id` = ?;', [Id], function (err, row) {
a = row;
});
//execute stuff
This will accomplish getting the value out into the next scope but where you would //execute stuff will have already happened before a is set. This is because (I'm assuming) node-mysql is asynchronous.

Related

Return a variable from sql query in Node.js

I have MySQL query in Node.js where I'm trying to return "variable" and assign in to getVarible OUTSIDE my query. Is it possible to do in this case? If so, how?
Here is my code :
var sqlQuery = connection.query(result, function(err, rows, fields) {
var count = rows.length;
if(count === 1){
var variable = rows[0].item;
return variable;
}
}
});
var getVariable = variable;
If you declare getVariable before your query call, you should be able to access it once your query return, within your cacllback fuction. You can try something like this:
var getVariable = {};
var sqlQuery = connection.query(result, function(err, rows, fields) {
var count = rows.length;
if(count === 1){
getVariable = rows[0].item;
}
}
});
However keep in mind that query execution is asynchronous, so your variable will be empty until your callback is executed.
So I would suggest you all logic where you use that variable to be executed within callback or use a promise of async framework.
Your connection.query does not return what you think it returns i.e. return variable; statement has no effect.
Checkout the API with the usage of query object.
var query = connection.query('SELECT * FROM posts');
query
.on('error', function(err) {
// Handle error, an 'end' event will be emitted after this as well
})
.on('fields', function(fields) {
// the field packets for the rows to follow
})
.on('result', function(row) {
// Pausing the connnection is useful if your processing involves I/O
connection.pause();
processRow(row, function() {
connection.resume();
});
})
.on('end', function() {
// all rows have been received
});
Alternatively you can have a short hand to handle the success, error by using the second parameter to connection.query. This is a function with signature function (error, results, fields) which does the same thing as above API.
connection.query(sqlQueryStr, function (error, results, fields) {})
The call to connection.query is asynchronous and the function passed as the second argument is executed only after the results are available i.e the query has executed.

NodeJS - how can get mysql result with executed query?

I am new in NodeJS with mysql (npm install mysql).
When I try to execute query like
connection.query("select ?? from users where id = ?",[["id","fname","lname"],req.body.userid],function (err, rows) {
**here I want query which above executed**
});
I want query in callback function which executed.
How can I get it??.
var c = connection.query("select ?? from users where id = ?",[["id","fname","lname"],req.body.userid],function (err, rows) {
console.log(c.sql)
});
connection.query("select ?? from users where id = ?",[["id","fname","lname"],req.body.userid],function (err, rows) {
res.send(rows);
});
also in preference swith the string query to :
"select id,fname,lname from users where id = '"+req.body.userid+"'"

Variable within for loop giving max value

EDIT: Updated with full code.
I'm writing javascript code in node.js that is meant to loop through an array of data that I have scraped from the web. The purpose of the code is to:
1) Check the player table to see if that player's name exists in a record, and
2) If that player doesn't exist, add him to the database.
Here is my code:
var cheerio = require('cheerio');
var request = require('request');
var data = [];
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'blahblah',
database: 'test',
port: 3306 });
connection.connect();
request('http://www.basketball-reference.com/friv/dailyleaders.cgi?month=12&day=28&year=2014', function(err, response, body){
if(!err && response.statusCode ==200){
var $ = cheerio.load(body);
$('td', 'tbody').each(function(){
var url = $(this).attr('href');
var text = $(this).text();
data.push(text);
});
for(i=1;i<data.length;i+=26){
var query = connection.query(
"SELECT * FROM player WHERE name = '"+data[i]+"'",function(err, result, fields) {
if (err) throw err;
if(result.length==0){
//var insertQuery = "INSERT INTO player (provider_id, team_id, position_id, name) VALUES (1, (SELECT id FROM team WHERE slug = '"+data[i+1]+"'),1,'"+data[i]+"');";
console.log(i);
}
});
}
}
});
Note that I commented out my INSERT query for testing purposes, but the player name is located in data[i] while the team name is in data[i+1].
To test, I am just printing i to the console, and every loop it prints out the max value of i, which is 3225. However, that console.log command is INSIDE the for loop, so shouldn't it print each value of i as it is incremented?
This is similar to this question: JavaScript closure inside loops – simple practical example
That answer explains the why things are acting the way they are.
This happens in closures, if you are referencing a variable in a callback and that variable was already at that max value before the callback was executed.
Here's an example of what your code is doing (bad with callbacks):
function a(){
var i = 0;
var callbacks = [];
for (i=0;i<100;i+=25){
callbacks.push(function(){
alert(i);
});
}
return callbacks;
}
var callbackArray = a();
for( f in callbackArray){
callbackArray[f]();
}
Here's what it should be doing:
function createFunction(i){
return function(){
alert(i);
}
}
function a(){
var i = 0;
var callbacks = [];
for (i=0;i<100;i+=25){
callbacks.push(createFunction(i));
}
return callbacks;
}
var callbackArray = a();
for( f in callbackArray){
callbackArray[f]();
}
For your fix, you should do something like this:
// outside of the code you posted, as a separate function.
function createPlayerSelectionCallback(data,i){
return function(err, result, fields) {
if (err) throw err;
if(result.length==0){
//var insertQuery = "INSERT INTO player (provider_id, team_id, position_id, name) VALUES (1, (SELECT id FROM team WHERE slug = '"+data[i+1]+"'),1,'"+data[i]+"');";
console.log(i);
}
}
}
// this for loop stays in the same place, just modified to use the new function.
for(i=1;i<data.length;i+=26){
var query = connection.query(
"SELECT * FROM player WHERE name = '"+data[i]+"'",createPlayerSelectionCallback(data, i))
}

JS function to count rows in SQLite table

I'm trying to make a JS function that counts rows in an SQLite table.
function countRows(){
db.transaction(function (tx){
tx.executeSql('SELECT id FROM table', [], function (tx, results) {
var len = results.rows.length;
alert(len);
});
});
}
The above code displays an alert with numbers of rows in the table. However, I'd like to make a function that would return the number instead of showing the alert box.
I tried:
function countRows(){
db.transaction(function (tx){
tx.executeSql('SELECT id FROM table', [], function (tx, results) {
var len = results.rows.length;
return len;
});
});
}
And then:
var number = countRows();
alert (number); // returns "undefined"
The above example returns "undefined", whereas a parallel example works fine:
function count(){
return 3;
}
var number = count();
alert (number); // returns 3
I want to assign the number to a variable, so I could then make another sql query, count rows in another table, and compare the two results.
In PHP this would be:
$sql1 = mysql_query('SELECT COUNT(*) FROM table1');
$rows1 = mysql_result($sql1, 0);
$sql2 = mysql_query('SELECT COUNT(*) FROM table2');
$rows2 = mysql_result($sql2, 0);
if ($row1>$row2){}
You would be served much better by changing your query.
SELECT COUNT(ID) FROM table
Plus, its an async call so that the call return is returning the callback function. You should pass your own callback function.
function countRows(callback){
db.transaction(function (tx){
tx.executeSql('SELECT id FROM table', [], function (tx, results) {
var len = results.rows.length;
callback(len);
});
});
}
db.transaction is asynchronous. returning value isn't assigned to any variable in code above. Solution is to pass callback or create custom event, which is almost the same.
Something like this:
function countRows(cb){
db.transaction(function (tx){
tx.executeSql('SELECT id FROM table', [], function (tx, results) {
var len = results.rows.length;
cb.call(this, len);
});
});
}
countRows(function (num) {alert(num)});

how can I pass argument in transaction callback function

From a tutorial code like this
function queryDB(tx) {
tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}
function querySuccess(tx, results) {
}
function errorCB(err) {
alert("Error processing SQL: "+err.code);
}
var db = window.openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
db.transaction(queryDB, errorCB);
in db.transaction i want to pass a variable as argument to queryDB function, so the code which i think of should looks like
db.transaction(queryDB(id), errorCB);
How I can actually implement this ? Or its simply gonna work like this and my id will be passed and get in tx ?
Wrap it in a function again
var id = 'THEID';
db.transaction(function(){
queryDB(id)
}, errorCB);
Note - This is assuming that you're making the API. Some APIs / frameworks insert the required information automatically. For example
//the db.transaction method
function transaction(param, callback) {
//do code stuff
callback(someInternalId); //callback is the function you pass as the first parameter
}
So, if you want to pass your own data in the callback, wrap it in a function. Otherwise, the code you are using may be doing this for you automatically.
I like to keep things very simple so I use a limited number of functions when handling storage on phonegap applications that can receive parameters. A lot of the examples I have seen have calls to many sub functions and for me, this is a nightmare when it comes to debugging.
I was caught out an a number of issues around Web SQL but reading the specs really, really helped clarify what I could and couldn't do. (http://www.w3.org/TR/webdatabase/)
Look at this simple code for an insert function:
function dbInsert(param1, param2, dbObj) {
val1 = param1;
val2 = param2;
val3 = String(dbObj.item2);
var sqlTxt = "INSERT INTO demo (geo1, geo2, geo3) VALUES (?, ?, ?)";
db.transaction(function(tx) {tx.executeSql(sqlTxt,[val1,val2,val3])}, errorCB, successCB);
}
Lets just to walk through it. Obviously a standard function which receives parameters which can be anything, in this case an object as well a strings.
sqlTxt is where the fun begins. Write this as you would normally write an insert statement, but where you would normally have the data to be inserted/selected etc in VALUES use the ? placeholder for each field in the database tables you want to pass data into.
Now lets break down the next line:
db.transaction(function(tx) {tx.executeSql(sqlTxt,[val1,val2,val3])}, errorCB, successCB);
When you create a new database, db is the handler to the database object so db.transaction asks to execute a transaction on the database db.
If we write next next section like this you can see it's function that calls tx.executeSql and because it in execute inside the db.transaction method, it will be passed the db handle.
function(tx) {
tx.executeSql(sqlTxt,[val1,val2,val3])
}
Now if we were to parse the sqlTxt it might look like this
INSERT INTO demo (geo1, geo2, geo3) VALUES ('a', 'b', 'c');
and because we are passing the three variable in place of the ? holder, it looks like the line above. And finally you call error and success callback functions.
In your case I would create a queryDB function like this:
function queryDB(id) {
var sqlTxt = "SELECT * FROM DEMO WHERE id=?"
db.transaction(function(tx) {tx.executeSql(sqlTxt,[id])}, errorCB, successCB);
}
In essence, the function grabs the parameter id, passes it into the query in the [id] and executes and returns error or success. Obviously you can extend this to use multiple parameters or if you want to be really clever, you just create a single database transaction function and pass in the sql and the parameters to use as an object or array (Example will be on my blog this weekend)
Ok first of all create a class hat will handle you're db instances (db updates etc) this class will hold a function that you will use for all you're query's
self.db = window.openDatabase( // and so on
then the function:
// execute a query and fetches the data as an array of objects
self.executeQuery = function(string, args, callback, callbackparams) {
var self = this;
//console.log('db execute: '+string);
self.db.transaction(function(tx) {
tx.executeSql(string, args, function(tx, result) {
var retval = [];
for (var i = 0; i < result.rows.length; ++i) {
retval.push(result.rows.item(i));
}
if (callback) {
callback(retval, result, callbackparams);
}
}, self.error);
});
}
then when u have initiated you're class (i named it myDb) go apeshit!
myDb.executeQuery('select l.* from location l inner join item_location il on (il.location_id = l.id and il.item_id = ?)', [item.id], function(locations, res, item){
item.locations = locations;
myDb.executeQuery('select * from media where item_id = ?', [item.id], function(media, res, item){
item.media = media;
// create item.
createItem(item);
}, item);
}, item);
as you can see the executeQuery has 4 params,
query,
params for query,
callback (with 3 params, result, status and myparam)
myparam (for callback)
It took me some time to fix this, but when you've done this! no more annoying db horror!
We can't send any paramenter for queryDB function like "queryDB(id)"
I solved this issue by this way.
var contactId = 33
dbInst.transaction(function(tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS CONTACT_REFERENCE (id unique)');
var sqlStr = 'INSERT INTO CONTACT_REFERENCE (id) VALUES (?)'
tx.executeSql(sqlStr, [contactId]);
}, errorCB, successCB);
I think everyone comes close to answering your question. Really you need one slight modification to JohnP's answer. You should pass in the SQLTransaction Object that carries the executeSQL function. So to build on John's answer:
var id = 'THEID';
db.transaction(function(tx){
queryDB(tx, id)
}, errorCB);
Then where you define the function you can grab your id param with an extra variable.
queryDB: function (tx, id) { ...your code... }
This is a worked solution:
var sqltxt= 'INSERT INTO CONTACTS(id, data) VALUES (?, ?)';
var db = window.openDatabase("Database", "1.0", "Demo", 200000);
db.transaction(function(tx){tx.executeSql('DROP TABLE IF EXISTS CONTACTS');
tx.executeSql('CREATE TABLE IF NOT EXISTS CONTACTS(name unique, password)');
tx.executeSql(sqltxt,[name, pass]);
}, errorCB, successCB);

Categories

Resources