我正在使用PostgreSQL 9.4和令人敬畏的JSONB字段类型。我试图查询文档中的字段。以下适用于psql CLI
SELECT id FROM program WHERE document -> 'dept' ? 'CS'
当我尝试通过我的Scala应用程序运行相同的查询时,我收到以下错误。我正在使用Play框架和Anorm,因此查询看起来像这样
SQL(s"SELECT id FROM program WHERE document -> 'dept' ? {dept}")
.on('dept -> "CS")
....
SQLException ::没有为参数5指定值。 (SimpleParameterList.java:223)
(在我的实际查询中有更多参数)
我可以通过将我的参数转换为jsonb
并使用@>
运算符来检查包含来解决此问题。
SQL(s"SELECT id FROM program WHERE document -> 'dept' @> {dept}::jsonb")
.on('dept -> "CS")
....
我不太热衷于工作。我不知道是否会对演员表现出性能损失,但这是额外的打字,并且不明显。
我还能做些什么吗?
答案 0 :(得分:7)
作为避免的解决方法?运算符,您可以创建一个完全相同的new operator。
这是原始运算符的代码:
CREATE OPERATOR ?(
PROCEDURE = jsonb_exists,
LEFTARG = jsonb,
RIGHTARG = text,
RESTRICT = contsel,
JOIN = contjoinsel);
SELECT '{"a":1, "b":2}'::jsonb ? 'b'; -- true
使用其他名称,没有任何冲突,例如# - #并创建一个新名称:
CREATE OPERATOR #-#(
PROCEDURE = jsonb_exists,
LEFTARG = jsonb,
RIGHTARG = text,
RESTRICT = contsel,
JOIN = contjoinsel);
SELECT '{"a":1, "b":2}'::jsonb #-# 'b'; -- true
在您的代码中使用此新运算符,它应该可以正常工作。
检查pgAdmin - > pg_catalog - >所有运营商使用的运营商?在名称中。
答案 1 :(得分:4)
在JDBC(和标准SQL)中,问号被保留为参数占位符。其他用途是不允许的。
请参阅Does the JDBC spec prevent '?' from being used as an operator (outside of quotes)?和discussion on jdbc-spec-discuss。
当前的PostgreSQL JDBC驱动程序会将问号的所有出现(文本或注释之外)转换为PostgreSQL特定的参数占位符。我不确定PostgreSQL JDBC项目是否已经做了任何事情(比如在上面的链接中引入了一个转义)来解决这个问题。快速查看代码和文档表明他们没有,但我没有深入挖掘。
附录:如the answer by bobmarksie所示,PostgreSQL JDBC驱动程序的当前版本现在支持通过加倍来回避问号(即:使用??
代替{{ 1}})。
答案 2 :(得分:2)
几天前我遇到了同样的问题,经过一番调查后我发现了这个问题。
https://jdbc.postgresql.org/documentation/head/statement.html
在JDBC中,问号(
var textarea = document.getElementsByName("your-message")[0]; textarea.value = booking;
)是PreparedStatement的位置参数的占位符。但是,有许多PostgreSQL运算符包含问号。要使SQL语句中的此类问号不被解释为位置参数,请使用两个问号(?
)作为转义序列。您也可以在Statement中使用此转义序列,但这不是必需的。特别是在语句中,单个(??
)可以用作运算符。
使用2个问号似乎对我有用 - 我使用以下驱动程序(使用maven依赖关系说明)...
?
...和MyBatis用于创建SQL查询,它似乎运行良好。看起来比创建PostgreSQL运算符更容易/更清洁。
SQL来自例如
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1201-jdbc41</version>
</dependency>
...到......
select * from user_docs where userTags ?| array['sport','property']
希望这适用于您的场景!
答案 3 :(得分:0)
正如鲍勃所说,只需使用??
而不是?
SQL(s"SELECT id FROM program WHERE document -> 'dept' ?? {dept}")
.on('dept -> "CS")