纯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: ?' """ );
上面的查询不包含任何编号的占位符或绑定变量,因为会被搜索的标记包含在注释、字符串文字或带引号的名称中。
反馈
您对此页面有任何反馈吗? 我们很乐意听取您的意见!