首页 > 解决方案 > 如何将单引号内的参数传递给 postgres 查询?

问题描述

在我的节点应用程序中,我需要在查询下运行,并且我正在动态传递参数。但它没有获取参数,因为它们在单引号内引用。为此提出解决方案。

const text = `UPDATE glacier_restore_progress
            SET 
            status='completed',
            restore_end=CURRENT_TIMESTAMP,
            restore_expire=DATE_TRUNC('minutes', current_timestamp + interval '$1 minutes')
            WHERE file_path = '$2' AND date_trunc('minutes', current_timestamp - interval '$1 minutes') <= restore_start`;

const values = [restoreDuration, fileKey];
await pool.query(text, values);

我得到的错误是,

"bind message supplies 2 parameters, but prepared statement \"\" requires 0"

标签: node.jspostgresql

解决方案


你是绝对正确的; 参数不能在引号内。我们有几种方法可以解决这个问题:

以同样破碎的例子SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL '$1 years';

  1. 让客户提交“完整”值:SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL $1;
  2. 在查询中构造字符串:SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL ($1 || ' years');
  3. (特定于时间间隔)使用可以将单位指定为自己的关键字的事实:SELECT * FROM employees WHERE CURRENT_TIMESTAMP - start_date < INTERVAL $1 MINUTE

在这种情况下,我的偏好是 1,但最忠实于您的问题的是 3。小心使用MINUTE而不是MINUTES. 使用连接运算符的选项 2 是您的工具带中的一个很好的技巧。在 Postgres 13 中测试的所有答案。

除此之外,您的参数可能会绑定为数字,这会给您带来错误。您可能需要将其转换为文本,如下所示$1::TEXT

您的完整查询将是:

UPDATE glacier_restore_progress
SET
    status = 'completed',
    restore_end = CURRENT_TIMESTAMP,
    restore_expire = DATE_TRUNC('minutes', CURRENT_TIMESTAMP + INTERVAL $1::TEXT MINUTE)
WHERE file_path = $2
  AND DATE_TRUNC('minutes', current_timestamp - INTERVAL $1 MINUTE) <= restore_start

推荐阅读