How to Insert in SQL with NodeJs and mssql library with params - sql

I have 2 arrays, the first one contains the columns for the insert and the second one contains de values
const columns = ['columnName1','columnName2','columnName3','columnName4','columnName5','columnName6'];
const values2 = ['test1', 'test2', 27, 1, 'an address', null];
module.exports = {columns, values2}
And I'm trying to do the insert using mmsql library but not even the documentation contains a sample with multiple columns to insert values to.
This is a sample of my insert
let pool = await sql.connect(config)
const result = await pool.request().query(`INSERT INTO [Test].[TableName] (${testData.columns}) VALUES ?`, [[testData.values2]]);
console.dir(result);
And I'm getting the following error:
RequestError: Incorrect syntax near '?'.
I was able to select to the db with no issues but there's something about the syntax that it doesn't seem to like..

At least you forgot to wrap ? with round brackets:
const result = await pool.request().query(`INSERT INTO [Test].[TableName] (${testData.columns}) VALUES (?)`, [[testData.values2]]);

As I can't find a single example, where you pass the parameters of your sql-query to the query function or use ? as a placeholder in their documentation, I'm not sure, whether node-mssql supports this. But if it does, you should at least create as many ? in the sql statement as you add values.
var cols = [...]; //your columns
const sqlquery = `insert into sometable (${cols}) values (${new Array(cols.length).fill('?')})`;
The documented way would be using input parameters
await pool.request()
.input('p1', sql.Int, value1)
.input('p2', sql.VarChar(50), value2)
.query('insert into sometable(col1, col2) values(#p1, #p2)');
To keep this flexible you could use something like the following
var cols = ['col1', 'col2'];
var vals = ['a string', 23];
const request = pool.request();
for (let i = 0; i < vals.length; i++)
request.input(`param_${i}`, vals[i]); //if you skip the parametertype, mssql will guess it from the value
const sqlquery = `insert into sometable(${cols}) values (${vals.map((_,i) => `#param_${i}`)`;
const result = await request.query(sqlquery);

Related

How to use IN prepared statement with single variable in typeorm

I have a .sql file containing a query such as
SELECT * WHERE id IN ($1)
The sql query is read and passed into a typeorm query with an array of parameters.
const result = await this.entityManager.query(myQuery, parameters);
I would like to have parameters be an array with a single value that would be a string concatenation of all the ids I want to find.
This would allow me to use my sql file no matter the number of ids I want to filter by.
I have tried formatting parameters in such a way that I can have $1 only no matter the number of items in my array:
const ids = ['1', '2', '3'];
const parameters = [ids.join("', '")];
or
const parameters = ["'" + ids.join("', '") + "'"];
etc
I have not found a syntax that works.
Is this feasible somehow ?
I have replaced the IN ($1) by = ANY($1) and am now passing the ids as an array. This works as I intend.
SELECT * WHERE id = ANY($1);
const ids = ['1', '2', '3'];
const result = await this.entityManager.query(myQuery, [ids]);

How to extract the query string from a SQLite object in nodejs?

How to extract the query string from a SQLite object in nodejs?
For example if we have this:
import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
const db = await open({
filename: 'test.db',
driver: sqlite3.Database
});
var ret = await db.get('SELECT * FROM `test` WHERE id=? AND foo=?', [100, 'bar']);
How can we achieve this:
SELECT * FROM `test` WHERE id="100" AND foo="bar"
I expect something like this to happen:
db.getQueryString();
es6 string replacement is supporet by nodesjs.
var my_id = 100
var my_var = 'bar';
var s = `SELECT * FROM `test` WHERE id="${my_id}" AND foo="${my_var}" `;
console.log(s);
But you should prepare your statements to make the secure like https://stackoverflow.com/a/49328621/5193536
Depending if ydo want the strings in the log to be used, for testing, you must add single quotes to the sting above, which the query makes automatically

is there any way to insert an array values into INT datatype in SQL?

I am trying to insert into a table called Observations, I need to insert 10 rows using for loop, I have an array of 10 values that need to be inserted in a column called sens_value which is an INT type. I have tried the following code but it cant take sensValues[i] as an INT.
I am using noodjs to insert into tables using mariadb database.
Basically I am looking for a way to insert different INT values into my SQL statement using for loop. I tried the following code:
const mariadb = require('mariadb/callback');
const dbConn = mariadb.createConnection({host: 'localhost', user:'tudublin', password: 'tudublinpwd', database: 'IoT'});
var sensValues = [10,20,30,15,18,22,28,33,16,40];
for (var i in sensValues) {
console.log(sensValues[i]) //10,20,30,15,18,22,28,33,16,40
var sql = "INSERT INTO Observations (sensor_id, sens_value, sens_units, dt_added) VALUES (2, sensValues[i], 'C Deg per Volt', now());";
dbConn.query(sql, insertCallback)
}
function insertCallback(err, res) {
if (err) {new Date().getTime()
console.log(err.message);
} else {
console.log(res);
dbConn.end();
}
}
The sensValues[i] in the VALUES is treated as a string, not as a value from the array. Pass it on as a parameter:
var sql = "INSERT INTO Observations (sensor_id, sens_value, sens_units, dt_added) VALUES (2, ?, 'C Deg per Volt', now());";
dbConn.query(sql, [sensValues[i]], insertCallback)

How to structure syntax for `SELECT` with `IN` SQL Server Query from Node via `mssql` package

I want to make use of SELECT and IN to match on values between tables from two different SQL databases in my Node app that makes use of the mssql package:
My question is, if I am passing a variable representing that array of values in my Node app, that looks like this:
const arr = ["1323", "2311", "1234"];
would I do this?:
N'[arr]'
or this?
N'arr'
Or is there some other syntax I should use?
Right now, this is the full query I'm passing:
// An array *like* this, saved in a variable name:
const sourceIdArr = ["1323", "2311", "1234"];
const selectInQuery = `
DECLARE #sourceIdArr NVARCHAR(4000) = N 'sourceIdArr'
SELECT NDID FROM SR_Empsheets
WHERE NDID IN ( SELECT value from openjson(#sourceIdArr) )
`;
Will this work, or should I approach it differently?
So something like
const sourceIdArr = ["1323", "2311", "1234"];
const selectInQuery = `
SELECT NDID FROM SR_Empsheets
WHERE NDID IN ( SELECT value from openjson(#sourceIdArr) )
`;
new sql.Request()
.input("sourceIdArr", sql.VarChar(sql.MAX), JSON.stringify(sourceIdArr) )
.execute(selectInQuery , (err, result) => {
// ... error checks
console.dir(result)
});

How safe is this generated query from SQL injection?

I am trying to make a search bar which works with multiple words, but I am worried about SQL injection.
I am using node express with the npm mssql package.
Here's the code which gets the criteria, generates the SQL and runs it:
router
.get('/search/:criteria', function (req, res) {
var criteria = req.params.criteria;
var words = criteria.split(" ");
var x = ""
words.map(word => x += `name like '%${word}%' and `);
x = x.substring(0, x.length - 5); // Remove trailing 'and'
var query = `SELECT * FROM table WHERE ${x}`
new sql.ConnectionPool(db).connect().then(pool => {
return pool.request().query(query)
}).then(result => {
})
});
A search for something to search would result in this query:
SELECT * FROM table
WHERE
name like '%something%'
and name like '%to%'
and name like '%search%'
I tried some SQL injections myself, but none of them seem to work.
Note: I am aware that we should always use inputs for this. It works fine for one word, but I don't know how to use inputs for many words. Ex:
new sql.ConnectionPool(db).connect().then(pool => {
return pool.request()
.input('input', '%'+criteria+'%')
.query(query)
})
The answer is: It's not safe. Your code does exactly nothing to make it safe, either. Don't build SQL by concatenating/interpolating user-supplied data into the statement.
In addition, you don't do any escaping for LIKE itself, either, so that is just as unclean.
If you need dynamic SQL, build a prepared SQL statement with the expected number of placeholders and then bind user-supplied values to those placeholders.
router.get('/search/:criteria', (req, res) => {
const ps = new sql.PreparedStatement();
const sqlConditions = [];
const escapedValues = {};
// set up escaped values, safe SQL bits, PS parameters
req.params.criteria.split(" ").forEach((v, i) => {
const paramName = 'val' + i;
escapedValues[paramName] = v.replace(/[\\%_]/g, '\\$&');
sqlConditions.push(`name LIKE '%' + #${paramName} + '%' ESCAPE '\'`);
ps.input(paramName, sql.VarChar);
});
// build safe SQL string, prepare statement
const sql = 'SELECT * FROM table WHERE ' + sqlConditions.join(' AND ');
ps.prepare(sql);
// connect, execute, return
ps.execute(escapedValues).then(result => {
res(result)
});
});
(Disclaimer: code is untested, as I have no SQL Server available right now, but you get the idea.)