I have a problem with SQL in node.js.
I have an array 'data' which contains some data returned from the async function and I want to put it into MySQL database if there's no result with the same data. There are some duplicated objects in array but I want to put just one into database.
Function example:
async function data_name(param){
var data = [];
data.push({
name: param,
sname: 'sname',
url: 'url',
report: 'report'
});
return data;
}
Then I run following code:
var data = await data_name('name');
data.forEach(item=>{
var chk = "SELECT * FROM `?` WHERE `name` = ? AND `sname` = ?;";
con.query(chk, [tablename, item.name, item.sname], function(er,items){
if(er) throw er;
if(items.length < 1){
var insert = "INSERT INTO `?` (name, sname, url, report) VALUES (?,?,?,?)";
con.query(insert, [tablename, item.name, item.sname, item.url, item.report], function(erg,added){
if(erg) throw erg;
console.log('Item added: ' + item.name);
});
}
else{
if(items[0].report != item.report){
var upd = "UPDATE `?` SET report = ? WHERE id = ?";
con.query(upd, [tablename, item.report, items[0].id], function(ere,edited){
if(ere) throw ere;
console.log('Item updated: ' +items[0].name);
});
}
}
//broken code below
var adc = "SELECT * FROM `links` WHERE `link` = ?;";
con.query(adc, item.url, function(erc, results){
//tried also with: results[0] === undefined || results[0] === null
var test = item.url + ' ' + results.length;
console.log(test);
if(results.length < 1){
var add_c = "INSERT INTO `links` (link_name, link_url) VALUES (?,?)";
con.query(add_c, [item.name, item.url], function(era, a_link){
if(era) throw era;
});
}
else{console.log('Record exists');}
});
});
});
The first SQL works great: it inserts all records to database, there are no duplicates and it updates values if it is required.
Second SQL (mentioned by a comment in code that I put before) doesn't work properly if the database is empty. It duplicates records in database (after running it database has 470 records while every record is duplicated about 8 times).
test variable prints for eg:
https://google.com 0
https://google.com 0
https://facebook.com 0
https://facebook.com 0
https://google.com 1
https://facebook.com 0
https://google.com 0
The problem exists only if a database is empty (if I run the code second time, the second SQL doesn't insert records new records and print in console 'Record exists'
Any ideas what can be reason of that?
Related
I'm using MySQL with NodeJS and I'm just pretty new.
I want to UPDATE col value if it's null else UPDATE for another col.
Simply like that: If col1 is null UPDATE else UPDATE col2.
app.post('/api/update', (req, res) => {
const convidn = req.body.conversationid
const currentuser = req.body.current
var sql = "UPDATE messages SET whodeleted='"+currentuser+"' WHERE converid = '" + convidn + "'";
That overwrites column value. I just want to if "whodeleted" is not null UPDATE for "whodeleted2" colum.
db.query(sql, (err, result) => {
if (err) throw err;
console.log("Number of records deleted: " + result.affectedRows);
});
})
You can do something like this
But your code is vulnerable to sql inject please read Preventing SQL injection in Node.js to so how you can avoid it
UPDATE messages
SET
whodeleted = CASE
WHEN whodeleted IS NULL THEN ?
ELSE whodeleted
END,
col2 = CASE
WHEN whodeleted IS NULL THEN col2
ELSE 'test'
END
WHERE
converid = ?
I am having the following JavaScript Procedure:
CREATE PROCEDURE ADD_OBSERVATION_VALUES()
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
arr = [];
// Get number of rows
//var query = "SELECT COUNT(*) FROM #ingest_stg/load (file_format => 'csv_format', pattern => '.*[.]csv.gz') t";
var query = "SELECT * FROM IYCF_TEMP";
var stmt = snowflake.createStatement( {sqlText: query} );
var rows_result = stmt.execute();
// rows_result.next();
// num_rows = rows_result.getColumnValue(1);
var row_num = 1;
var record_source = 'ONA'
// Set the indicators
COLUMN_FIELD_NAMES = ['beneficiary',
'nbr_1st_cons_6mc_iycfc number',
'followup_2nd_time_6mc_iycfc'];
while(rows_result.next()){
for (var col_num = 0; col_num<COLUMN_FIELD_NAMES.length; col_num = col_num+1){
var col_name = COLUMN_FIELD_NAMES[col_num];
var query = "INSERT INTO LINK_OBSERVATION_FIELD(FIELD_NAME_OBSERVATION_HASH_KEY, LOAD_DT, RECORD_SRC, OBSERVATION_DATE_LOCATION_HASH_KEY, INDICATOR_HASH_KEY)"
query += "VALUES (md5(concat(COLUMN_FIELD_NAMES[col_num], rows_result['date'])), current_timestamp(), record_source, md5(rows_result['date']), md5(COLUMN_FIELD_NAMES[col_num]))";
var stmt = snowflake.createStatement( {sqlText: query} );
if(stmt.execute()){
var query = "INSERT INTO SAT_FIELD_VALUES(OBSERVATION_FIELD_HASH_KEY, LOAD_DT, LOAD_END_DT, record_src, FIELD_VALUE, REVIEW_STATUS, SUBMISSION_DT, FIELD_NAME_OBSERVATION_HASH_KEY)"
query += "VALUES (md5(md5(concat(rows_result[col_name], rows_result['date']))),current_timestamp(), NULL, record_source, rows_result[col_name], 'PENDING', rows_result['_submission_time'], md5(concat(rows_result[col_name], rows_result['date'])))";
var stmt = snowflake.createStatement( {sqlText: query });
stmt.execute()
}
}
}
return "DONE"
$$;
It will loop over a specific field names of a survey to add them with some changes into specific tables on Snowflake.
I am keep getting the following error:
Execution error in store procedure ADD_OBSERVATION_VALUES: SQL compilation error: error line 1 at position 163 invalid identifier 'COLUMN_FIELD_NAMES' At Statement.execute, line 33 position 20
COLUMN_FIELD_NAMES seems to be a variable defined in JS:
// Set the indicators
COLUMN_FIELD_NAMES = ['beneficiary', ...
But then the code uses it as a literal string while building a query:
query += "VALUES (md5(concat(COLUMN_FIELD_NAMES[col_num], ...
Instead, it should be parsed and concatenated with JavaScript and, as in:
query += "VALUES (md5(concat(" + COLUMN_FIELD_NAMES[col_num] +", ...
If executing the query doesn't work, try printing the value instead of executing it, and then debug.
I am unable to return the projectIds array after the mysql statements have finished executing as the loop is iterating before executing them. This results in empty array being returned everytime.
function fetchProjects (projects, userId, callback) {
projectIds = [];
Object.keys(projects).forEach(function(key) {
var row = projects[key];
const sql = 'create table if not exists users_' + row.project_id + '(sno int primary key auto_increment, iteration_no int not null, user_id int not null, foreign key(iteration_no) references pro_' + row.project_id + '(iteration_no), foreign key(user_id) references user(user_id))';
connection.query(sql, function(err, result) {
if(err) {
console.log(err.sqlMessage);
return callback(err.sqlMessage, false);
} else {
// console.log("First statement executed");
const sql1 = "select distinct t1.project_id, t1.project_name, t1.client, t1.initial_department_id, t1.start_date, t1.status, t1.current_department, t1.currently_assigned_user from project t1, users_" + row.project_id + " t2 where t1.project_id = '" + row.project_id + "' and (select user_id from users_" + row.project_id +" where user_id = " + userId + ")";
connection.query(sql1, function(err, result1) {
if(err) {
console.log(err.sqlMessage);
return callback(err.sqlMessage, false);
} else {
if(result1.length > 0) {
console.log(result1);
projectIds.push(result1);
}
}
});
}
});
// console.log("Iterating");
});
return callback(false, projectIds);
}
You are trying to execute callback style code in forEach which doesn't wait for the query to finish. That is the reason you are getting emoty array. I would make few modifications
Use promise version of the query method. Check the documentation of mysql node package
Use for..of loop instead of forEach.
Make the function async
Also await when you call the promise version of query method.
Hope this helps.
I am new in nodejs and mysql.
I am have an array of objects that i get from post and want to insert it to mysql database.
If the data already exist then run the update query to database.
The problem is Insert query not loop the entire array. it just insert the last entry of Array. Here my code:
Array Data:
bukukasData
[{transactionid: '562018965521',
tanggal: '2018-06-05',
kodeakun: 0, item: 'Saldo',
debit: 100000, credit: 0,
saldo: 100000},
{transactionid:'562018595664',
tanggal:'2018-06-05',
kodeakun: 0,
item: 'Test Data',
debit: 0,
credit: 5000,
saldo:95000}]
NodeJS Query
app.post('/api/addbukukas', function(req, res) {
let bukukasData = req.body.bukukasData;
var status = '';
for (var i = 0; i < bukukasData.length; i++) {
var transactionid = req.body.bukukasData[i].transactionid;
var kodeakun = req.body.bukukasData[i].kodeakun;
var item = req.body.bukukasData[i].item;
var debit = req.body.bukukasData[i].debit;
var credit = req.body.bukukasData[i].credit;
var saldo = req.body.bukukasData[i].saldo;
var tanggal = req.body.bukukasData[i].tanggal;
db.query('SELECT COUNT (*) AS rowCount FROM bukukas WHERE transactionid = ?', [req.body.bukukasData[i].transactionid], function(error, result) {
var rows = result[0].rowCount;
if (rows > 0) {
db.query('UPDATE bukukas SET transactionid=?, kodeakun=?, tanggal=?, item=?, debit=?, credit=?, saldo=? WHERE transactionid = ?', [transactionid, kodeakun, tanggal, item, debit, credit, saldo, transactionid],
function(err, result) {
if (err) {
status = 'Update Gagal';
} else {
status = 'Update Success';
}
})
} else {
db.query('INSERT INTO bukukas (transactionid, kodeakun, tanggal, item, debit, credit, saldo) VALUES (?,?,?,?,?,?,?)', [transactionid, kodeakun, tanggal, item, debit, credit, saldo], function(err, insertresult) {
if (err) {
status = 'Insert Gagal';
} else {
status = "insertresult";
}
})
}
})
}
console.log(status);
return res.json({ status: status });
});
With this code the only data that getting inserted to database just the last data in array. How can i insert all the data in Array to database?
Thanks
Use let instead of var. That will avoid this problem.
The source of this problem is, that in JavaScript the for-loop loops through the variable i and starts bukukasData.length times the db query. The parameter is given as reference. Since the loop iterates very fast, the first sql statement ist started with i set to the last value and all db-statements are executed with i set to bukukasData.length. let was introduced to JavaScript to fix problems like this. With let it will create a copy of the variable in the background.
I can pass an array to an mysql insert in nodeJS like so..
var data = {userId: 3, name: "sample"}
db.query('insert into my_table SET ?', data, function(err, result){...}
Is there a similar way of passing an array to a select query in the where clause... without specifying all the fields?
var data = {userId: 3, name: "sample"}
db.query('select * from my_table WHERE ?', data, function(err, result){...}
Doesn't seem to work.. nor does using the SET name in place of where...
database.conn.config.defaultQueryFormat = function (query, values) {
if (!values) return query;
var updatedQuery = query.replace("?", function () {
var whereClause = "";
for(var index in values){
whereClause += mysql.escapeId(index) + " = " + db.escape(values[index]) + " and ";
}
whereClause = whereClause.substring(0, whereClause.length - 5);
return whereClause;
});
return updatedQuery;
};
This appears to work.. e.g.
var val = db.query('select * from my_table where ?', data, function(err, result) {
}