带有 CTE 的 pg-promise 动态列

pg-promise Dynamic Columns with CTE

我正在尝试使用 pg-promise 在快速服务器上使用 AJAX 请求更新我的数据库。

到目前为止一切正常,但现在我想使用 CTE (WITH) 更新两个表,这也可以正常工作。我现在想做的是能够拥有动态列,具体取决于 PUT 请求。

澄清一下:

  1. 请求

    {
        "dob": "01.01.1970",
        "email": "example@example.com",
        "street": "street 1",
    }
    
  2. 请求

    { 
        "dob": "01.01.1970",
        "email": "example@example.com",
        "phone": "0000",
        "tag": "blue",
    }
    

我尝试了以下方法并且有效,但我的问题是:

  1. 我使用 pg-promise 正确吗?
  2. 这种方法仍然SQL 注入安全吗 (:raw)?
  3. 有没有更好的方法达到同样的效果?

QueryFile.sql

WITH update_table_one AS (
    UPDATE table_one SET username=${username} 
    WHERE identification_number=${identification_number}
    RETURNING identification_number
)       
UPDATE table_two SET ${fromSet:raw}
WHERE identification_number=(SELECT identification_number FROM update_table_one);

Server.js

let qf = // ...QueryFile
let helpers = pgp.helpers;
let user = req.params.user;
let body = req.body;

let dbBody = {
    username: user,
    identification_number: 'ABC123',
    fromSet: helpers.sets(body)
};

db.oneOrNone(qf, dbBody)
    .then(data => {
        res.json({ success: true, message: 'Yes!' });
    })
    .catch(error => {
        res.json({ success: false, message: 'No!' });
    });

对初始问题的补充(与我在评论中的问题有关):

    { 
        "dob": "01.01.1970",
        "email": "example@example.com",
        "street": "street 1",
        "phone": "0000",
        "tag": "blue",
        "group": "students",
        "password": "hash",
        "track": "one",
    }

Am I using pg-promise correctly?

差不多。您的查询没有 return 任何内容,因此请改用 oneOrNone is logically incorrect, it should be none 方法。

Is this approach still SQL injection safe (:raw)?

是的,因为即使您正在注入原始数据集,列也会根据它们的 JavaScript 类型在 helpers 中自动预转义,因此任何注入尝试都会在那里被挫败。

Is there a better way to achieve the same results?

只有事先知道所有的列,才能将它们预先声明为 ColumnSet,以获得更好的性能 and/or 类型转换。但除此之外,没有。

另外请记住,如果您调用 helpers.sets(body) 不传递任何列,它将 return 一个空字符串,如 per the API,这反过来会导致无效UPDATE.