HTML5 SQL Insert Multiple Rows - javascript

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 (?,?,?,?),(?,?,?,?),(?,?,?,?)

Related

Sequelize how to update json columns without select query

I want to update postgres column of json data type
columnData = [{"123":{a:1,b:2}}, {"456":{a:1,b:2}}]
expected = [{"123":{a:5,b:2}}, {"456":{a:1,b:2}}]
something "123".a =5 along with other values as it is.
I want to achieve this in single query
Model.update({columnData : columnData.123.a = 5});

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.

Use JS object as values on mySQL query string

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.

My PHP/ PDO query only returns 7 records when it should return 9

I have a web app that queries an Oracle Database for ID's that don't have X,Y's, I'm using Jquery and PHP API's,
I'm passing a list of ID's to PHP to query the database, and returning more information on the records so I can geoCode them.
For some reason my code skips the first and last record and only returns 7 of the 9.
In SQL Developer, My SQL query returns 9 records, which is correct.
My JavaScript, My Array (theIDS) has the 9 record IDS
that I'm selecting on, these are the same I used in SQL Developer.
My PHP page processes the array and returns 7 of the 9. Skips first and last.
In SQL Developer, My SQL query returns 9 records, which is correct.
SELECT ID, M_ADD1,M_CITY,M_STATE FROM CI_Data
WHERE ID IN
('1129','135','158','306','325','397','630','755','776');
My JavaScript code:
var theIDS = ["1129", "135", "158", "306", "325", "397", "630", "755", "776"];
var phpIDS = theIDS.join();
// My AJAX call to the PHP to pass the array and return the records.
$.ajax({ url : "forgeocode.php",
type : 'POST',
data : {'data': JSON.stringify(phpIDS)},
success : function(result){
console.log(result.length + " Records");
console.log(result);
for (var i = 0; i < result.length; i++) {
console.log(result[i][0]+ " ID Number");
console.log(result[i][1]);
console.log(i);
}
}
});
My PHP page that gets the POST and queries the records
$db = new PDO('oci:dbname=//myDBName:1521/infrastructuregisdev', 'Acct', 'Pwd');;
$arrData= $_POST['data'];
$arr = explode(",",$arrData);
$in = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT ID, M_ADD1,M_CITY,M_STATE FROM CIGIS.CI_DATA WHERE ID IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($arr);
$data = $stm->fetchAll();
header('content-type: application/json');
echo json_encode($data);
I need all 9 records, not sure if it's the PHP page using PDO. Why is it skipping the first and last record?
You're sending the string as JSON in JavaScript, so you need to use json_decode() in PHP.
$arrData= json_decode($_POST['data']);
If you don't do this, there are double quotes in $arrData. And after you explode it, the first value is '"1129' and the last is '776"'. These won't match the ID's in the table.
There's not really any need to convert the string to JSON in the first place, though. In fact, there isn't even any need to convert the array to a string. Just send the array, it will be encoded properly. Use this in the JavaScript:
data : {'data': theIDS},
and
$arr = $_POST['data'];
in PHP.
JSON.stringify(phpIDS)
This will create the following:
"1129,135,158,306,325,397,630,755,776"
Which is then passed to PHP, which you are using the following code on:
$arr = explode(",",$arrData);
But the problem is that you are exploding a string on ',' which will give you the following values:
"1129
135
158
306
325
397
630
755
776"
So when you try to run your "IN ()" on that it cannot match the first and last value. I think you see why?
So, you'd need to adjust things and run json_decode on the string first.
$arrData= json_decode($_POST['data']);
And then query your database!
Happy programming.

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.

Categories

Resources