SQL Parse Error when using node-mysql - javascript

I'm getting parse errors when I try to use node-mysql to invoke a query on a MYSQL database. I'm pretty sure that the query works. It runs without doubt via phpmyadmin.
Message.save = function(message, callback){
db.query("INSERT INTO e_message (chatid, message, userid) VALUES(" + message.chatid + ", '" + message.message +"', " + message.userid + "); SELECT * FROM e_message WHERE chatid = " + message.chatid + " ORDER BY timestamp DESC LIMIT 0, 1;",
function(err, rows, fields){
console.log(err);
callback(err, new Message(rows[0]));
});
}
I'm getting the follwing error:
{ [Error: ER_PARSE_ERROR: 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 'SELECT * FROM e_message WHERE chatid = 1 ORDER BY timestamp DESC LIMIT 0, 1' at line 1]
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlState: '42000',
index: 0 }
The query looks like this via console.log():
INSERT INTO e_message (chatid, message, userid) VALUES(1, 'test123', 1);
SELECT * FROM e_message WHERE chatid = 1 ORDER BY timestamp DESC LIMIT 0, 1;
I don't know whats wrong with this...
EDIT:
If I split it into two queries, I get the result I wanted:
Message.save = function(message, callback){
db.query("INSERT INTO e_message (chatid, message, userid) VALUES(" + message.chatid + ", '" + message.message +"', " + message.userid + ");", function(err, rows, fields){
db.query("SELECT * FROM e_message WHERE userid = " + message.userid + " AND chatid = " + message.chatid + " ORDER BY timestamp DESC LIMIT 0, 1;", function(err, rows, filds){
callback(err, new Message(rows[0]));
});
});
}
Thank you!

node-mysql won't by default allow you to issue multiple SQL statements in a single query.
To allow that, you will need to set the multipleStatements connection option when creating the connection.
Note that allowing this may/will put you at risk of SQL injection, particularly if building the statements as strings. For example, if your message.userid was set to the string 1);drop database production;SELECT (, you'd be in trouble.
In this case what you really want may be to do the insert and a second SELECT LAST_INSERT_ID() to get the id the latest record was inserted with. It will return the latest inserted auto increment key for the session, that is, it will not be affected by other inserts by other connections/sessions.

Related

Knex RAW MySQL query adding new lines

I am new to MySQL and previously used PSQL the same way as I am using MySQL but the below code is erroring.
return await db
.raw(
`INSERT INTO users(firstName,
lastName,
email,
password,
type,
addressLine1,
addressLine2,
addressLine3,
mobileNumber,
townCity,
postcode)
VALUES (
'${firstName}',
'${lastName}',
'${email}',
'${hashedPassword}',
'${mobileNumber}',
${type},
'${addressLine1}',
'${addressLine2}',
'${addressLine3}',
'${townCity}',
'${postcode}');
SELECT * from users WHERE id = LAST_INSERT_ID()`,
)
.then(() => ...)
Returning the below error.
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlState: '42000',
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 'SELECT * from users WHERE id = LAST_INSERT_ID()' at line 24",
sql: 'INSERT INTO users(firstName, \n' +
' lastName, \n' +
' email, \n' +
' password, \n' +
' type,\n' +
' addressLine1, \n' +
' addressLine2, \n' +
' addressLine3, \n' +
' mobileNumber,\n' +
' townCity, \n' +
' postcode)\n' +
' VALUES (\n' +
" 'Jane',\n" +
" 'Doe',\n" +
" 'janedoe#email.com',\n" +
" 'password', \n" +
" '07123456789',\n" +
' 100, \n' +
" '1', \n" +
" 'Test road', \n" +
" 'Westminster', \n" +
" 'London', \n" +
" 'L1 1TG'); \n" +
' SELECT * from users WHERE id = LAST_INSERT_ID()'
}
I suspect it is related to the template literals but not sure of the best way to go about resolving this, it worked fine in PSQL (excluding the last line). Is there any better ways of using raw SQL, I am not interested in all the high-level ORM commands.
You need to enable multipleStatements
const mysql = require('mysql')
connection = mysql.createConnection({
host: 'localhost',
user: 'youruser',
password: 'yourpassword',
database: 'yourdb',
multipleStatements: true
})
connection.connect()
connection.query('INSERT INTO users(firstName,
lastName,
email,
password,
type,
addressLine1,
addressLine2,
addressLine3,
mobileNumber,
townCity,
postcode)
VALUES (
'${firstName}',
'${lastName}',
'${email}',
'${hashedPassword}',
'${mobileNumber}',
${type},
'${addressLine1}',
'${addressLine2}',
'${addressLine3}',
'${townCity}',
'${postcode}');
SELECT * from users WHERE id = LAST_INSERT_ID();', function(err, results) {
if (err) {
throw err
}
console.log(results[0]])
})
connection.end()
Looks like you can't do too much in one query. Extracting SELECT * from users WHERE id = LAST_INSERT_ID() into it's own query after the insert worked fine
Try to execute first query seperately. If it didnt execute, check youre table structure. Seems like structure missing primary key settings or something on youre migration

Grouping SQL results by month

I am trying to write a function that reads from an mssql database. Calculates the average number of days taken by engineering on a project and the percentage of on time projects and stores the results in my own Mongo database. Below is what I have, which works
async function update(m, y) {
var query = "SELECT AVG(DATEDIFF(day, DateBlockReleased, DateEngineeringTargetComplete)) AS AvgDays, SUM(IIF(DATEDIFF(day, DateBlockReleased, DateEngineeringTargetComplete)>=0, 1, 0)) AS OnTime, COUNT(DateBlockReleased) AS Total FROM JobData.JobData, JobData.BOMInfo, JobData.DesignInfo WHERE JobData.JobData.BOMInfoID = JobData.BOMInfo.BOMInfoID AND JobData.JobData.DesignInfoID = JobData.DesignInfo.DesignInfoID AND JobData.DesignInfo.DateEngineeringTargetComplete IS NOT NULL AND JobData.JobData.isArchivedDate IS NOT NULL AND MONTH(JobData.JobData.isArchivedDate) =" + m + " AND YEAR(JobData.JobData.isArchivedDate) =" + y;
sql.connect(config, (err) => {
if (err) {
console.log("Error while connecting to database :- " + err);
} else {
var request = new sql.Request();
request.query(query, function (err, rs) {
if (err) {
console.log("Error while querying database :- " + err);
sql.close();
} else {
var record = {
_id: m + "_" + y,
AvgDays: rs.recordset[0].AvgDays,
OnTime: rs.recordset[0].OnTime / rs.recordset[0].Total * 100
};
kpiConn.collection('engineeringData').insertOne(record);
sql.close();
}
})
}
})
}
However when I run this for multiple months and years I get the records for the first 10 months and then abort errors from the SQL server. I believe this is because I am querying the database too many times at once and so I am trying to condense this into one SQL query but am struggling to group the results by month. I don't know whether it's easier to return the entire database with ontime calculated and then use javascript to group them? Also open to any suggestions to make my query in general more streamlined as I'm quite new to SQL (Have a feeling I should be using joins)
Try doing a select all with a sort.
If you have a column in your database with months etc and then also time taken you can run something like this.
SELECT column-list
FROM table_name
[WHERE condition]
[ORDER BY column1, column2, .. columnN] [ASC | DESC];
For you would just be ;
select * FROM table_name
Hope this helps :)

mysql parse error shows when query has 3 conditions

i have a select query to a local database and for some reason the following error shows up:
ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FROM site WHERE name = OCC AND date_start = 2018-07-30 08:00:00 AND date_end = '' at line 1
here's my query:
connection.query("SELECT *, FROM shop WHERE name = " + shop_name + " AND date_start = " + myDate + " AND date_end = " + myDate2, function (err, result)
{
if (err)
{
console.log("Error Is:" + err);
}
else
{
console.log('DATA EXISTING IS =' + JSON.stringify(result));
}
});
am i missing something?
The usual mantra: use parameterized queries. They will prevent SQL injections and make your service more secure. Furthermore they will take care of the usual pitfalls when building a query using string concatenation.
Let's have a look at your query
"SELECT *, FROM shop WHERE name = " + shop_name + " AND date_start = " + myDate + " AND date_end = " + myDate2
Which spells out to something like
SELECT *, FROM shop WHERE name = myshop AND date_start = 2018-07-30 AND date_end = 2018-08-10
There are at least 3 errors
The , behind the SELECT * this is also the one the error tells you about. I suppose you had a column list and replaced it with *
The shop name column is most certainly some char column. So you have to enclose your values with quotes
Also the dates must be used with quotes, so the SQL engine will parse it to a date and do the comparison. For some SQL engines there is also a special annotation for dates. Have a look in the documentation.
This query should work
"SELECT * FROM shop WHERE name = '" + shop_name + "' AND date_start = '" + myDate + "' AND date_end = '" + myDate2 +"'"
depending on what myDate and myDate2 are.
At least problems 2 and 3 would not happen if you use parameterized queries. Consult the documentation of the library you are using.

Error: ER_PARSE_ERROR: You have an error in your SQL syntax;

I'm trying to insert values using mysql in nodejs. I had written the following code and installed MySQL support via npm,But canot to INSERT INTO the table due to this problem.
My code;
var mysql = require('mysql');
var values=randomValueHex(8);
var sql = "INSERT INTO `activationkeys`(`activationKey`, `productId`)
VALUES ( values ,'3')";
con.query(sql, function (err, result) {
if (err) throw err;
console.log("1 record inserted");
});
My Error on terminal:
Error: ER_PARSE_ERROR: 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 ''3')'
How can i solve this problem?
Why are you using back quote for the column names? We do not need that in column names. You can simply create your dynamic sql query by using + operator on the column values like this:
var sql = "INSERT INTO activationkeys (activationKey, productId) VALUES ( " + values + " ,'3')";
Instead of
var sql = "INSERT INTO `activationkeys`(`activationKey`, `productId`)
VALUES ( values ,'3')";
Please try this
var sql = "INSERT INTO `activationkeys`(`activationKey`, `productId`)
VALUES ( " + values + " ,'3')";
provided values is a string
values currently means nothing the way you're using it in the SQL query.
What is values? Is it an integer, or a string?
Nevertheless, you need to concatenate the values variable within the string.
var sql = "INSERT INTO `activationkeys`(`activationKey`, `productId`) VALUES (" + values + ",'3')";
And one more correction values variable have to give like this '" + values + "' . This is the most correct way of define as a variables. Otherwise you give like this " + values + " , you may be have an error accure like this Error: ER_BAD_FIELD_ERROR: Unknown column 'xxxxxx' in 'field list'. And my code is
var sql = "INSERT INTO `activationkeys`(`activationKey`, `productId`) VALUES ( '" + values + "' , 3 )";
This is simple way to write SQL query in you JavaScript code.
Try It Once
const QUERY = INSERT INTO users (firstName, lastName) VALUES ( "${firstName}", "${lastName}")
Note: Please wrap your complete query into the back ticks.

adding to a value in a database not replacing it

So i am storing my users 'freinds' in a database and i am currently using this to add there freind to it
socket.on('addFreind', function(username, freind) {
console.log("ADD FREIND " + freind + "TO " + username)
let query = 'update users set freinds="' + freind + '" where username = "' + username + '"';
connection.query(query, function(err) {
console.log(err)
});
});
but that just replaces the original value with the new one how can i add to the original value
i have tried querying the original value and adding it to an array and then adding the new value to that array then putting it in my database but that failed horribly and i was wondering if there was just a simple way to do this

Categories

Resources