我最近使用nodejs-mysql
模块在node.js中进行查询,在我的工作案例中,我只能使用参数绑定语法,如:
SELECT * FROM table WHERE name = ?
现在我想用这些?
OR ??
参数构建动态sql。假设我有2个条件(name
和age
),其中任何一个都可以为null(如果用户不提供),
所以我想在3种情况下构建MySQL:
name=Bob
:SELECT * FROM table WHERE name = 'Bob'
age=40
:SELECT * FROM table WHERE age > 40
SELECT * FROM table WHERE name = 'Bob' AND age > 40
我知道如果你自己构建查询很容易,但是在使用只能绑定字段或值的占位符时如何实现呢?
在nodejs-mysql
的文档中,占位符?
仅代表值,??
代表字段:
我对解决方案的第一个想法是使用这些占位符插入查询部分,但它会失败,因为?
和??
都将转义我的查询部分,并且我的查询将被错误地执行。
到目前为止,我的代码如下所示,我确定它不正确,因为查询件已被转义:
// achieve paramters from url request
var condition = {};
if(params.name)condition["name"] = ["LIKE", "%" + params.name + "%"];
if(params.age)condition["age"] = parseInt(params.age, 10);
//build query
var sqlPiece = buildQuery(condition);
//try to replace ? with query
var sql = 'SELECT * FROM table WHERE ?';
connection.query(sql, sqlPiece, function(err, results) {
// do things
});
// my own query build function to proceed conditions
function buildQuery(condition) {
var conditionArray = [];
for(var field in condition){
var con = condition[field];
if(con !== undefined){
field = arguments[1] ? arguments[1] + "." + field : field;
var subCondition;
if(con instanceof Array) {
subCondition = field + " " + con[0] + " " + wrapString(con[1]);
}else{
subCondition = field + " = " + wrapString(con);
}
conditionArray.push(subCondition);
}
}
return conditionArray.length > 0 ? conditionArray.join(" AND ") : "1";
}
//wrap string value
function wrapString(value){
return typeof value === "string" ? "'" + value + "'" : value;
}
那么有什么方法可以解决这个问题吗?
感谢Jordan的优惠,它正在发挥作用,但是:
我知道通过字符串连接建立查询非常好,但在我的情况下我不能使用它,因为我使用了一些中间件或处理mysql和控制器,所以我能做什么是定义接口,这是一个带占位符的sql字符串。因此,接口字符串之前是预定义的,在控制器功能期间我无法修改它。
答案 0 :(得分:11)
你有一个非常好的开始,但你可能已经过度思考了一下。诀窍是使用占位符(?
)作为字符串构建查询,同时构建一个值数组。
因此,如果您有params = { name: 'foo', age: 40 }
,则需要构建以下对象:
where = 'name LIKE ? AND age = ?';
values = [ '%foo%', 40 ];
如果您只有{ name: 'foo' }
,那么您将构建这些:
where = 'name LIKE ?';
values = [ '%foo%' ];
无论哪种方式,您都可以直接在query
方法中使用这些对象,即:
var sql = 'SELECT * FROM table WHERE ' + where;
connection.query(sql, values, function...);
那么我们如何构建这些对象呢?实际上,代码与您的buildQuery
函数非常相似,但不太复杂。
function buildConditions(params) {
var conditions = [];
var values = [];
var conditionsStr;
if (typeof params.name !== 'undefined') {
conditions.push("name LIKE ?");
values.push("%" + params.name + "%");
}
if (typeof params.age !== 'undefined') {
conditions.push("age = ?");
values.push(parseInt(params.age));
}
return {
where: conditions.length ?
conditions.join(' AND ') : '1',
values: values
};
}
var conditions = buildConditions(params);
var sql = 'SELECT * FROM table WHERE ' + conditions.where;
connection.query(sql, conditions.values, function(err, results) {
// do things
});