将同一变量传递到 SQL 语句的多个部分时出错

Error with passing in the same variable into multiple parts of SQL statement

所以我有一个 Node.js 查询,它应该传入这三个值,并为具有特定 ID 的用户按特定数量更新特定列:

await client.query(sqlStatement, [columnName, changeBy, id])

'sqlStatement' 看起来像:

'UPDATE tableName SET () = () + () WHERE id = ()'

如您所见,它应该传递值,使 SQL 语句看起来像:

'UPDATE tableName SET columnName = columnName + changeBy WHERE id = id'

我也试过如下编写 sqlStatement(只将 columnName 传入查询两次,但这也会导致错误:

'UPDATE tableName SET () = () + () WHERE id = ()'

返回的错误是错误:“$1”处或附近的语法错误。

不确定如何解决此问题 - 非常感谢任何帮助。

发生这种情况的原因是 node-postgres doesn't support query parameters for identifiersSET 之后的列名称是一个标识符。此外,即使这可行,除非 node-postgres 以某种方式用整个 ()(带括号)代替你的价值,你会得到

ERROR: source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression.

如果您希望保留 node-postgres,它的 documentation recommends to use pg-format in such cases, to build a dynamic SQL statement. If you consider alternatives, you can look into Knex.js 将为您构建查询,如下所示:

knex('tableName')
   .update({ 
       columnName: knex.raw('?? + ?',['columnName',changeBy])
   })
   .where('id', id)

同时,作为一种解决方法,您应该能够将 sqlStatement 设置为您自己的动态 SQL 查询:

do language plpgsql $$ begin execute format('UPDATE test SET %I = %I + %s WHERE id = %s','','',,); end$$;

然后尝试一下。请注意,我删除了更新列周围的括号以避免多列更新错误。应该发生的是 node-postgres 将以上计算为

do language plpgsql $$ begin execute format('UPDATE test SET %I = %I + %s WHERE id = %s','col','col',51,72); end$$;

并将其传递给 PostgreSQL,后者应将其执行为

UPDATE test SET "col" = "col" + 51 WHERE id = 72;

来自doc:

  • %I 用于 I 标识符,如果需要,PostgreSQL 将自动引用。
  • %L 用于字符串 Literals
  • %s 用于 simple string 替换,在某种意义上它不会被引用,所以它可用于数字文字