使用准备好的语句参数 pg-promise 的 ORDER BY 命令

ORDER BY command using a prepared statement parameter pg-promise

我是 Node、API 和 SQL 的新手,但我碰壁了。我正在使用 pg-promise 准备好的语句,我正在尝试将 sorted 参数与 ORDERED BY 命令一起使用来对结果进行通常的排序,但它并不像往常一样工作进来订购相同。 如果我直接使用参数的名称,它会起作用,你能看出我的查询有什么问题吗? 像往常一样,非常感谢您的时间和帮助。 这是我的方法:

if (city, region, country, category, minPrice, maxPrice, orderedBy, sorted) {
    if (sorted == 'asc') {
      await db.any({
        name: 'get-city-category-price-range-ordered-by-asc-products',
        // text: 'SELECT * FROM products WHERE city =  AND region =  AND country =  AND category =  AND price >=  AND price <=  ORDER BY price ASC', // working
        text: 'SELECT * FROM products WHERE city =  AND region =  AND country =  AND category =  AND price >=  AND price <=  ORDER BY  ASC', // not working
        values: [city, region, country, category, minPrice, maxPrice, orderedBy]
      })
        .then(result => {
          console.log('get-city-category-price-range-ordered-by-asc-products:', result);
          if (result.length > 0) {
            res.status(200).send({
              data: result
            });
          }
          else {
            res.status(404).send({
              error: 'No product found.'
            });
          }
        })
        .catch(function (error) {
          console.log('get-city-category-price-range-ordered-by-asc-products error:', error);
        });

    } else if (sorted == 'desc') {
      await db.any({
        name: 'get-city-category-price-range-ordered-by-desc-products',
        // text: 'SELECT * FROM products WHERE city =  AND region =  AND country =  AND category =  AND price >=  AND price <=  ORDER BY price DESC', // working
        text: 'SELECT * FROM products WHERE city =  AND region =  AND country =  AND category =  AND price >=  AND price <=  ORDER BY  DESC', // not working
        values: [city, region, country, category, minPrice, maxPrice, orderedBy]
      })
        .then(result => {
          console.log('get-city-category-price-range-ordered-by-desc-products:', result);
          if (result.length > 0) {
            res.status(200).send({
              data: result
            });
          }
          else {
            res.status(404).send({
              error: 'No product found.'
            });
          }
        })
        .catch(function (error) {
          console.log('get-city-category-price-range-ordered-by-desc-products error:', error);
        });
    }
  }

不幸的是,您不能将查询参数用于列和 table 名称之类的东西,只能用于值。所以这永远行不通,您需要通过添加正确的“order by”语句来手动构建 SQL 文本。所有关于 SQL 注入的警告都适用,因此请检查您的 orderBy 字段是否有效(例如,只包含字母,没有空格或其他字符)。

当您选择 PreparedStatement, your query formatting is done on the server side. So if you decided to use PreparedStatement for exactly that purpose, to get values formatted by the server, then you will have to do without the rich query formatting that pg-promise supports internally for regular queries, and limiting yourself to what PostgreSQL server can do in that regard. And unlike pg-promise 时,PostgreSQL 服务器不允许在任何地方使用动态 SQL 名称或标识符。

但是,如果您选择 PreparedStatement because you think in your case it will execute faster, then you can still benefit from rich query formatting supported by pg-promise, by formatting the query separately, and then executing PreparedStatement 使用预先格式化的查询,即没有任何参数:

const text = pgp.as.format(`SELECT * FROM products WHERE city = $/city/
                            AND region = $/region/ AND country = $/country/
                            AND category = $/category/
                            AND price BETWEEN $/minPrice/ AND $/maxPrice/
                            ORDER BY $/orderedBy:name/ $/sorted:value/`, {
                              city, region, country, category,
                              minPrice, maxPrice, orderedBy, sorted
                            });

const name = 'get-price-range-ordered-by-products-' + sorted; // unique query name

await db.any({name, text});

如您所见,排序顺序也可以动态设置,无需重复您的代码。我们将 sorted 附加到查询的 name,因为它会生成不同的执行路径,这需要唯一的查询名称。

P.S。我是 pg-promise.

的作者