mysql - 如何在node.js-sql中通过绑定(bind)参数构建动态查询?

标签 mysql node.js

我最近使用 nodejs-mysql 模块在 node.js 中进行查询,在我的工作案例中,我只能使用参数绑定(bind)语法,如:

SELECT * FROM table WHERE name = ?

现在我想用这些 ??? 参数构建动态 sql。假设我有 2 个条件(nameage),其中任何一个都可以为 null(如果用户不提供), 所以我想分3种情况搭建MySQL:

  1. name=Bob:SELECT * FROM table WHERE name = 'Bob'
  2. age=40:SELECT * FROM table WHERE age > 40
  3. 两者:SELECT * FROM table WHERE name = 'Bob' AND age > 40

我知道如果您自己构建查询很容易,但是如果使用只能绑定(bind)字段或值的占位符,我该如何实现呢?

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 和 Controller ,所以我能做什么就是定义interface,这是一个带占位符的sql字符串。所以,接口(interface)字符串是之前预定义的,我不能在我的 Controller 函数中修改它。

最佳答案

您的开端非常好,但您可能想得太多了。诀窍是使用占位符 (?) 作为字符串构建查询,同时构建值数组。

因此,如果您有 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
});

关于mysql - 如何在node.js-sql中通过绑定(bind)参数构建动态查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31822891/

相关文章:

mysql - SQL概念: nested loop

mysql - 使用 MySql2 将 Heroku 连接到 RDS

javascript - Opera Unite 和 Node.js 有什么区别?

node.js - graphql-tag/index 没有导出成员 'gql'

php - 使用 php 从 mysql 数据库中读取 blob

mysql - 总结mysql中日期时间的多个datediff

mysql - MySQL COUNT() 和连接的问题

node.js - 需要在 Material 数据表中显示嵌套的 JSON 对象

node.js - OpenShift 上使用 Node.js、express 和 socket.io 的 Access-Control-Allow-Origin

javascript - 如何在 Express API 中显示 Sequelize 验证错误消息