动态构建 SQL 查询(使用 PostgreSQL 和 JavaScript)

huangapple go评论91阅读模式
英文:

Dynamically building a SQL query (postgres and javascript)

问题

我有一个需要返回产品列表的 JavaScript 函数。它使用 postgres 来检索产品列表。该函数接收一个 categoryId 和一个可选的 typeId。因此,我需要根据这些条件构建一个 SQL 查询。

当然,我可以这样做:

async function getProducts(categoryId, typeId = false) {
  let products;
  if (typeId) {
    products = await sql`select * from products where categoryId=${categoryId} and typeId=${typeId}`
  }
  else {
    products = await sql`select * from products where categoryId=${categoryId}`
  }
  return products;
}

但是,我如何使用模板字面量语法动态地构建 SQL 查询呢?

类似这样:

async function getProducts(categoryId, typeId = false) {
  let query = `select * from products where categoryId=${categoryId}`;
  if (typeId) {
    query += ` AND typeId=${typeId}`;
  }
  products = await sql`${query}` // 这样不起作用,那么我该如何生成这样一个动态查询呢?
  return products;
}

(注意:这里使用了 @vercel/postgres)

英文:

I have a javascript function that needs to return a list of products. It's using postgres to retrieve the list of products. The function is passed a categoryId and an optional typeId. So I need to build a SQL query based on these.

Of course I could do something like this:

async function getProducts(categoryId, typeId = false) {
  let products;
  if (typeId) {
    products = await sql`select * from products where categoryId=${categoryId} and typeId=${typeId}`
  }
  else {
    products = await sql`select * from products where categoryId=${categoryId}`
  }
  return products;
}

But how could I somehow dynamically "build" the SQL query with the template literals syntax?

Something like this:

async function getProducts(categoryId, typeId = false) {
let query = `select * from products where categoryId=${categoryId}`;
if (typeId) {
  query += ` AND typeId=${typeId}`;
}
products = await sql`${query}` // doesn't work, so how could I generate a dynamic query like this?
return products;
}

(Note: this is using @vercel/postgres)

答案1

得分: 0

这是要翻译的内容:

Vercel没有提供文档,但他们的 @vercel/postgres 包只是 @neondatabase/serverless 的一个紧密封装,所以你也可以使用 它们的方法sql`…`, pool.sql`…`client.sql`…` 模板标签不能以其他方式使用,如果不与模板字符串一起使用,它们会抛出异常。然而,你可以使用 .query() 方法,该方法将查询文本和参数值作为单独的参数传入:

async function getProducts(categoryId, typeId) {
  let query = `select * from products where categoryId=$1`;
  let params = [categoryId];
  if (typeId != null) {
    query += ` AND typeId=$2`;
    params.push(typeId);
  }
  const products = await sql.query(query, params);
  return products;
}

当然,手动构建 SQL 字符串是有风险的 - 它容易导致语法错误和 SQL 注入安全漏洞。确保始终使用参数化查询,不要将动态值插入到查询中。

对于常见用例(如具有不同字段的动态条件),考虑使用 ORM 或查询构建器库,它们配备了经过验证的辅助函数来处理这些事情。

英文:

It's not documented by Vercel but their @vercel/postgres package is just a tight wrapper around @neondatabase/serverless so you can use their methods as well. The sql`…`, pool.sql`…` and client.sql`…` template tags cannot be used in any other way, they will throw an exception when not used with a template string. However, you can use the .query() method which takes the query test and the parameter values as separate arguments:

async function getProducts(categoryId, typeId) {
  let query = `select * from products where categoryId=$1`;
  let params = [categoryId];
  if (typeId != null) {
    query += ` AND typeId=$2`;
    params.push(typeId);
  }
  const products = await sql.query(query, params);
  return products;
}

Of course, building SQL strings manually is risky - it easily leads to syntax errors and SQL injection security vulnerabilities in your software. Make sure to always use parameterised queries and never interpolate dynamic values into your queries.

For common use cases (like dynamic conditions with various fields) consider using an ORM or query builder library instead, they come equipped with tried-and-tested helper functions for these things.

huangapple
  • 本文由 发表于 2023年8月9日 03:40:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862758.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定