Javascript MySQL从JSON对象动态生成查询

Javascript MySQL从JSON对象动态生成查询,javascript,mysql,json,Javascript,Mysql,Json,是否有一种方法可以从值可能为空的JSON对象动态构建MySQL查询 例如,从像这样的对象: { "a": 1 "b": "" "c": "foo" } 创建如下查询(“b”为空,不应将其考虑在内): 或 编辑:它可能确实是重复的。但我认为有一种更适合SQL的方法来实现这一点,例如使用变量和IF语句 编辑2:我找到了一种方法(在node.js API中工作,但在其他语言中应该类似): 当然,此代码目前不可用,必须对其进行调整,同时牢记注入问题。重要信息:此策略对用户开放。您必须转义这

是否有一种方法可以从值可能为空的JSON对象动态构建MySQL查询

例如,从像这样的对象:

{
  "a": 1
  "b": ""
  "c": "foo"
}
创建如下查询(“b”为空,不应将其考虑在内):

编辑:它可能确实是重复的。但我认为有一种更适合SQL的方法来实现这一点,例如使用变量和IF语句

编辑2:我找到了一种方法(在node.js API中工作,但在其他语言中应该类似):


当然,此代码目前不可用,必须对其进行调整,同时牢记注入问题。

重要信息:此策略对用户开放。您必须转义这些值-最好使用准备好的查询。如果没有对数据库客户机的更多了解,就不可能指导您如何操作

另外:我强烈建议拥有一个允许列的白名单,并且只允许在查询中使用白名单中的列键。下面的示例包括一个白名单来演示这一点

以下是一个MVP,它将处理任意/动态对象,并根据您的请求生成SQL语句:

const obj={
“a”:1,
“b”:“,
“c”:“foo”,
“坏”:“不允许”
}
//如何使用白名单的示例
常量白名单=['a','c'];
//设置一个空数组以包含WHERE条件
让where=[];
//迭代对象中的每个键/值
Object.keys(obj).forEach(函数(key){
//如果密钥未列入白名单,请不要使用
如果(!白名单包括(键)){
返回;
}
//如果该值为空字符串,请不要使用
如果(''==对象[键]){
返回;
}
//如果我们已经做到了这一点,那么将该子句添加到条件数组中
where.push(``${key}`=“${obj[key]}”`);
});
//将where数组转换为AND子句字符串
where=where.join('AND');
//如果有WHERE字符串,请在前面加上WHERE关键字
如果(在哪里){
where=`where${where}`;
}
const sql=`SELECT*自表${where}`;
console.log(sql);

//从表中选择*,其中'a`=“1”和'c`=“foo”
让我们尝试创建一个可以处理非常复杂查询的函数

函数prepareStmtFromObject(参数){
常量约束=[];
常量数据=[];
Object.keys(params).forEach((项)=>{
如果(!params[item]| | params[item]==“”){
返回;
}
if(Array.isArray(params[item])){
push(`${item}in(?)`);
数据推送(参数[项目]);
}else if(参数类型[item]=“string”&¶ms[item].indexOf(“,”>-1){
push(`${item}in(?)`);
data.push(参数[item].split(“,”);
}else if(参数[item]instanceof RegExp){
push(`${item}REGEXP?`);
数据推送(参数[项目]);
}else if(参数[项目]&&typeof参数[项目]=“对象”){
Object.key(参数[项]).forEach((值)=>{
如果(值=“$gte”){
push(`${item}>=?`);
数据推送(参数[项目][值]);
}else if(值==“$lte”){
push(`${item}?`);
数据推送(参数[项目][值]);
}else if(值==“$lt”){
push(`${item}<?`);
数据推送(参数[项目][值]);
}else if(值==“$like”){
if(Array.isArray(params[item][value])){
const localConstraints=[];
参数[item][value].forEach((likeValue)=>{
push(`${item}LIKE?`);
data.push(`%${likeValues}%`);
});
push(`(${localConstraints.join(“OR”)})`);
}else if(typeof params[item][value]==“string”&¶ms[item][value].indexOf(“,”>-1){
const localConstraints=[];
params[item][value]=params[item][value]。拆分(“,”;
参数[item][value].forEach((likeValue)=>{
push(`${item}LIKE?`);
data.push(`%${likeValues}%`);
});
push(`(${localConstraints.join(“OR”)})`);
}否则{
push(`${item}LIKE?`);
data.push(`%${params[item][value]}%`);
}
}
});
}否则{
push(`${item}=?`);
数据推送(参数[项目]);
}
});
返回{约束,数据};
}
常数数据={
用户ID:1,
公司:[“谷歌”、“微软”],
用户名:{$like:“Test”},
名称:{$like:[“Test1”、“Test2”]},
年龄:{$gt:10}
}
const stmt=prepareStmtFromObject(数据);
log(“从用户位置选择*”,stmt.constraints.join(“和”);

console.log(stmt.data)JSON对象来自哪里。。。我假设这里涉及到某种客户端编程语言?看起来很容易进行SQL注入。是的,当然它涉及数据验证和准备好的查询。Barmar是对的,问题及其解决方案与语言相似。我重新打开了问题,请添加一个语言标记,并显示您尝试的解决方案。您应该能够使链接问题中的算法适应您的语言。
SELECT * FROM db.table
WHERE a = 1
AND c = "foo"
SELECT * FROM db.table
WHERE a = 1
AND b = ????
AND c = "foo"
const jsonObj = {
"a": 1,
"b": "",
"c": "foo"
}
const query = `
SELECT * FROM db.table
WHERE
IF('${jsonObj.a}' != '', a = '${jsonObj.a}', 1=1)
AND
IF('${jsonObj.b}' != '', b = '${jsonObj.b}', 1=1)
AND
IF('${jsonObj.c}' != '', c = '${jsonObj.c}', 1=1)
`