JDBC 转义
JDBC 规范(类似于 ODBC 规范)承认某些供应商特定的 SQL 可能需要用于某些 RDBMS 功能。为了帮助开发人员跨多个数据库产品编写可移植的 JDBC 应用程序,使用了一种特殊的转义语法来指定开发人员想要运行的通用命令。JDBC 驱动程序将这些转义序列转换为其特定数据库的本机语法。有关更多信息,请参阅 Java DB 技术文档.
可以使用 Statement.setEscapeProcessing(false)
禁用对这些转义的 sql 语句的解析。
Connection.nativeSQL(String sql)
提供了另一种处理转义的方法。它将给定的 SQL 转换为适合 PostgreSQL® 后端的 SQL。
示例 8.1. 使用 JDBC 转义
要使用 JDBC 转义,只需编写您的 SQL,将日期/时间文字值、外连接和函数替换为 JDBC 转义语法。例如
ResultSet rs = st.executeQuery("SELECT {fn week({d '2005-01-24'})}");
是以下内容的可移植版本
ResultSet rs = st.executeQuery("SELECT extract(week from DATE '2005-01-24')");
用于 like 转义字符的转义
您可以通过添加以下转义来指定在字符串比较(使用 LIKE
)中使用哪个转义字符来保护通配符字符(’%’ 和 ‘_’):{escape '转义字符'}
。驱动程序仅在比较表达式的末尾支持此功能。
例如,您可以使用“|”作为转义字符来保护“_”,从而比较字符串值。
rs = stmt.executeQuery("select str2 from comparisontest where str1 like '|_abcd' {escape '|'} ");
外部联接的转义
您可以使用以下语法指定外部联接:{oj table (LEFT|RIGHT|FULL) OUTER JOIN (table | outer-join) ON search-condition}
例如
ResultSet rs = stmt.executeQuery("select * from {oj a left outer join b on (a.i=b.i)} ");
日期时间转义
JDBC 规范定义了用于指定日期、时间和时间戳值的转义符,这些转义符受驱动程序支持。
- 日期:
{d 'yyyy-mm-dd'}
,它被转换为DATE 'yyyy-mm-dd'
- 时间:
{t 'hh:mm:ss'}
,它被转换为TIME 'hh:mm:ss'
- 时间戳:
{ts 'yyyy-mm-dd hh:mm:ss.f...'}
,它被转换为TIMESTAMP 'yyyy-mm-dd hh:mm:ss.f'
。TIMESTAMP 的小数秒部分 (.f…) 可以省略。
转义标量函数
JDBC 规范定义了使用转义调用语法来表示函数:{fn function_name(arguments)}
。以下表格显示了 PostgreSQL® 驱动程序支持的函数。驱动程序支持转义函数和转义值的嵌套和混合。JDBC 规范的附录 C 描述了这些函数。
以下表格中的一些函数被翻译,但报告为不支持,因为它们重复或改变了参数的顺序。虽然这对文字值或列来说是无害的,但它会在使用预处理语句时造成问题。例如 " {fn right(?,?)}
" 将被翻译为 " substring(? from (length(?)+1-?))
"。如您所见,翻译后的 SQL 需要比翻译前更多的参数,但驱动程序不会自动处理这种情况。
表 8.1. 支持的转义数值函数
函数 | 报告为支持 | 翻译 | 评论 |
---|---|---|---|
abs(arg1) | 是 | abs(arg1) | |
acos(arg1) | 是 | acos(arg1) | |
asin(arg1) | 是 | asin(arg1) | |
atan(arg1) | 是 | atan(arg1) | |
atan2(arg1, arg2) | 是 | atan2(arg1, arg2) | |
ceiling(arg1) | 是 | ceil(arg1) | |
cos(arg1) | 是 | cos(arg1) | |
cot(arg1) | 是 | cot(arg1) | |
degrees(arg1) | 是 | degrees(arg1) | |
exp(arg1) | 是 | exp(arg1) | |
floor(arg1) | 是 | floor(arg1) | |
log(arg1) | 是 | ln(arg1) | |
log10(arg1) | 是 | log(arg1) | |
mod(arg1, arg2) | 是 | mod(arg1, arg2) | |
pi(arg1) | 是 | pi(arg1) | |
power(arg1, arg2) | 是 | pow(arg1, arg2) | |
radians(arg1) | 是 | radians(arg1) | |
rand() | 是 | random() | |
rand(arg1) | 是 | setseed(arg1)*0+random() | 使用给定参数初始化种子并返回一个新的随机值。 |
round(arg1, arg2) | 是 | round(arg1, arg2) | |
sign(arg1) | 是 | sign(arg1) | |
sin(arg1) | 是 | sin(arg1) | |
sqrt(arg1) | 是 | sqrt(arg1) | |
tan(arg1) | 是 | tan(arg1) | |
truncate(arg1, arg2) | 是 | trunc(arg1, arg2) |
表 8.2. 支持的转义字符串函数
函数 | 报告为支持 | 翻译 | 评论 |
---|---|---|---|
ascii(arg1) | 是 | ascii(arg1) | |
char(arg1) | 是 | chr(arg1) | |
concat(arg1, arg2…) | 是 | (arg1 | |
insert(arg1, arg2, arg3, arg4) | 否 | overlay(arg1 placing arg4 from arg2 for arg3) | 此功能不支持,因为它会改变参数的顺序,这可能会导致问题(例如,对于预处理语句)。 |
lcase(arg1) | 是 | lower(arg1) | |
left(arg1, arg2) | 是 | substring(arg1 for arg2) | |
length(arg1) | 是 | length(trim(trailing from arg1)) | |
locate(arg1, arg2) | 否 | position(arg1 in arg2) | |
locate(arg1, arg2, arg3) | 否 | (arg2*sign(position(arg1 in substring(arg2 from arg3)+position(arg1 in substring(arg2 from arg3)) | 不支持,因为三个参数版本会复制并改变参数的顺序。 |
ltrim(arg1) | 是 | trim(leading from arg1) | |
repeat(arg1, arg2) | 是 | repeat(arg1, arg2) | |
replace(arg1, arg2, arg3) | 是 | replace(arg1, arg2, arg3) | 仅在 7.3 及更高版本的服务器上报告为支持。 |
right(arg1, arg2) | 否 | substring(arg1 from (length(arg1)+1-arg2)) | 由于 arg2 重复,因此不支持。 |
rtrim(arg1) | 是 | trim(trailing from arg1) | |
space(arg1) | 是 | repeat(’ ‘, arg1) | |
substring(arg1, arg2) | 是 | substr(arg1, arg2) | |
substring(arg1, arg2, arg3) | 是 | substr(arg1, arg2, arg3) | |
ucase(arg1) | 是 | upper(arg1) | |
soundex(arg1) | 否 | soundex(arg1) | 由于需要 fuzzystrmatch 扩展模块,因此不支持。 |
difference(arg1, arg2) | 否 | difference(arg1, arg2) | 由于需要 fuzzystrmatch 扩展模块,因此不支持。 |
表 8.3. 支持的转义日期/时间函数
函数 | 报告为支持 | 翻译 | 评论 |
---|---|---|---|
curdate() | 是 | current_date | |
curtime() | 是 | current_time | |
dayname(arg1) | 是 | to_char(arg1, ‘Day’) | |
dayofmonth(arg1) | 是 | extract(day from arg1) | |
dayofweek(arg1) | 是 | extract(dow from arg1)+1 | 我们必须加 1 才能在预期的 1-7 范围内。 |
dayofyear(arg1) | 是 | extract(doy from arg1) | |
hour(arg1) | 是 | extract(hour from arg1) | |
minute(arg1) | 是 | extract(minute from arg1) | |
month(arg1) | 是 | extract(month from arg1) | |
monthname(arg1) | 是 | to_char(arg1, ‘Month’) | |
now() | 是 | now() | |
quarter(arg1) | 是 | extract(quarter from arg1) | |
second(arg1) | 是 | extract(second from arg1) | |
week(arg1) | 是 | extract(week from arg1) | |
year(arg1) | 是 | extract(year from arg1) | |
timestampadd(argIntervalType, argCount, argTimeStamp) | 是 | ((interval according to argIntervalType and argCount)+argTimeStamp) | 由于后端不支持,因此未实现 argIntervalType 值 SQL_TSI_FRAC_SECOND |
timestampdiff(argIntervalType, argTimeStamp1, argTimeStamp2) | 不 | extract((interval according to argIntervalType) from argTimeStamp2-argTimeStamp1 ) | 仅支持 argIntervalType 值 SQL_TSI_FRAC_SECOND、SQL_TSI_FRAC_MINUTE、SQL_TSI_FRAC_HOUR 或 SQL_TSI_FRAC_DAY |
表 8.4. 支持的转义杂项函数
函数 | 报告为支持 | 翻译 | 评论 |
---|---|---|---|
database() | 是 | 当前数据库() | 仅在 7.3 及更高版本的服务器上报告为支持。 |
ifnull(arg1, arg2) | 是 | coalesce(arg1, arg2) | |
用户() | 是 | 用户 |