18

山姆麦克白的问题

JDBC 规范中有什么允许的吗?被转义并成为参数占位符以外的任何东西?

例如,Postgres 允许您?用作运算符:

SELECT * FROM tbl WHERE tbl.data ? 'abc'

一个 JDBC 驱动程序可以让您使用吗?作为操作员仍然是 JDBC 兼容的?

4

3 回答 3

11

如果您有最新的 postgresql 驱动程序,您可以使用:

??

更改原始查询:

SELECT * FROM tbl WHERE tbl.data ?? 'abc'

详细信息在此拉取请求中 - https://github.com/pgjdbc/pgjdbc/pull/227 此更改是在原始问题之后很久才进行的,但值得注意的是现在有一个简单的答案。

于 2015-05-28T21:31:55.593 回答
8

我认为如果 JDBC 驱动程序允许?操作符不转义并按原样使用,那将是完全可以接受的,但它可能 1)使您的解析器复杂化以实际识别来自该操作符的参数,并且 2)可能会混淆人们(可能还有工具) 习惯于?仅表示参数占位符。

所以我的建议是提供某种转义(或替代运算符)。但是查看 JDBC 规范,驱动程序应该只使用 JDBC 转义语法来实现 JDBC 规范中定义的转义(13.4.2:“转义语法不打算用于调用用户定义的或供应商特定的标量函数。 “;虽然这是专门关于{fn ...}逃跑的)。

因此,要么您需要使用替代转义,要么“打破”规则(我认为没有人会介意)。如果您想要更权威的答案,可以将您的问题发送到jdbc-spec-discuss 邮件列表。我相信 Lance Andersen(JDBC 规范负责人)会提供答案。

编辑

同样有趣的是,JDBC 规范第 6.2 节(指南和要求)说:

驱动程序应该提供对底层数据源实现的每个特性的访问,包括扩展 JDBC API 的特性。目的是让使用 JDBC API 的应用程序能够访问与本机应用程序相同的功能集。

因此,基于您应该(不是必须)支持?-operator,您只需要找到一种实用的方法即可。


基于jdbc-spec-discuss 上的讨论进行更新

根据 Lance Andersen 的说法,关于问号,JDBC 规范遵循 SQL 规范:它们只能用作查询文本中的参数占位符(当然注释和引用文本除外),因为?在 PostgreSQL hstore 运算符中使用 as 会不被允许。(见此消息

可用的选项是为操作员提供别名或转义,前提是这与未来的更改不冲突(如果没有千里眼,这很难做到;)。最好的解决方案 - 防止未来 JDBC 更改出现问题 - 可能是自定义转义。

JDBC 实际上并没有定义供应商转义,但 Lance Andersen 确实提出了一种类似于 JDBC 转义的转义{postgres <thing to be escaped>}:在此转义中使用供应商名称或驱动程序名称将提供一种命名空间形式,以防止与规范冲突。(见此消息

为了符合“正常”的 JDBC 函数转义,我建议定义一个转义,允许您的问题中的查询表述为:

SELECT * FROM tbl WHERE {postgres containskey(tbl.data, 'abc')}

我是根据hstore 文档containskey的含义选择的。: ) 和:的类似建议。为了保持一致性,您也可以考虑对其他 hstore 运算符执行此操作。??&containsallkeys?|containsanykey

您也可以决定只转义问号本身。例如用{postgres '?'}or转义{postgres qm}(qm 表示问号)。我确实认为可读性低于我的函数转义建议:

SELECT * FROM tbl WHERE tbl.data {postgres '?'} 'abc'

根据 JDBC v.Next (4.4?) 的新提案进行了更新

下一个 JDBC 规范(可能编号为 4.4)可能会添加显式 JDBC 转义以完全转义查询片段,其明确意图是能够为不使用问号作为参数标记的数据库系统转义问号并且需要支持问号的其他用途。

建议的语法是{\ <thing-to escape> \}(Oracle JDBC 驱动程序已将其作为非标准转义支持)。使用这种语法,参数标记可以用{\?\}(在字符串文字中:){\\?\\}转义,或者转义更大的片段以提高可读性。

另请参阅SQL 2016 MATCH RECOGNIZE JDBC parameter Marker / Escape Characters和jdbc-spec-discuss 邮件列表上的早期讨论。

于 2013-02-09T08:55:53.570 回答
5

我在JDBC 规范中看不到任何允许?转义的内容。几乎所有它说的?是:

参数标记,用“?”表示 在 SQL 字符串中,用于指定在运行时可能会发生变化的语句的输入值。[1]

然后...

参数序号是传递给适当的 setter 方法的整数,指的是语句中的参数标记(“?”),从 1 开始。[2]

而且它只为一小组特性定义了转义语法,看起来它们都不能应用于?

JDBC 为以下内容定义了转义语法:

  • 标量函数
  • 日期和时间文字
  • 外连接
  • 调用存储过程
  • LIKE 子句的转义字符[3]

总体而言,JDBC 规范似乎没有非常“严格”的语言(例如,与某些 W3C 规范文档相比,它大量使用mustshould),所以我不知道是否允许使用的驱动?程序escaped 在技术上是不兼容的,但它可能不太兼容。

它甚至看起来甚至连 Postgres 驱动程序都不允许,因为驱动程序中实际解析 SQL 语句的方法? 不检查任何转义字符


1. JDBC 4.1 规范,第 13.2 节 —PreparedStatement接口
2. JDBC 4.1 规范,第 13.3.2 节 — 设置参数
3. JDBC 4.1 规范,第 13.4 节 — 转义语法

于 2013-02-08T21:44:18.983 回答