Javascript 处理潜在未定义值时创建SQL SELECT查询的最佳实践

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<

我目前正在使用PostgreSQL via创建一个NodeJS网站

我有一个带有HTML表单的页面,该页面带有复选框,用于选择变量以搜索数据库中使用的各种字段。然后将它们输入带有
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]) + ')';