Error in UPDATING thorugh mysql npm package - javascript

I am trying to UPDATE mysql Database through mysql npm package. I am using express.I need help with the following query.
app.put("/api/movies/:id", (req, res) => {
let id = parseInt(req.params.id);
let values = [...Object.values(req.body)];
values.push(id);
let fields = 'SET Rank = ?, SET Title = ?, SET Description = ?, SET Runtime = ?,\
SET Genre = ?, SET Rating = ?, SET Metascore = ?, SET Votes = ?,\
SET Gross_Earning_in_Mil = ?, SET Director = ?, SET Actor = ?, SET Year = ?';
connection.query("UPDATE moviesList " + fields + " \
WHERE Id = ?", values , (err, rows) => {
if(err) {res.send(err); console.log(err);}
else res.send(rows.message);
});
})
I was able to insert into table but I am getting following error for above code while UPDATE,
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlMessage:
'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near \'SET Title = \'Pulp Fiction\', SET Description = \'The lives of two mob hitmen, a bo\' at line 1',
sqlState: '42000',
index: 0,
sql:
'UPDATE moviesList SET Rank = 5, SET Title = \'Pulp Fiction\',
SET Description = \'The lives of two mob hitmen, a boxer, a gangster\\\'s wife, and a pair of diner
bandits intertwine in four tales of violence and redemption.\',
SET Runtime = 154, SET Genre = \'Crime, Comedy\', SET Rating = 8.9, SET Metascore = 94, SET Votes = 1511653, SET Gross_Earning_in_Mil = 107.93, SET Director = \'Quentin Tarantino\', SET Actor = \'John Travolta\', SET Year = 1994 WHERE Id = 5' }

The issue is w.r.t the fields defined .
You should define in an following format
For Example:
let fields = 'SET Rank =? , Title =?, Description =? , Runtime =?, Genre =?, Rating =? '
Please refer this link:
https://www.technicalkeeda.com/nodejs-tutorials/nodejs-mysql-update-query-example

The module provides a lot of flexibility that can save you time if you build each step of the process thoughtfully. It will accept an object for an INSERT or UPDATE as long as the keys match the column names of corresponding fields in the table you're querying.
So, if you have the ability to define the key values coming in via req.body you can let things flow through very easily without any additional manipulation or mapping.
Consider the following updated example of your code with a sample of how you would need to structure req.body upstream:
// example of what req.body would need to look like:
{
"Rank": "value_a",
"Title": "value_b",
"Description": "value_c",
"Runtime": "value_d",
"Genre": "value_e",
"Rating": "value_f",
"Metascore": "value_g",
"Votes": "value_h",
"Gross_Earning_in_Mil": "value_i",
"Director": "value_j",
"Actor": "value_k",
"Year": "value_l"
}
app.put("/api/movies/:id", (req, res) => {
let id = req.params.id;
let payload = req.body;
connection.query("UPDATE moviesList SET ? WHERE Id = ?", [payload, id], (err, rows) => {
if (err) throw err;
console.log('changed ' + rows.changedRows + ' rows');
// res.send(rows.message);
// in this context rows is the response object from the module
// message is not a sub-object of the feature so rows.message
// would likely fail
});
})

Related

How do I sanitize ILIKE query in Node-pg

I'm trying to create a filter for a findAll function that filters by name. The other filters in this function work fine but I can't get the name filter to work.
The function below accepts filter parameters (if any) and adds on to the WHERE query based on any passed in filters. Right now, when I pass in a name, it returns nothing unless the query matches a name in the database but I'm trying to return results that contain whatever the value of name is (i.e. a name query for 'net' would get you 'Neural Networks')
Here is what I have so far:
static async findAll(searchFilters = {}) {
let query = `SELECT handle, name, description, num_employees AS "numEmployees", logo_url AS "logoUrl"
FROM companies`;
let whereStatement = []
let values = []
const {name, minEmployees, maxEmployees} = searchFilters
if (minEmployees > maxEmployees) throw new BadRequestError('minEmployees cannot be greater than maxEmployees!')
if (!!minEmployees) {
values.push(minEmployees)
whereStatement.push(`num_employees >= $${values.length}`)
}
if (!!maxEmployees) {
values.push(maxEmployees)
whereStatement.push(`num_employees <= $${values.length}`)
}
if (!!name) {
values.push(name)
whereStatement.push(`name ILIKE $${values.length}`)
}
if (whereStatement.length > 0) {
query += ` WHERE ${whereStatement.join(" AND ")}`
}
query += ' ORDER BY name'
const companiesRes = await db.query(query, values)
return companiesRes.rows;
}
I tried typing it like this:
name ILIKE '%$${values.length}%'
but I got this message:
"error": {
"message": "bind message supplies 1 parameters, but prepared statement \"\" requires 0",
"status": 500
}
Is there a specific way to sanitize ILIKE queries in Node-pg or is my syntax just off?
I think your code in place where you append the name filter should look like:
...
if (!!name) {
values.push(`%${name}%`)
whereStatement.push(`name ILIKE $${values.length}`)
}
...
see 503#issuecomment-32055380

get the last insert id in node.js and pass it to a second query

I have in my sql database 2 tables, a table called club and a table called players, they are connected by one to many relationships, the query in node.js works fine but i can not get the last insert of table club , i need to it for insert in the foreign key in the table players
here what i have tried in node.js:
module.exports={
create:(data,callback)=>{
var myArray = new Array();
/* for(let item of data.players) {
console.log(item.firstname);
}*/
data.players.forEach((player) => {
console.log(player.id);
console.log(player);
var playerModel ={
id : player.id,
firstname : player.firstname,
lastname : player.lastname,
position : player.position,
price : player.price,
appearences : player.appearences,
goals : player.goals,
assists : player.assists,
cleansheets : player.cleansheets,
redcards : player.redcards,
yellowcards : player.yellowcards,
image : player.image,
clubid : player.clubid,
};
console.log("model"+playerModel.position);
myArray.push(playerModel);
});
var id;
pool.query(
'insert into club(userid,name,price) values(?,?,?)',
[
data.userid,
data.name,
data.price
],
(error,result) => {
if(error){
callback(error);
}
/* id = result.insertId;
console.error(result);
console.log(result+" result");*/
console.log(result.insertId);
return callback(null,result.insertId);
},
);
for(var item of myArray){
pool.query(
'insert into players(id,firstname,lastname,position,price,appearences,goals,assists,cleansheets,redcards,yellowcards,image,clubid) values (?,?,?,?,?,?,?,?,?,?,?,?,?)',
[
item.id,
item.firstname,
item.lastname,
item.position,
item.price,
item.appearences,
item.goals,
item.assists,
item.cleansheets,
item.redcards,
item.yellowcards,
item.image,
(
'select top 1 id from club order by id desc'
)
],
(error,results,fields)=>{
if(error){
callback(error);
}
return callback(null,results);
},
);
}
},
no idea about how to do this
If I understand this correctly, a subquery should work here.
-- first insert the club from paraterized query
insert into club (clubid, name, price)
values (? , ? , ?);
-- then use a subquery to find the last inserted club id
insert into
players (id, firstname, lastname, position, price, appearences, goals, assists, cleansheets, redcards, yellowcards, image, clubid)
values
(
? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ,
(
select clubid
from club
order by clubid desc
limit 1
)
)
;
Apart from that, an insert statement doesn't give you any data back. If you are looking to get the ID from the first call in NodeJS, you need to run a batch statement. 1 insert and 1 select, in the same batch of statements that is sent to the SQL server. See more for multi statement config here. node-mysql multiple statements in one query
const pool = mysql.createConnection({multipleStatements: true});
pool.query(`
insert into club(userid,name,price) values(?,?,?);
select clubid from club order by clubid desc limit 1;
`
, params
, function(err, results) {
if (err) throw err;
// now the id will be the second item of the batch statement result
const myId = results[1]
});
)
Based on both things, you could combine them, actually.
pool.query(`
insert into club(userid,name,price) values(?,?,?);
insert into players (id, firstname, lastname, position, price, appearences, goals, assists, cleansheets, redcards, yellowcards, image, clubid)
values
(
? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ,
(
select clubid
from club
order by clubid desc
limit 1
)
);
`
, params
)
You could also create yourself a stored procedure for this purpose.
Create a multi-query batch, like
INSERT INTO table1 (column1, column2, column3) VALUES (?, ?, ?);
INSERT INTO table2 (column1, reference_column, column3) VALUES (?, LAST_INSERT_ID(), ?);
Execute using a method which:
supports multi-query batch execution
executes the batch as a transaction
The parameters are provided to this method as one solid data array (for shown code it will contain 5 values, first 3 will be inserted into 1st query and all another toi 2nd one). id value assigned by 1st query will be automatically retrieved by the function and inserted into 2nd query.
I don't know what is the method with described properties in Node.JS. But it must exist..
An alternate way to figure this out was placing the initial query holding the first INSERT statement into a variable:
const first_insert = db.query('INSERT')...
Then returning the variable at the end of the first promise, and then finding the property values of the variable (since it returns a javascript object afterall):
.then((first_insert) => {
console.log(Object.entries(first_insert)); //returns array
console.log(first_insert[0]);
/*returns contents of first index of previously returned array, you'll see an object with a insertId property, thats what you need*/
console.log(first_insert[0].insertId)
/*this is the value you need to pass to each following statement*/
/*store that value in a variable that you declarre before any of the db methods, I named mine pk*/
pk = first_insert[0].insertId
/*Now use that variable for the foreign key and to correspond with the placeholder in whatever queries you use*/
}

Inserting multiple values in mysql using nodejs is causing parsing errors

I need to insert a record into mysql using nodejs. I am able to insert directly by typing values into the query just fine. I can insert using query + value syntax to concatenate the values but read this leaves open the risk of SQL injection.
let sql ="INSERT INTO gametypes (strGameType, intTeamSize, intMaxPlayers, intMinPlayers) Values ? ";
var gametype ="Solo Zonewars";
var teamSize =1;
var maxPlayers = 16;
var minPlayers = 10;
var values = [gametype, teamSize, maxPlayers, minPlayers];
console.log("connected as id '" + connection.threadId);
connection.query(sql, values, function(err, result, fields) {
connection.release();
if(!err) {
console.log(result);
}else console.log(err);
});
Below is the attached error I am getting from mysql. It seems like it is putting extra quotes around the gametype variable and not attempting to insert the rest into the query. Any ideas?
error from mysql
I would suggest you to not use an array and replace your query by this one
let sql ="INSERT INTO gametypes (strGameType, intTeamSize, intMaxPlayers, intMinPlayers) Values (?, ?, ?, ?) ";
then you will pass the values one by one
If you are having 4 value parameters to the query, you should have 4 question marks as well. Try with the first line changed to:
let sql ="INSERT INTO gametypes (strGameType, intTeamSize, intMaxPlayers, intMinPlayers) Values (?, ?, ?, ?) ";
You can try wrapping your values into an array, as this method is intended for inserting multiple rows:
let sql ="INSERT INTO gametypes (strGameType, intTeamSize, intMaxPlayers, intMinPlayers) Values ? ";
var gametype ="Solo Zonewars";
var teamSize =1;
var maxPlayers = 16;
var minPlayers = 10;
var values = [
[gametype, teamSize, maxPlayers, minPlayers]
];
console.log("connected as id '" + connection.threadId);
connection.query(sql, [values], function(err, result, fields) {
connection.release();
if(!err) {
console.log(result);
}else console.log(err);
});

"Order by" results from SQLITE query not ordered

I am working on a webshop-project. I am trying to get sorted results based on parameter values from a sqlite database. I am trying to sort products based on "select" values.
In my app.js
app.get('/sortMaleProducts', function(request, response){
var sortValues = request.query.sortValue;
if(sortValues == 'priceASC')
{
sortValues = ["man", "price", "ASC"];
}
else if(sortValues == 'priceDESC')
{
sortValues = ["man", "price", "DESC"];
}
db.sortMaleProducts(sortValues, function(error, clothes){
if(error){
console.log("Error: "+ error);
}
else{
console.log(clothes)
const model = {
clothes
}
response.render("man.hbs", model)
}
})
})
In my db.js
exports.sortMaleProducts = function(sortValues, callback){
const query = 'SELECT * FROM products WHERE gender = ? Order by ?, ?'
db.all(query, sortValues, function(error, clothes){
console.log(clothes);
callback(error, clothes);
})
If I hardcode the query like:
const query = 'SELECT * FROM products WHERE gender = 'man' Order by price ASC'
Then it works....But I want to use user inputs so I can reuse code..
If you want to sort by a column, that column name has to appear directly in the query. What you're doing sorts the results by the strings 'price' and 'ASC', which are the same for every row so any order of results is sorted.
You can't use column names as parameters anywhere else in a query either, like in the columns to return or in a WHERE. They have to be present when the statement is prepared by compiling it into sqlite's internal bytecode, which happens before any parameter binding or the execution of the query.

what the best way to insert a relationship table in mysql using NodeJS

First of all I have to say I'm totally newbi in NodeJS technologies.
But, I've tried to do something to try to learn it.
This is the problem:
I have 3 tables (PARTICIPANT, ADDRESS_PARTICIPANT and INSCRIPTION).
The ADDRESS_PARTICIPANT contains participant_id (it's the participant's address).
The INSCRIPTION contains participant_id
So, to store a inscription row, at first I need to save the PARTICIPANT and the ADDRESS_PARTICIPANT. Only after this I could insert INSCRIPTION
I'm doing this in the way i've learn, but I think there are a lot of nested ifs.
How could I improve this code? Someone told me with Promise i'll well.. but I don't know. Someone could help me? Thanks
Here is the code:
this.save = function(data, retur) {
var con = db();
const SQL_INSERT_PARTICIPANT =
`INSERT INTO participant (nome_completo, tipo_funcionario, data_nascimento, sexo, unidade, cpf, email, telefone, telefone_emergencia) VALUES( ? )` ;
const SQL_INSERT_ADDRESS_PARTICIPANT =
`INSERT INTO endereco_participante (participant_id, cep, estado, cidade, bairro, endereco, numero) values( ? )`;
const SQL_INSERT_INSCRIPTIONS = `......`
var values = [
data.nome_completo, data.tipo_funcionario, new Date(dateToEN(data.data_nascimento)), data.sexo, data.unidade, data.cpf_funcionario, data.email, data.telefone, data.telefone_emergencia
]
const insertParticipante = con.query(SQL_INSERT_PARTICIPANT , [values], function (err, result) {
if (err) throw err;
var values_end = [
result.insertId, data.cep, data.estado, data.cidade, data.bairro, data.endereco, data.numero
]
if (result.affectedRows > 0 ) {
const insertEndPart = con.query(SQL_INSERT_ADDRESS_PARTICIPANT , [values_end], function(err, result2 ) {
if (err) throw err;
console.log('Number of records inserted in ADDRESS_PARTICIPANT table: ' + result2.affectedRows);
console.log('insertId.: ' + result2.insertId)
if (result.affectedRows > 0 ) {
const insertInscricao = con.query(SQL_INSERT_INSCRIPTIONS, [values_ins], function(err, result3) {
console.log(`Inscription recorded! id: `+resul3.insertId)
})
}
})
}
})
}
You can use MySQL's LAST_INSERT_ID i assume every table has a primray key column with a auto_increment option.
With no argument, LAST_INSERT_ID() returns a BIGINT UNSIGNED (64-bit)
value representing the first automatically generated value
successfully inserted for an AUTO_INCREMENT column as a result of the
most recently executed INSERT statement. The value of LAST_INSERT_ID()
remains unchanged if no rows are successfully inserted.
https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_last-insert-id
Then you can use these INSERT's in NodeJS instead.
INSERT INTO participant (nome_completo, tipo_funcionario, data_nascimento, sexo, unidade, cpf, email, telefone, telefone_emergencia) VALUES( <other columns> )
This insert below will use LAST_INSERT_ID() to get the participant.id
INSERT INTO endereco_participante (participant_id, cep, estado, cidade, bairro, endereco, numero) values( LAST_INSERT_ID(), <other columns> )
With three table the problem gets more complex.
Then you can use MySQL's user variables.
INSERT INTO participant (nome_completo, tipo_funcionario, data_nascimento, sexo, unidade, cpf, email, telefone, telefone_emergencia) VALUES( <other columns> )
SET #participant_id = LAST_INSERT_ID();
INSERT INTO endereco_participante (participant_id, cep, estado, cidade, bairro, endereco, numero) values( #participant_id, <other columns> )
SET #endereco_participante_id = LAST_INSERT_ID();
Then you can use #participant_id and #endereco_participante_id in the third insert query. (which seams you didn't provided in your question).
Note the SET queries are separated queries so you need to execute them also with con.query('SET #participant_id = LAST_INSERT_ID();', ..)

Categories