【问题标题】:Possible to add dynamic WHERE clause with a QueryFile?可以使用 QueryFile 添加动态 WHERE 子句吗?
【发布时间】:2020-01-08 12:25:30
【问题描述】:

我有一个存储在 SQL 文件中的复杂查询,我想将它重用于各种路由,但根据路由更改 WHERE 子句。这将代替在多个文件中进行大型复杂查询,唯一的区别是 WHERE 语句。

是否可以在使用 QueryFile 时动态添加 WHERE?简化示例如下:

SELECT "id", "userId", "locationId", "title", "body",
  (
    SELECT row_to_json(sqUser)
    FROM (
      SELECT "id", "firstname", "lastname"
      FROM "users"
          WHERE "users"."id" = "todos"."userId"
      ) sqUser
  ) as "user"
FROM "todos"
const queryIndex = new pgp.QueryFile('sql/todos/index.pgsql', queryOptions);
// 1. Use as is to get a list of all todos
// 2. OR Append WHERE "locationId" = $1 to get list filtered by location
// 3. OR Append WHERE "id" = $1 to get a specific item
// without having three separate SQL files?

看起来(也许?)您可以在查询文件中添加以下内容,但这仍然感觉有限(仍然需要两个文件用于 =LIKE,并且它仍然仅限于一个 WHERE 条件)。执行 WHERE 1 = 1 之类的操作来返回所有记录也感觉很奇怪。

WHERE $1 = $2

我很想听听人们对此的想法,或者是否有更好的方法。

【问题讨论】:

    标签: node.js postgresql pg-promise


    【解决方案1】:

    您可以将动态条件作为Raw Text 注入到查询文件中:

    SELECT "id", "userId", "locationId", "title", "body",
      (
        SELECT row_to_json(sqUser)
        FROM (
          SELECT "id", "firstname", "lastname"
          FROM "users"
              ${condition:raw}
          ) sqUser
      ) as "user"
    FROM "todos"
    

    预先格式化的参数,基于条件:

    // Generate a condition, based on the business logic:
    const condition = pgp.as.format('WHERE col_1 = $1 AND col_2 = $2', [111, 222]);
    

    执行您的查询文件:

    await db.any(myQueryFile, {condition});
    

    高级

    以上内容适用于您想要在代码中生成简单动态条件的情况。但有时您可能需要交替使用复杂的静态条件。在这种情况下,您可以让您的主查询文件引用从属查询文件中的条件(开箱即用支持嵌套查询文件)。在这种情况下,您甚至不需要使用:raw 过滤器,因为默认情况下查询文件是作为原始文本注入的:

    主查询:

    SELECT * FROM table ${condition}
    

    加载具有复杂条件的从属查询文件(应用启动时):

    const conditionQueryFile1 = new QueryFile(...);
    const conditionQueryFile2 = new QueryFile(...);
    

    根据业务逻辑选择正确的从属查询:

    const condition = conditionQueryFile1; // some business logic here;
    

    以slave为参数执行master查询:

    await db.any(myQueryFile, {condition});
    

    【讨论】:

    • 感谢@vitaly-t 的快速回复。这是有道理的,我在查看文档时错过了pgp.as.format 。很棒的图书馆,感谢您的辛勤工作。
    • @bergy 另请参阅我刚刚添加的高级部分;)
    • 你能举一个使用QueryFiles的动态条件的例子吗?在应用启动时初始化查询文件时,参数并不总是已知的,因此将params 传递给QueryFile 构造函数是不可行的。我通过使用参数格式化辅助QueryFile 并将其作为:raw 包含在主要QueryFile 中解决了这个问题。只是想知道这是否是最好的方法。
    • params 用于两步格式化。你的所作所为是无关的。你的方法听起来很正常,应该没问题。
    猜你喜欢
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多