How to update multiple rows in mysql using node js - mysql

I am facing problem while updating multiple rows in table.
following is my data
const update_Data = upins_data.map(
upins_data => [{
upin_id: upins_data.upin_id,
media_type: upins_data.media_type,
land: upins_data.land
}]
);
it has multiple values.
i have tired following code
var updateSecTab = `UPDATE tb_bid_upins SET upin_id=?,media_type=?,land=? WHERE bid_id = ?`;
var query = db.query(updateSecTab,[update_Data,cond],function(error,result,fields){
if (error) { /**If error while inserting into table 2 it rowback the Transaction */
console.log('in err 1');
return db.rollback(function () {
throw err;
});
}
db.commit(function (err, result3) {
if (err) {
console.log('in err 2');
return db.rollback(function () {
throw err;
});
}
/**Send success result to front end */
console.log('success!');
res.send(JSON.stringify(result));
})
});
console.log(query.sql);
When i print the query it gives result as follows
UPDATE tb_bid_upins SET upin_id=('[object Object]'), ('[object Object]'),media_type=1,land=? WHERE bid_id = ?

Hello everyone i have tried following solution and it works.
var upins_data = [ { upin_id: 1, media_type: 5, land: 'Rakhiyal Circle' } ],
[ { upin_id: 3, media_type: 6, land: 'Rakhiyal Circle' } ]
var cond = 1
i have added above two variable in single array as follows
const update_Data = upins_data.map(
upins_data => {
return {
bid_id: cond,
upin_id: upins_data.upin_id,
media_type: upins_data.media_type,
land: upins_data.land
}
}
);
than i have used foreach on update_Data array and i have created multiple sql quires using mysql foramt function.
var queries = '';
update_Data.forEach(function (item) {
let sql = mysql.format("UPDATE tb_bid_upins SET upin_id=?,media_type=?,land=? WHERE bid_id = ? ;", [item.upin_id,item.media_type, item.land, item.bid_id]);
queries += sql;
console.log(sql);
});
than i have passed above queries variable in sql query as follows
db.query(queries,(err,result)=>{
if(err){
console.log('err',err);
}else{
console.log('result',result);
}
});
above code works for me in nodejs .
if anyone wants to improve than they can.
thank you

Related

Is it possible to use one specific mysql result as an object ? NodeJS

I got my MySQL data printed in console.log() as console.log(result) and it works fine.
Now I need to use this result to define variable MyPlan in a different function.
This is how I got the results from MySQL db:
function load() {
var MySQL = SQL.createConnection(credentials)
MySQL.connect((err) => {
if(err) {
console.log(err);
process.exit(0);
}
for(var i = 0; i < 250; i++) console.log('\n');
console.log('Successfuly logged in!');
});
MySQL.query("SELECT plan FROM users WHERE username = 'asd123'", (err, rows) => {
if(err) { console.log(`[!] SQL Error: ${err}`); return; }
rows.forEach((results) => {
console.log(results); //output: RowDataPacket { plan: 300 }
});
});
}
load();
I need MyPlan: to be declared with a number 300 as stated above.
startMyPlan() {
//var theoric = 10;
this.botCountInt = setInterval(() => {
let json = {
connected: 0,
MyPlan: //300
};
this.send(json);
}, 100);
}
I tried to define results in first function like this:
rows.forEach((results) => {
myresult = results //first option
// OR LIKE THIS:
this.myresult = results; //second option
console.log(results);
});
and write it in startMyPlan() as
let json = {
connected: 0,
MyPlan: this.myresult
};
But first option gave me error myresult is not defined and second option gave me different error: Cannot set properties of undefined(setting 'myresult').
EDIT: I guess my problem is that results won't give me correct output OUTSIDE that function where it's created. It returns undentified when I try to run console.log(results); once it's run outside load() function
So, as per my understanding, you have not defined the myresult variable in any scope.
The first option will work if you do var myresult=undefined just before rows.forEach((results) => call.
One example:
var rows = [{ "test": "foo1" }, { "test": "foo2" }, { "test": "foo3" }, { "test": "foo4" }];
var myresult;
rows.forEach((results) => {
myresult = results //first option
console.log(myresult);
});
console.log(myresult);
I am not sure what exactly you want to do with myresult. But I think above example will be enough to understand things.

Loop queries sequilze in node js

I have a loop where I am checking if records exist and if not insert it , the problem is my console shows code inside loop doesn't run line by line , it runs all selects first and then run all inserts
loop from excel
tablesdata.map(async function (table) {
check if record exist
await product_meta
.count({
where: [
{
title: fr_name,
language_id: 2,
},
],
})
.then((count) => {
console.log(count);
if (count > 0) {
console.log(count);
} else {
insert record create_pr = products.create(product, {});product_id = create_pr.id;
}
)}
)}
It will be more straightforward to use async/await - the Array.map() is returning an array of promises that can be resolved using Promise.all().
const promises = tablesdata.map(async function (table) {
if (recordExists) {
const count = await product_meta.count({
where: {
title: fr_name,
language_id: 2,
},
});
if (!count) {
// this will create a new product, perhaps it is meant to be a product meta?
const create_pr = await products.create(product, {});
// return the created ID
return create_pr.id;
}
console.log("there are already", count, "product metas");
return null;
}
});
// this will resolve an array of newly created IDs,
const allResults = await Promise.all(promises);
// filter out the null entries
const productIds = allResults.filter((result) => result);

Is there a way to pass a value from a mysql callback function to the outer function in express?

I'm using express and npm MySQL to develop an API.I have a json request in this format:
{
"payments":[
{
"PolicyNo": "ME3",
"PaymentDate": "2019-04-16T18:00:00.000Z",
},
{
"PolicyNo": "PIN001q",
"PaymentDate": "2019-04-16T18:00:00.000Z",
}]
}
I want to check the database if the policyNo exists before inserting. To avoid the common ERR_HTTP_HEADERS_SENT, I've looped through the payments querying the database with the PolicyNo. If it exists it's pushed into a success array if it doesn't it's pushed into a failed array.
This works perfectly but I can't access these arrays outside the callback.
Here's what I've tried:
router.post('/bla', (req, res)=>{
const values = []
const failedvalues = []
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?'
req.body.payments.forEach(element => {
connection.query(sql,element.PolicyNo,(err, rows) =>{
if(!err){
if(rows && rows.length > 0){
values.push(element.PolicyNo, element.PaymentDate)
}else{
failedvalues.push(element.PolicyNo)
}
}
})
})
res.json({
failed:failedvalues,
success:values
})
})
Here's the response I'm getting:
{
"failed": [],
"success": []
}
This has some major problems, mostly conceptually.
Firstly the forEach is synchronous will be called payments.length number of times, but the sql query is Asynchronous so it will complete in the future.
I think you are confused between synchronous and asynchronous functions and how they work.
But you can solve this (in your case) atleast two ways.
1) Use the IN syntax and get the array. Iterate over it and do stuff. "SELECT PolicyNo from pinclientinfo WHERE PolicyNo in (...)"
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo IN (' + Array(req.body.payments).fill('?').join(',') + ')'
const policies = req.body.payments.map(p => p.PolicyNo);
const values = [];
const failedvalues = [];
connection.query(sql, ...policies, (err, rows) => {
//now check each row..
rows.forEach(element => {
//Not optimized only depicts logic
///do stuff
/// like fill values and failedvalues
if(policies.indexOf(element.PolicyNo) > -1){
values.push(...)
}else{
failedvalues.push(...)
}
});
res.json({
failed: failedvalues,
success: values
})
})
Which will be 1 DB call.
2) The other approach is (not very good) doing multiple db calls and check for count.
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?'
let count = 0;
req.body.payments.forEach(element => {
connection.query(sql, element.PolicyNo, (err, rows) => {
if (!err) {
if (rows && rows.length > 0) {
values.push(element.PolicyNo, element.PaymentDate)
} else {
failedvalues.push(element.PolicyNo)
}
}
// check If all Complete
count+=1;
if(count === req.body.payments){
//all complete
res.json({
failed: failedvalues,
success: values
})
}
})
})
BUT SERIOUSLY, USE PROMISE. USE ASYNC/AWAIT USE THOSE SWEET LITTLE FEATURES ES6 GIVES YOU
Check out: this post
because connection.query is asynchronous, so return:
{
"failed": [],
"success": []
}
use promise and await you can synchronized resolve mysql data
use Promise.all() you can synchronized resolve list of promise
router.post("/bla", async (req, res) => {
let values = [];
let failedvalues;
let promises = [];
let sql = "SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?";
req.body.payments.forEach(element => {
promises.push(
new Promise(function(resolve, reject) {
connection.query(sql, element.PolicyNo, (err, rows) => {
if (!err) {
if (rows && rows.length > 0) {
values.push(element.PolicyNo, element.PaymentDate);
} else {
failedvalues.push(element.PolicyNo);
}
}
resolve();
});
})
);
});
await Promise.all(promises);
res.json({
failed: failedvalues,
success: values
});
});

nodejs mysql queries showing only one records instead of all records in the database

Am trying to retrieve all the database records from a table called post using node js but the problem is that only one record is retrieved instead of all.
In php I can use while() loop to loop through the database record to get all data.
Currently, I do not know how to neatly loop through the database in nodejs to get all the records from database. Some Stackoverflow scholars suggest using await/async method but i do not know to to implement it on the code below to make it work. can someone help me fix the issue.
var connection = require('./config');
module.exports.getpost = function (req, res) {
connection.query('SELECT * FROM posts', function (error, results, fields) {
if (error) {
console.log('error');
res.json({
status : false,
message : 'there are some error with the query'
});
} else {
var postid = results[0].id;
var title = results[0].title;
var content = results[0].content;
var type = -1;
console.log(title);
// Checking user status
connection.query('SELECT count(*) as cntStatus,type FROM like_table WHERE userid= ? and postid=?', [userid,postid], function (error, results, fields) {
if (error) {
console.log('error');
res.json({
status : false,
message : 'there are some error with the query'
});
} else {
var total_count = results[0].cntStatus;
if(total_count > 0){
type = results[0].type;
}
var total_count = results[0].cntStatus;
var result = {
"id" : postid,
"title" : title,
"content" : content,
"type" : type,
"likes" : total_count
};
console.log('query okay');
res.json({
//data:results,
data : result
});
}
});
}
});
}
I'm assuming you're using mysql npm. In that case I'm not sure what is the problem in your case. Results param is an array of rows returned by your select statement. So you can use loop to iterate trough all the rows.
You don't actually need to use async/await (which doesn't have any advantage in terms of functionality but looks cleaner). But if you want to get rid of callbacks you need to wrap connection query into a promise or use mysql2 npm which has promise interface. Here is how you can iterate trough all the rows from your select using async/await instead of callback:
var connection = require('./config');
module.exports.getpost = async function (req, res) {
try {
const queryResult = await query('SELECT * FROM posts');
queryResult.forEach(row => {
console.log(row.title);
})
} catch (err) {
console.log('error');
res.json({
status: false,
message: 'there are some error with the query'
});
}
}
Please note that you need to use nodejs 8 to run the code with async/await.
Also you don't need to do another query inside of your posts query, you can merge those two using SQL join
async waterfall - Runs an array of functions in series, each passing their results to the next in the array. However, if any of the functions pass an error to the callback, the next function is not executed and the main callback is immediately called with the error.
var connection = require('./config');
var async = require('async');
module.exports.getpost = function (req, res) {
var arrayOfFuncs = [];
var func_1 = function(callback) {
connection.query('SELECT * FROM posts', function (error, results, fields) {
if (error) {
console.log('error');
callback(error, null);
} else {
var toPass = {};
toPass.postid = results[0].id;
toPass.title = results[0].title;
toPass.content = results[0].content;
toPass.type = -1;
callback(null, toPass);
}
})
}
arrayOfFuncs.push(func_1);
var func_2 = function(prevData, callback) {
connection.query('SELECT count(*) as cntStatus,type FROM like_table WHERE userid= ? and postid=?', [userid,prevData.postid], function (error, results, fields) {
if (error) {
console.log('error');
callback(error, null);
} else {
var total_count = results[0].cntStatus;
if(total_count > 0){
type = results[0].type;
}
var total_count = results[0].cntStatus;
var result = {
"id" : postid,
"title" : title,
"content" : content,
"type" : type,
"likes" : total_count
};
console.log('query okay');
callback(null, result);
}
});
}
arrayOfFuncs.push(func_2);
async.waterfall(arrayOfFuncs, function(errString, finalResult) {
if(errString) {
return res.send(errString);
} else {
return res.send(finalResult);
}
});
}

How to return a nested json in node.js mysql in a single query

I'm trying to create an api that will return a nested json, coming from two related tables student and studentSubjects
[{
id:"1",
name: "John",
subjects: [{
id:"1",
subject: "Math"
},
{
id:"2",
subject: "English"
}
]
},
{
id:"2",
name: "Peter",
subjects: [{
id:"1",
subject: "Math"
},
{
id:"2",
subject: "English"
}
]
}]
My code looks like this:
this.get = function(res){
db.acquire(function(err, con){
con.query('SELECT * FROM students', function(err, results){
if (err){
res.send({status: 0, message: 'Database error'});
}else{
res.send({status: 1, data: results});
}
})
con.release()
})
}
I know the query should have joins, but it only returns single row. I tried also to make a loop, it won't work because its async
Thanks for your help!!
You cannot create a nested JSON from a MySQL query because it will always return a flat result.
Anyway, to create a nested JSON you should create multiple queries and insert the corresponding array object where needed.
You should really consider using Promises for creating nested queries because it will allow you to make asynchronous operations back to back.
Below code will also close the connection if an error occurs in any of the queries.
PS: I explained each step in the comments in the code below
Imagine having a database called 'School' and three tables called 'Student', 'Subject' and 'Link_student_subject'.
// Instantiate mysql datase variables
const mysql = require( 'mysql' );
const config = {
host : 'localhost',
user : 'root',
password : 'root',
database : 'school'
}
var connection;
// Instantiate express routing variables
const express = require('express');
const router = express.Router();
module.exports = router;
// Wrapper class for MySQL client
// - Constructor creates MySQL connection
// - Connection opened when query is done
// - Promise is resolved when executing
// - Promise returns reject in case of error
// - If promise resolved rows will be the result
class Database {
constructor( config ) {
this.connection = mysql.createConnection( config );
}
query( sql, args ) {
return new Promise( ( resolve, reject ) => {
this.connection.query( sql, args, ( err, rows ) => {
if ( err )
return reject( err );
resolve( rows );
} );
} );
}
close() {
return new Promise( ( resolve, reject ) => {
this.connection.end( err => {
if ( err )
return reject( err );
resolve();
} );
} );
}
}
// Function that will execute a query
// - In case of an error: ensure connection is always closed
// - In case of succes: return result and close connection afterwards
Database.execute = function( config, callback ) {
const database = new Database( config );
return callback( database ).then(
result => database.close().then( () => result ),
err => database.close().then( () => { throw err; } )
);
};
// Instantiate Database
var database = new Database(config);
// Express routing
router.get('/students', function (req, res) {
// Variables - Rows from Students & Subjects & Link_student_subject
let rows_Students, rows_Subjects, rows_Link_Student_Subject;
// Create a Promise chain by
// executing two or more asynchronous operations back to back,
// where each subsequent operation starts when the previous operation succeeds,
// with the result from the previous step
Database.execute( config,
database => database.query( "select a.*, null as subjects from student a" )
.then( rows => {
rows_Students = rows;
return database.query( "select * from subject" )
} )
.then( rows => {
rows_Subjects = rows;
return database.query( "select * from link_student_subject" )
} )
.then( rows => {
rows_Link_Student_Subject = rows;
} )
).then( () => {
// Create your nested student JSON by looping on Students
// and inserting the corresponding Subjects array
for (let i = 0; i < rows_Students.length; i++) {
let arraySubjects = [];
for (let x = 0; x < rows_Link_Student_Subject.length; x++) {
if(rows_Students[i].id == rows_Link_Student_Subject[x].id_student){
arraySubjects.push(searchObjInArray(rows_Subjects, "id", rows_Link_Student_Subject[x].id_subject));
}
}
rows_Students[i].subjects = arraySubjects;
}
res.send(JSON.stringify(rows_Students));
} ).catch( err => {
// handle the error
res.send(err);
});
});
// Function - search if object in array has a value and return that object
function searchObjInArray(array, arrayProp, searchVal){
let result = null;
let obj = array.find((o, i) => {
if (o[arrayProp] == searchVal) {
result = array[i];
return true; // stop find function
}
});
return result;
}
If you run this code with node and go to "127.0.0.1/students" it will return exactly the same JSON as in your question.
All credits and extra info on MySQL and promises - https://codeburst.io/node-js-mysql-and-promises-4c3be599909b
MySQL 5.7+ has a JSON datatype that you can leverage for your "subjects" field. Here's a great tutorial on how to use that:
https://www.sitepoint.com/use-json-data-fields-mysql-databases/