如何使用JDBC引用/转义列名等标识符?

adi*_*tsu 8 java jdbc

不同的数据库服务器使用不同的方式引用和转义标识符

例如,"foo bar"vs"foo bar"vs [foo bar],或"10"""vs"10 \"",或者某些数据库需要引用FooBar或数组等标识符,而其他数据库则不需要引用.

是否有任何API方法可以为给定的数据库连接正确执行引用/转义?或任何替代解决方案?

use*_*421 14

看一下

DatabaseMetaData.getIdentifierQuoteString()
Run Code Online (Sandbox Code Playgroud)

我从来没用过它,但听起来不错:-)

getExtraNameCharacters() 也可以提供一些帮助


Sto*_*ica 6

从 Java 9 开始,该Statement接口为特定于引擎的引用提供了各种方法:

  • enquoteIdentifier 用于 SQL 标识符(例如架构、表、列名称)
  • enquoteLiteral 用于字符串文字(例如 char、varchar、文本文字)
  • enquoteNCharLiteral 用于国家字符集文字
Statement stmt = connection.createStatement();
String query = String.format(
        "SELECT id FROM %s WHERE name = %s",
        stmt.enquoteIdentifier("table", false),
        stmt.enquoteLiteral("it's"));
ResultSet resultSet = stmt.executeQuery(query);
Run Code Online (Sandbox Code Playgroud)

但是,只要有可能(即对于 CRUD 查询中的值),请改用准备好的语句。

Statement stmtFormat = connection.createStatement();
String query = String.format(
        "SELECT id FROM %s WHERE name = ?", 
        stmtFormat.enquoteIdentifier("table", false);
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, "it's");
ResultSet resultSet = stmt.executeQuery();
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案。 (3认同)

Yis*_*hai 0

我认为您问题的答案是,如果您正在使用 JDBC 编写数据库中立应用程序,那么您需要使用数据库中立名称,而不是需要每个数据库供应商进行特殊转义的名称。

据我所知,JDBC 中没有任何支持这一点的信息。ORM 产品将处理此类事情。

编辑:如果你正在编写一个 ORM,那么我认为需要为每个支持的数据库提供一个单独的 SQL 生成类,只是为了处理涉及的各种语法,所以你必须编写它。您当然可以查看各种开源 ORM 的源代码,看看它们是如何处理它的。

  • @PaulTomblin 嘿,是的,“标准”。规范中有很大的灵活性 - 供应商添加自己的关键字和保留字,如果应用程序要使用它们,则必须引用它们。我同意尝试遵守规范是最不痛苦的选择,但 JDBC 不公开“java.sql.Connection.quoteIdentifier(...)”或“DatabaseMetaData.quoteIdentifier(...”,这很“糟糕”。 )` 方法并支持 SPI,因为这意味着您总是在进行保留​​字舞蹈。`getIdentifierQuoteString` 不做这个工作,它不表达引用规则。 (3认同)
  • 关于数据库中立名称的观点很好,但仍然可能会出现意外(例如,某个标识符在另一个数据库中可能不可接受)。另外,如果我......实际上正在编写一个 ORM 该怎么办?是否需要为每个受支持的数据库单独的手动编码引用/转义实现? (2认同)
  • @PaulTomblin Heh,这里的专用 PostgreSQL 用户。奇怪的是,在 Pg 的解析器难以区分未保留关键字和用户标识符的情况下,我有必要这样做,但总的来说,这并没有太大问题。我只是感到恼火的是,JDBC 规范使得应用程序防御性地引用标识符以及 JDBC 驱动程序暴露其正确引用的知识变得比应有的困难。(除非你是 MySQL 或 MS SQL Server,否则无论如何都是 ANSI SQL 引用) (2认同)