纯SQL模板语言
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
正如上一章中记录的那样,plain SQL API 支持一种字符串模板迷你语言,允许从较小的部分构造复杂的 SQL 字符串内容。下面可以看到一个简单的例子,例如,当寻找对 PostgreSQL 的各种供应商特定运算符类型的支持时
ARRAY[1,4,3] && ARRAY[2,1]
condition("{0} && {1}", array1, array2);
这样的 plain SQL 模板总是由两件事组成
- 包含
{number}样式占位符的 SQL 字符串片段。 - 一组
org.jooq.QueryPart参数,这些参数预计会嵌入到 SQL 字符串中
SQL 字符串可以通过基于 0 的索引引用参数。每个参数可以被引用多次。例如,SQLite 对 REPEAT(string, count) 函数的模拟可能如下所示
Field<Integer> count = val(3);
Field<String> string = val("abc");
field("replace(substr(quote(zeroblob(({0} + 1) / 2)), 3, {0}), '0', {1})", String.class, count, string);
// ^ ^ ^ ^^^^^ ^^^^^^
// | | | | |
// argument "count" is repeated twice: \------------------+----------|---------------------/ |
// argument "string" is used only once: \-----------------------------/
为了方便起见,还有一个 DSL.list(QueryPart...) API,它允许将逗号分隔的查询部分列表包装在单个模板参数中
Field<String> a = val("a");
Field<String> b = val("b");
Field<String> c = val("c");
// These two produce the same result:
condition("my_column IN ({0}, {1}, {2})", a, b, c); // Using distinct template arguments
condition("my_column IN ({0})", list(a, b, c)); // Using a single template argument
解析规则
在处理这些 plain SQL 模板时,会运行一个迷你解析器来处理以下事项
- 像
'abc'或$$abc$$这样的字符串文字 - 像
"name",`name`, 或[name]这样的带引号的名称 - 像
/* block */或-- line这样的注释 - 像
{d '2000-01-01'}这样的 JDBC 转义序列 - 索引 (
?) 或命名 (:identifier) 绑定变量占位符
以上内容会被模板引擎识别,并且在替换编号的占位符和/或绑定变量时,其中的内容会被忽略。例如
query(
"""
SELECT /* In a comment, this is not a placeholder: {0}. And this is not a bind variable: ? */ title AS `title {1} ?`
-- Another comment without placeholders: {2} nor bind variables: ?
FROM book
WHERE title = 'In a string literal, this is not a placeholder: {3}. And this is not a bind variable: ?'
"""
);
上面的查询不包含任何编号的占位符或绑定变量,因为会被搜索的标记包含在注释、字符串文字或带引号的名称中。
反馈
您对此页面有任何反馈吗? 我们很乐意听取您的意见!