【发布时间】:2010-01-10 19:04:42
【问题描述】:
不同的数据库服务器使用不同的方式来引用和转义标识符。
例如"foo bar" vs `foo bar` vs [foo bar], or "10""" vs "10\"", 或者 FooBar 或数组之类的标识符需要为某些数据库引用,但对于其他数据库则不需要。
是否有任何 API 方法可以为给定的数据库连接正确执行引用/转义?或者任何替代解决方案?
【问题讨论】:
不同的数据库服务器使用不同的方式来引用和转义标识符。
例如"foo bar" vs `foo bar` vs [foo bar], or "10""" vs "10\"", 或者 FooBar 或数组之类的标识符需要为某些数据库引用,但对于其他数据库则不需要。
是否有任何 API 方法可以为给定的数据库连接正确执行引用/转义?或者任何替代解决方案?
【问题讨论】:
看看
DatabaseMetaData.getIdentifierQuoteString()
我没用过,但听起来不错:-)
getExtraNameCharacters() 也可以提供一些帮助
【讨论】:
从 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);
但是,只要有可能(即对于数据查询中的值),请改用准备好的语句。
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();
【讨论】:
我认为您的问题的答案是,如果您正在使用 JDBC 编写与数据库无关的应用程序,那么您需要使用与数据库无关的名称,而不是需要每个数据库供应商进行特殊转义的名称。
在支持它的 JDBC 中我一无所知。 ORM 产品会处理这些事情。
编辑:如果您正在编写 ORM,那么我认为每个支持的数据库都需要一个单独的 SQL 生成类,只是为了处理所涉及的各种语法,所以您必须编写它。您当然可以查看各种开源 ORM 的源代码,看看它们是如何处理的。
【讨论】:
java.sql.Connection.quoteIdentifier(...) 或 DatabaseMetaData.quoteIdentifier(...) 方法和支持 SPI,因为这意味着你总是在做保留字的舞蹈。 getIdentifierQuoteString 不做这项工作,它不表达引用规则。