通过命令行将变量传递给 psql 文件。一个变量通过了另一个没有

Passing Variable in to psql file via command line. One variable passes other doesnt

我正在尝试通过命令行中的 psql 将两个变量传递到我 运行 的 .psql 文件中。我的一个变量转换为另一个不转换的值。 var1(靠近 where 子句的语句末尾的 id 值转换得很好,但 var2 作为 json 检查 id 的一部分的变量未转换。我认为这与我的方式有关逃避事情但玩了一个小时后我被困住了。谢谢

命令行

psql -h 127.0.0.1 -f "delete.psql" -v var1="$var1" -v var2="$var2"

delete.sql

update data
   set value = jsonb_set(value, '{my_items}',
   jsonb_path_query_array(value->'item', '$ ? (@."id" <> (:'var2') )')) where id=(:'var1') ;

返回错误,因为缺少 var2 的转换

psql:delete.psql:3: ERROR:  syntax error at or near "var2"
LINE 3: ...th_query_array(value->'my_items', '$ ? (@."id" <> (:'var2')...
                                                                ^

问题是 引用的字符串文字中不执行变量插值。所以这块不行:

'$ ? (@."id" <> (:'var2') )'

The manual:

Variable interpolation will not be performed within quoted SQL literals and identifiers.

解决简单情况的一种方法是连接字符串。但是你的情况并不是那么简单,因为你真的想要一个 jsonpath 类型的参数,你可以很容易地为 SQL 注入空间...

jsonb_path_query_array() 有自己的方式在类型为 jsonb 的名为“vars”的第三个参数中传递变量。这是继续进行的安全方法。

或者$var2 作为合法的 jsonb 文字传递,例如:'{"var2" : "foo"}'。那么您的 UPDATE 查询可以是:

update data set value = jsonb_set(value, '{my_items}', jsonb_path_query_array(value->'item', '$ ? (@."id" <> $var2)', :'var2')) where id = :'var1';

继续传递裸字符串值并让 Postgres 动态构造“vars”参数:jsonb_build_object('var2', :'var2'))

那么您的 UPDATE 查询可以是:

update data set value = jsonb_set(value, '{my_items}', jsonb_path_query_array(value->'item', '$ ? (@."id" <> $var2)', jsonb_build_object('var2', :'var2'))) where id = :'var1';

还删除了一些噪音括号。

相关:

  • use \set variable inside plpgsql declare block

您正确地引用了变量。参见:

  • How can I quote a named argument passed in to psql?

有多种替代方法:准备好的语句、(临时)函数...参见: