Reputation: 2731
I am use nodejs npm package sql
I currently have an array of product skus like so..
var skus = ['product1', 'product2', 'product3'];
My sql store in a file as follows...
SELECT *
FROM stock AS s
WHERE s.sku IN (@skus)
Then I also have my prepared statement code as follows..
var connection = new sql.Connection(config, function(err) {
var ps = new sql.PreparedStatement(connection);
//Add params
if(params != undefined){
for(var key in params){
ps.input(key, sql.VarChar(200));
}
}
ps.prepare(sqlstatement, function(err) {
ps.execute(params, function(err, data) {
callback(null, data);
ps.unprepare(function(err) {
});
});
});
});
}
skus
is contained correctly within the params
object as the statement works fine when I am using it for simple WHERE X = @Y
I am just struggling with how I need pass the array of skus
to allow them to work in the prepared statement.
I am amend the string using split
and join
to comma seperate them etc etc but I can't get these methods to work.
I assumed that I would need the param string to look like the following 'product1','product2','product3'
.
would be also useful if someone could shed some light on how to debug the completed prepared statement so I can see what is actually being queried to SQL (with params inplace)
Many thanks in advance!
Upvotes: 5
Views: 8819
Reputation: 4947
in case other people like me come across this, here is a little helper function:
let nonce = 0;
export function inputList(req: sql.Request, data: Array<any>, type: (() => sql.ISqlType) | sql.ISqlType): string {
const out = [];
nonce++;
nonce %= 1e6;
const name = nonce.toString(36);
// classic for loop should be faster but i'm lazy. do the optimization yourself.
data.forEach((value, index) => {
const key = `_${name}_${index.toString(36)}`;
out.push(`@${key}`);
if (type) req.input(key, type, value);
else req.input(key, value);
});
return `(${out.join(",")})`;
};
// example usage. don't take it as best practice:
export async function getDocTypes(docTypes: Array<string>) {
const out = {};
const req = pool.request();
const res = await req.query(`
SELECT
[dt].[kue_dokuart] as [type],
[dt].[langtext] as [name]
FROM
[dbo].[dokuart_langtexte] as [dt]
WHERE
[dt].[kue_dokuart] IN ${inputList(req, docTypes, sql.NVarChar)}
AND
[dt].[sprache] = '049'
`);
res.recordset.forEach(row => {
out[row.type] = row.name;
});
return out;
};
> await getDocTypes(["APERS", "DPERS"])
{APERS: 'Personalakte', DPERS: 'Personaldokumente'}
Upvotes: 0
Reputation: 30256
It appears that the sql
object (i.e. the mssql
module) has no attribute to handle arrays of anything. Moreover, specifying a scalar type in the call to ps.input
similarly does not work.
The next best thing is to build keys for your array of parameters into your sql statement itself:
var connection = new sql.Connection(config, function(err) {
var ps = new sql.PreparedStatement(connection);
// Construct an object of parameters, using arbitrary keys
var paramsObj = params.reduce((obj, val, idx) => {
obj[`id${idx}`] = val;
ps.input(`id${idx}`, sql.VarChar(200));
return obj;
}, {});
// Manually insert the params' arbitrary keys into the statement
var stmt = 'select * from table where id in (' + Object.keys(paramsObj).map((o) => {return '@'+o}).join(',') + ')';
ps.prepare(stmt, function(err) {
ps.execute(paramsObj, function(err, data) {
callback(null, data);
ps.unprepare(function(err) {
});
});
});
});
}
Upvotes: 6