I have stored some unique codes in MySQL as array in respective to user email, now i want to verify the user with email and unique code submit by user. I want to create a query where i can match email and unique id stored in database, to proceed the user.
Database Entry:
["BZFeWwnmr8Rm6tuu","daFJWZCEtp2WzxtD","VV80UQQZ1ym77h0m"]
I have tried FIND_IN_SET
This is the code for API, I have stringify the user entered data, where it returns the value if there is single unique value stored, But if i fetch array of unique code e.g, ["BZFeWwnmr8Rm6tuu","daFJWZCEtp2WzxtD","VV80UQQZ1ym77h0m"]
the MySQL query not working.
exports.vr_client_detail = function (req, res) {
const JSON_DATA = 'application/json';
if(req.headers['content-type'] === JSON_DATA){
if (req.body) {
var unique_string = JSON.stringify(req.body.unique_string);
var email = req.body.management_email;
db.sequelize.query('SELECT * FROM im_vr_client_activation '+
'WHERE FIND_IN_SET(unique_string, '+"'"+unique_string+"') AND "+
' management_email= ' + "'" + email + "'").then(function(app){
var arr = app[0];
return res.json({response_status:'success', response_code:185, data:arr, response:'Successfully fetch data.'})
});
}else{
return res.json({response_status:'error',response_code:10001,response:'Post data is empty.'});
}
}else{
return res.json({response_status:'error',response_code:10000,response:'Post data is not a json type.'});
}
}
The data returns nothing
{
"response_status": "success",
"response_code": 185,
"data": [],
"response": "Successfully fetch data."
}
It would be best if you normalized your schema, using a many-to-one table to hold all the unique strings instead of putting them into a single column.
But if you can't do that, you need to remove the [ and ] characters so you can use FIND_IN_SET().
You should also use a parametrized query to prevent SQL injection. See How to create prepared statements in Sequelize?
db.sequelize.query('SELECT * FROM im_vr_client_activation '+
'WHERE FIND_IN_SET(:unique_string, SUBSTR(unique_string, 2, LENGTH(unique_string)-2)) ' +
'AND management_email = :email', {
replacements: { unique_string: unique_string, email: email }
}).then(...)
If you're using MySQL 5.7 or higher you can change the datatype of the column to JSON and use JSON_CONTAINS(). And in 8.0 you can use the MEMBER OF operator.
Related
I am trying to dynamically build my SQL statement using node. The where clause will be completely different for each of my cases.
const sql = `select columnName from tableName where ?`;
const whereClause = { "name": "Siri", "Age":20}
connection.query(sql, whereClause, (err, rows) { ... });
However, I keep getting SQL syntax error. The query node builds is select columnName from tableName where name = 'siri', age = 20. I figured the reason I get SQL syntax error is because the SQL statement is missing the AND part. I want to be able to construct the query by giving the JSON object for the where clause.
I don't want to build the query using string concatenation due to SQL injection risks. So, is there another way that I can build my SQL statement without manually adding the AND part?
I'm pretty sure you can't process column names like that. Write a helper function that processes the json object and escapes values.
function processValue(value) {
if(!isNaN(value)) {
return value;
}
if(typeof value === "string") {
return `"${mysql.escape(value)}"`;
}
throw new Error("Unsupported value type!");
}
function where(obj) {
return Object.entries(obj).reduce(function(statement, [key, value]) {
return statement.concat(["AND", key, "=", processValue(value)]);
}, []).slice(1).join(" ");
}
Your query now looks like this:
const sql = `select columnName from tableName where ?`;
connection.query(sql, where({ "name": "Siri", "Age":20 }), (err, rows) { ... });
On another note, just use an ORM or a query builder like Knex so that you don't have to do all this manually.
I have the following code that I used for inserting into MySQL (MariaDB)....
import mysql from "mysql";
const INSERT_QUERY = "INSERT INTO CALL_DATE SET ? ON DUPLICATE KEY UPDATE MADE_DATE = VALUES(MADE_DATE)";
insertCallDate(callId, server, date){
const callDate = {
...
};
return connection.query(
INSERT_QUERY,
callDate
);
}
When I move to oracleDB I would like to do something like that again but the closest I can find is something like...
const INSERT_QUERY = "INSERT INTO CALL_DATE SET (ID, ...) values (:1, ...)";
Is there something similar to MySQL so I can pass a prestructured JSON object to Oracle? Specifically using the Node JS oracledb library?
There's a short section on JSON in the node-oracledb documentation. To quote an example:
const data = { "userId": 1, "userName": "Chris", "location": "Australia" };
const s = JSON.stringify(data); // change JavaScript value to a JSON string
const result = await connection.execute(
`INSERT INTO j_purchaseorder (po_document) VALUES (:bv)`,
[s] // bind the JSON string
);
There are also two runnable examples: selectjson.js and selectjsonblob.js.
Most of the JSON technology in Oracle is not specific to node-oracledb, so the Oracle manual Database JSON Developer’s Guide is a good resource.
You may be interested in SODA, which is also documented for node-oracledb and has an example, soda1.js. It lets you store 'documents' in the DB. These documents can be anything, but by default JSON documents are used.
I am implementing fingerprint authentication for my angular app using node tcp server in my scenario the bio metric device return the string of special characters to my node server which includes special characters like single and double like ##$'%" i wanted to store this complete string to database with single as well as double quotes. i have following query
var fingerPrint = '##$'%"'
db.query("insert into tbl_name (id, tempalte) value ('"+fingerPrint+"','')", (err, result)=>{
console.log(result)
})
but when string contain double quotes the query terminates as well as the problem with single quote. is there is any way to achieve this mechanism.
Thanks in advance
Here's one way to do it, using MySQL in NodeJs. This is what you can try:
let fingerPrint = `'##$'%"'`;
let addQuery = "INSERT INTO tbl_name (id, template) VALUES (?,?)";
let values = [1, fingerPrint];
db.query(addQuery, values, function (err, result) {
if (err) {
return console.error(err.message);
}
console.log("Number of records inserted: " + result.affectedRows);
})
Try
encodeURI() and decodeURI() it may work
I have a simple nodejs application which executes the following query.
select * from User where userid in (?)
The userids i get is a JSON array send from client side. How can i use that in this select query ? I tried
1. As itself but not working.
2. Convert this to Javascript array, not working
If you are using node module like mysql, the 2nd approach should work.
var query=select * from User where userid in (?);
var data=['a','b','c'];
var queryData=[data];
conn.query(query, queryData, function (err, results) {})
According to the documentation, "Arrays are turned into list, e.g. ['a', 'b'] turns into 'a', 'b'". So this approach should work (I have used it practically).
If you pass an array to the parameter it works with node mysql2. Parameters are already passed as arrays, so your first parameter needs to be an array [[1,2,3]].
select * from User where userid in (?)
const mysql = require('mysql2/promise');
async function main(){
let db = await mysql.createPool(process.env.MYSQL_URL);
let SQL = 'select * from User where userid in (?)';
let [res, fields] = await db.query(SQL, [[1,2,3]]);
console.log(res)
return res;
}
main().then(() => {process.exit()})
Revisiting this, since the original approach on the question is valid, but with some caveats. If your only escaped argument is the one on the IN clause, then you have to specify it as nested array; something like: [['usrId1', 'usrId2', 'usrIdN']]. This is because the un-escaping functionality expects an array, replacing each '?' with the corresponding array element. So, if you want to replace your only '?' with an array, that array should be the first element of all arguments passed. If you had more than one '?', the syntax is more intuitive, but at the end consistent and the same; in this case, you could have your arguments similar to: ['myOtherArgument1', 'myOtherArgument2', ['usrId1', 'usrId2', 'usrIdN'], 'myOtherArgument3']
Something like this could work!
// get your possible IDs in an array
var ids = [1,2,3,4,5];
// then, create a dynamic list of comma-separated question marks
var tokens = new Array(ids.length).fill('?').join(',');
// create the query, passing in the `tokens` variable to the IN() clause
var query = `SELECT * FROM User WHERE userid IN (${tokens})`;
// perform the query
connection.query(query, ids, (err, data) => {
// do something with `err` or `data`
});
You can do like this:
select * from User where userid in (?,?,?,?)
var array = [];
array.push(value);
array.push(value);
array.push(value);
array.push(value);
then use array as parameter that should be bind.
// get query string data with commas
var param=req.params['ids'];
//damy data var param = [1,2,3,4,5];
var array = params.split(",").map(Number);
//Note in select query don't use " and ' ( inverted commas & Apostrophe)
// Just use ` (Grave accent) first key off numeric keys on keyboard before one
con.query(`select * from TB_NAME where COL IN(?)`,[array],(err,rows,fields)=>{
res.json(rows);
});
let val = ["asd","asd"]
let query = 'select * from testTable where order_id in (?)';
connection.query(query, [val], function (err, rows) {
});
In Node, you need to put array in the array.
Update: Please see this answer. It is the correct way to do what is asked in the question.
The methods I have tried are:
Expand JSON array to a string in the required format. Concatenate it with query using '+'. (Beware of SQL injections)
Dynamically add '?' using length of JSON array holding user ids. Then use the array to provide user ids.
Both works. I then changed my logic with a better approach so now i don't need then 'in' clause anymore.
Finally i move forward from postgresql 9.1 to postresql 9.3 that supports JSON data type. Then the same code function properly.
However i think that what i want to do in the first place can be done... if someone know how i still want to know.
Enviroment
node v0.10.28
pg v3.3.0
postgresql 9.1
I got this insert query
INSERT INTO sessions(sid, user_id, session_object) VALUES ('id1', 1, '{"id":"fX2HkXYLclB","data": testing"}') RETURNING session_id
When testing it from pgAdmin (or command line) it works fine, but when my app try to run it from pg.client.query it try to turn the object as a string saving "[object object]". Here is the node code:
var session = {"id":"fX2HkXYLclB","data": "testing"};
var sql = 'INSERT INTO sessions(sid, user_id, session_object) VALUES (\'id1\', ' +
' 1, \''+JSON.stringify(session)+'\' ) RETURNING session_id';
console.log(sql);
client.query(sql, function(err, info) {
if(err) {
return addSessionCB(err, null);
}
return addSessionCB(null, info.rows[0].session_id);
});
After runing the application and testing the query manually on pg_admin the table show this 2 results.
session_id | sid | user_id | session_object | active
------------+-------------+---------+---------------------------------------+---------
1 | fX2HkXYLclB | 1 | [object Object] | t
2 | fX2HkXYLclB | 1 | {"id":"fX2HkXYLclB","data": "testing"}| t
(2 filas)
So, the question is ¿what im doing wrong with the pg.query?
Adding the original code, the code before is simplified for readability.
function addSession(session, addSessionCB) {
log.log('debug', '[PSQL]Add new session on DB. \nsession: '+ session.id +
'\nuser:'+ session.data.user);
function executeAddSessionQuery(user_id){
var sql = 'INSERT INTO sessions(sid, user_id, session_object) VALUES (\'' +
session.id + '\', '+user_id+', \''+JSON.stringify(session)+'\' ) ' +
'RETURNING session_id';
log.log('debug', '[PSQL]Adding session: '+session.id+' for user_id: '+
user_id+'\nSQL: '+sql);
client.query(sql, function(err, info) {
if(err) {
log.log('debug', '[PSQL]Error adding new session. \n'+err);
return addSessionCB(err, null);
}
return addSessionCB(null, info.rows[0].session_id);
});
};
//to save session we need to know user id
getUserByName({name: session.data.user},
function getUserByNameCB(err, user_result){
if(err || !user_result){
//if error or not result we try to save new user
log.log('debug', '[PSQL]Associated user not found. Creating a new ' +
'user entry. ');
addUser({name: session.data.user},
function addUserCB(err, newUserID){
if(err){
log.log('warn', '[PSQL]Session user didn\'t exists and cannot be ' +
'added to DB');
return addSessionCB(err, null);
}
executeAddSessionQuery(newUserID);
});
} else {
//if the user exist we use his id.
executeAddSessionQuery(user_result.user_id);
}
});
}
The node postgres module has another form of query; where the 2nd parameter is an array of objects. So in your case
var sql = 'INSERT INTO sessions(sid,user_id,session_object) VALUES ($1,$2,$3) RETURNING session_id';
var values = [id1,1,JSON.stringify(session)];
and then follow that up with
client.query(sql,values,function(err,info) {
...
This also has the added benefit of guarding against SQL injection attacks.