将同一变量传递到 SQL 语句的多个部分时出错
Posted
技术标签:
【中文标题】将同一变量传递到 SQL 语句的多个部分时出错【英文标题】:Error with passing in the same variable into multiple parts of SQL statement 【发布时间】:2022-01-09 12:45:33 【问题描述】:所以我有一个 Node.js 查询,它应该传入这三个值,并为具有特定 id 的用户按特定数量更新特定列:
await client.query(sqlStatement, [columnName, changeBy, id])
“sqlStatement”看起来像:
'UPDATE tableName SET ($1) = ($1) + ($2) WHERE id = ($3)'
如您所见,它应该传入 SQL 语句如下所示的值:
'UPDATE tableName SET columnName = columnName + changeBy WHERE id = id'
我也尝试将 sqlStatement 编写如下(并且只需将 columnName 两次传递到查询中,但这也会导致错误:
'UPDATE tableName SET ($1) = ($2) + ($3) WHERE id = ($4)'
返回的错误是error: syntax error at or near "$1"。
不知道如何解决这个问题——非常感谢任何帮助。
【问题讨论】:
【参考方案1】:发生这种情况的原因是node-postgres
doesn't support query parameters for identifiers 和SET
之后的列名是一个标识符。此外,即使这有效,除非 node-postgres
以某种方式将整个 ($1)
(带括号)替换为您的值,否则您会得到
ERROR: source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression
.
如果你想保留node-postgres
,它的documentation建议在这种情况下使用pg-format来构建动态SQL语句。如果您考虑替代方案,您可以查看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','$1','$1',$2,$3); 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
用于s简单的s字符串替换,在某种意义上它不会被引用,所以它可以用于数字文字
【讨论】:
以上是关于将同一变量传递到 SQL 语句的多个部分时出错的主要内容,如果未能解决你的问题,请参考以下文章