Javascript 处理潜在未定义值时创建SQL SELECT查询的最佳实践
我目前正在使用PostgreSQL via创建一个NodeJS网站 我有一个带有HTML表单的页面,该页面带有复选框,用于选择变量以搜索数据库中使用的各种字段。然后将它们输入带有Javascript 处理潜在未定义值时创建SQL SELECT查询的最佳实践,javascript,sql,node.js,postgresql,pg-promise,Javascript,Sql,Node.js,Postgresql,Pg Promise,我目前正在使用PostgreSQL via创建一个NodeJS网站 我有一个带有HTML表单的页面,该页面带有复选框,用于选择变量以搜索数据库中使用的各种字段。然后将它们输入带有pg promise的SQL查询,预期的行为是将结果以JSON格式传递回用户 下面是一个非常简单的工作示例 HTML格式: <form action="/search" method="get"> <fieldset> <legend>Variable A<
pg promise
的SQL查询,预期的行为是将结果以JSON格式传递回用户
下面是一个非常简单的工作示例
HTML格式:
<form action="/search" method="get">
<fieldset>
<legend>Variable A</legend>
<div>
<input type="checkbox" name="variable_a" value="apple">
<label for="variable_a">
Apple
</label>
</div>
<div>
<input type="checkbox" name="variable_a" value="orange">
<label for="variable_a">
Orange
</label>
</div>
</fieldset>
<fieldset>
<legend>Variable B</legend>
<div>
<input type="checkbox" name="variable_b" value="pear">
<label for="variable_b">
Pear
</label>
</div>
<div>
<input type="checkbox" name="variable_b" value="banana">
<label for="variable_b">
Banana
</label>
</div>
</fieldset>
<button type="submit">Search</button>
</form>
给定/search?variable_b=pear&variable_b=banana
URL,此操作将失败,但可以使用以下URL/search?variable_a=apple&variable_b=banana
这无疑是因为在上面的示例中,req.query.variable_a
未定义,因为没有选中复选框,SQL查询将以的形式在()中结束。如果variable_a
或variable_b
未通过复选框定义,我可能需要添加,在这种情况下,预期的行为是在所述列上没有过滤器
我的问题是什么是最好的处理方法
我觉得我可能可以创建很多if/else逻辑来处理潜在的未定义的req.query
变量和生成的SQL查询,但这看起来很混乱,也不优雅。首先-您的输入将只保留最后选择的值
<input type="checkbox" name="variable_a" value="apple">
在您的SQL中——如果您没有发送任何变量——您希望得到结果
导致其strict和statement-var未定义-查询返回false此问题与此处记录的问题相同:
基本上,查询格式化引擎根据格式化参数生成SQL。它不会对生成的SQL进行任何语法验证
您正在()中生成,
,这是无效的SQL,因此会出现错误
您应该检查变量是否存在,甚至不要在缺少变量时尝试生成这样的查询,因为您的查询将无法生成任何好的结果
示例:
router.get('/search', (req, res, next) => {
const variables = ['variable_a', 'variable_b', 'variable_c'];
const conditions = variables.filter(v => v in req.query)
.map(v => pgp.as.format('$1:name IN ($2:csv)', [v, req.query[v]]))
.join(' AND ');
conditions = conditions && 'WHERE ' + conditions;
db.any('SELECT * FROM food $1:raw', conditions)
.then(result => res.send(result))
.catch(error => {/* handle the error */});
});
可能还有其他解决方案,因为这是非常通用的,它不会限制您处理此问题的方式
例如,与此相反:
v => pgp.as.format('$1:name IN ($2:csv)', [v, req.query[v]])
您可以这样做:
v => pgp.as.name(v) + ' IN (' + pgp.as.csv(req.query[v]) + ')';
这将产生相同的结果。随便你喜欢哪一个!;) 我不太明白为什么第一个查询会失败。但是,听起来您需要构建一个方法来动态构建查询和参数。或者更好的做法是创建一个存储过程,该过程接受变量的参数列表,然后根据参数列表在其中动态构建查询。我认为它失败了,因为它可能计算为SELECT*FROM food,其中变量a IN()和变量b IN('pear','banana')代码>返回ERROR:syntax ERROR at or near')
我相信它指的是参数中的空。哦,我现在明白了,这些输入有效吗?如果不是,可以使用组合框而不是复选框?在这种情况下,它是有效的输入。用户可以使用复选框定义的变量筛选器搜索数据库在variable_a
和/或variable_b
上,或者根本没有,或者两者之间的任何内容。与此相同的问题:复选框按预期工作-例如,如果选中variable_b
的两个复选框,则URL为/search?variable_b=pear&variable_b=banana
,这两个变量都可以通过req.params.variable_b
在数组中。你回答的第二部分我不明白在这种情况下你会如何实施。谢谢,我喜欢这个。没有难看的逻辑,它很好而且简洁。@BML91我做了一些改进,使用:name
过滤器作为列名:谢谢。我认为变量.map()
在之前需要一个.filter(v=>v!==null)
。join()
否则你似乎会在('apple')中得到变量a和这样的东西,对于不存在的变量。@BML91现在这个例子更好了,显示在没有条件时执行非条件查询的最佳方法。
v => pgp.as.format('$1:name IN ($2:csv)', [v, req.query[v]])
v => pgp.as.name(v) + ' IN (' + pgp.as.csv(req.query[v]) + ')';