Use JS object as values on mySQL query string - javascript

Im using pool to query mySQL on nodejs. We doing and it is working fine.
let values = [1, 2, 3];
DB.pool.query('SELECT * ROM table_name WHERE col1 = ? AND col2 = ? AND col3 = ?' , values, ( err, rows ) => {
//Do something
});
As you can notice, the where values are on array and we use ? on the query string to insert those values. The problem with this is, on complex queries, there are alot of value.
Is there a way to use object instead?
Something like:
let values = {col1: 1, col1: 2, col1: 3};
and the query string would be like:
SELECT * ROM table_name WHERE col1 = :col1 AND col2 = :col2 AND col3 = :col3
Any help would be appreciated.

You might be looking for a query builder like knex or slonik.
You could write your own utility function to help interpolate strings into queries, maybe using the JS Template Literals, but there are packages like the above which already exist to help you do some of this.
Ultimately, the answer is "not really". A SQL query is essentially a string. Either you are going to work with a client/library that builds a query for you (which is what whatever client you're already using is doing, letting you pass in an array of values to get interpolated into the string), or you are going to manually create your strings yourself somehow.

Related

Sequelize how to return result as a 2D array instead of array of objects?

I am using Sequelize query() method as follows:
const sequelize = new Sequelize(...);
...
// IMPORTANT: No changed allowed on this query
const queryFromUser = "SELECT table1.colname, table2.colname FROM table1 JOIN table2 ON/*...*/";
const result = await sequelize.query(queryFromUser);
Because I am selecting two columns with identical names (colname), in the result, I am getting something like:
[{ "colname": "val1" }, { "colname": "val2" }...], and this array contains values only from the column table2.colname, as it is overwriting the table1.colname values.
I know that there is an option to use aliases in the SQL query with AS, but I don't have control over this query.
I think it would solve the issue, if there was a way to return the result as a 2D array, instead of the array of objects? Are there any ways to configure the Sequelize query that way?
Im afraid this will not be possible without changes in the library directly connecting to the database and parsing its response.
The reason is:
database returns BOTH values
then in javascript, there is mapping of received rows values to objects
This mapping would looks something like that
// RETURNED VALUE FROM DB: row1 -> fieldName:value&fieldName:value2
// and then javascript code for parsing values from database would look similar to that:
const row = {};
row.fieldName = value;
row.fieldName = value2;
return row;
As you see - unless you change the inner mechanism in the libraries, its impossible to change this (javascript object) behaviour.
UNLESS You are using mysql... If you are using mysql, you might use this https://github.com/mysqljs/mysql#joins-with-overlapping-column-names but there is one catch... Sequelize is not supporting this option, and because of that, you would be forced to maintain usage of both libraries at ones (and both connected)
Behind this line, is older answer (before ,,no change in query'' was added)
Because you use direct sql query (not build by sequelize, but written by hand) you need to alias the columns properly.
So as you saw, one the the colname would be overwritten by the other.
SELECT table1.colname, table2.colname FROM table1 JOIN table2 ON/*...*/
But if you alias then, then that collision will not occur
SELECT table1.colname as colName1, table2.colname as colName2 FROM table1 JOIN table2 ON/*...*/
and you will end up with rows like: {colName1: ..., colName2: ...}
If you use sequelize build in query builder with models - sequelize would alias everything and then return everything with names you wanted.
PS: Here is a link for some basics about aliasing in sql, as you may aliast more than just a column names https://www.w3schools.com/sql/sql_alias.asp
In my case I was using:
const newVal = await sequelize.query(query, {
replacements: [null],
type: QueryTypes.SELECT,
})
I removed type: QueryTypes.SELECT, and it worked fine for me.

Similar string matching in Sequelize MYSQL

I'm new to Sequelize and JS and might not know all operators so I want to ask if there's any way to retrieve an entry from a database which is similar to but not an exact match. So for example the string I'm searching for is +921234567890 but in the database its stored as +92-1234567890, separated with a hyphen for country dialing codes.
The db I'm using is MySQL.
I tried this which I know is incorrect but I'm not sure how to move ahead:
where: {
cell: {
[Op.or]: {
[Op.like]: "%-%",
[Op.eq]: cellNumber,
},
},
You can use the REGEX_REPLACE() sql function to replace any non-numeric characters in the cell column before comparing to your input. Use the sequelize.where(), sequelize.fn(), and sequelize.col() functions to generate the query. Assuming your table is model and Model is Model.
const cellNumber = 1234567890;
const results = await Model.findAll({
where: sequelize.where(
sequelize.fn('REGEXP_REPLACE', sequelize.col('model.cell'), '[a-zA-Z]+', ''),
'=',
cellNumber
),
});
This should generate SQL similar to:
SELECT * FROM `model`
WHERE REGEXP_REPLACE(`model`.`cell`, '[a-zA-Z]+', '') = 1234567890;
The solution to this issue was solved using raw sql query but for anyone looking for an answer when using REGEXP_REPLACE, you should use REPLACE with sequelize.literal:
cell: { [Op.eq]: this.sequelize.literal("REPLACE('cell','-','')") }

HTML5 SQL Insert Multiple Rows

I'm trying to insert multiple rows into an SQLite database.
Single row insert like this works fine:
tx.executeSql("INSERT or REPLACE INTO `table` (`type` , `pid` , `title` , `body`) VALUES (?,?,?,?) ", ['qa',v.id,v.title,v.content_html ] ,console_success, console_fail);
How can I pass an array of variables into that execute to run all at once?
(the paramiterizaion method seems to be properly sanitizing my data and inserting. when I do a raw query it does not and my sql fails. I need to inset a full html body in the DB )
so I can't just do a query like this
insert into table (a,b,c) values (a,b,c) ,(a,b,c),(a,b,c)
and escape() function messes up my html in the body.
P.S. NOT the same as this question HTML 5 SQLite: Multiple Inserts in One Transaction
As you found out, you should really stick to parametrized query and avoid "raw" queries. Parametrized queries will automatically escape the input for you thus preventing SQL injection.
The key here is to build a parametrized query that will fit your needs. Here is an example.
// Guessing 2d array of raw data
var dataArr = [ ['qa','123','title1','<html></html>' ],
['bc','456','title2','<html></html>' ],
['xy','789','title3','<html></html>' ] ];
// Creating a parametrized entry for every row of dataArr
var param = "(?,?,?,?),".repeat(dataArr.length).slice(0,-1);
// The insert query
var query = "INSERT or REPLACE INTO `MyTable` (`type` , `pid` , `title` , `body`) VALUES ";
// Convert the 2d dataArr into 1d data
var data = [];
for(var i = 0; i < dataArr.length; i++)
data = data.concat(dataArr[i]);
tx.executeSql(query + param, data); // Final query is : INSERT or REPLACE INTO `MyTable` (`type` , `pid` , `title` , `body`) VALUES (?,?,?,?),(?,?,?,?),(?,?,?,?)

how to fetch all values in single variable using java script

i am retrieving the all values in a for loop but i want to insert those values in database using single variable.It possible to store all values to the single record.
var emailId;
//log.info("testing 1234 = "+tw.local.EntityProMasterList.listAllSelected);
for (var i = 0; i < tw.local.EntityProMasterList.listAllSelected.listLength; i++){
emailId = tw.local.EntityProMasterList.listAllSelected[i];
log.info("testing 1 = "+emailId.value);
}
log.info("testing 1 = "+emailId.value);
You can user JSON.stringify() and save it as string:
var holder = {};
holder.var1 = "var1";
holder.var2 = "var2";
log.info("holder:"+JSON.stringify(holder));
The output will be:
holder:{"var1":"var1","var2":"var2"}
I believe your question is - given a list of values, how can I insert those values into the database as separate entries. If this is correct there is a right way and a wrong way to do this.
The wrong way is to simply put all the SQL into a string and use one of the DB services in the system data toolkit to execute. Something like -
insert into table blah values(1, 2, 3, 4);
This would be wrong because you are open to SQL injection attacks. There is a different service for parameterized queries. This takes 1 or more SQL statements and a list of parameters to use in them. The details are documented in the service so I won't repeat them here. Basically you would modify your query to have the ? Character where you need the data from your array. You then create arrays of parameters that fill out the values on execution.

"Node.js / Edge.js - Insert JS variables into SQL" part 2

Here's the original question.
Okay, I'm using Node.js and Edge.js to insert values to an SQL database.
First attempt was a straightforward insertion of hardcoded values:
var insertRow = edge.func('sql', function () {/*
INSERT INTO dbo.table (column0, column1, column2)
VALUES (value0, value1, value2)
*/});
insertRow();
This hardcoded insertion works as expected, of course.
And as seen in the answer of the question before me, passing the function an object allows the SQL statement to recognize a name/value pair of the object via an #, allowing dynamic value assignment:
var rowObj = {
v0: 'value0',
v1: 'value1',
v2: 'value2'
}
var insertRow = edge.func('sql', function () {/*
INSERT INTO dbo.table (column0, column1, column2)
VALUES (#v0, #v1, #v2)
*/});
insertRow(rowObj);
Works as expected.
What I would like to do is have the table and columns be variable as well, through properties provided by the same rowObj.
I tried:
var rowObj = {
t: 'dbo.table',
c0: 'column0',
c1: 'column1',
c2: 'column2',
v0: 'value0',
v1: 'value1',
v2: 'value2'
}
var insertRow = edge.func('sql', function () {/*
INSERT INTO #t (#c0, #c1, #c2)
VALUES (#v0, #v1, #v2)
*/});
insertRow(rowObj);
But this doesn't work. I tried making the table dynamic on its own, and the columns on their own, and that didn't work either.
note: I don't know SQL, I don't know the limitations of Node.js/Edge.js, and I'm very new to programming in general (so if my nomenclature is inconsistent/wrong, let me know but please don't tear me apart) I was just wondering if what I'm trying to do can be done.
I suggest you call edge.func as many times as you need different selection criteria. If you don't know the column names a priori, you can always construct the T-SQL string you pass to edge.func dynamically. With this approach you would normally loose some optimizations around precompiled SQL statements, but given how MS SQL optimizes query execution on the server the savings are minimal.

Categories

Resources