变量
适用于 ❌ 开源版 ✅ Express 版 ✅ 专业版 ✅ 企业版
在命令式语言中,局部变量是临时存储数据以供进一步处理的重要方式。 所有过程语言都有声明、赋值和引用此类局部变量的方法。
声明
在 jOOQ 中,可以使用 DSL.var()
创建局部变量表达式(不要与 DSL.val(T)
混淆,后者会创建绑定值!)
Variable<Integer> i = var("i", INTEGER);
这个变量本身没有任何作用。 但与 jOOQ 中的许多事物一样,它必须首先在实际 jOOQ 表达式之外声明,才能在 jOOQ 表达式中使用。
我们现在可以在声明语句中引用该变量,如下所示
-- MySQL syntax DECLARE i INTEGER;
// All dialects declare(i)
请注意,在不同的方言中,有很多不同的方法可以声明局部变量。 有
Oracle PL/SQL、PostgreSQL pgplsql 风格
在这些语言中,DECLARE
语句实际上不是可以在任何地方使用的独立语句。 它是 过程块的一部分,位于 BEGIN .. END
之前
-- PL/SQL syntax DECLARE i INT; BEGIN NULL; END;
使用 jOOQ 时,您可以安全地忽略此事实,并在这些方言中添加 DECLARE
语句。 jOOQ 会将额外的 BEGIN .. END
块添加到您的周围块中,以确保整个块在语法和语义上都是正确的。
T-SQL、MySQL 风格
在这些语言中,DECLARE
语句确实是可以随时使用的独立语句。 就像在 Java 语言中一样,变量可以在任何位置声明,并且只能在词法上“进一步向下”使用。 暂时忽略 T-SQL 对作用域的 JavaScript 式理解。
-- T-SQL syntax DECLARE @i INTEGER;
请注意,您可以安全地忽略某些方言(例如 T-SQL)中需要的 @
符号。 jOOQ 会为您生成它。
赋值
局部变量需要一种方式来为其赋值。 可以在 org.jooq.Variable
或 org.jooq.Declaration
上直接进行赋值。 例如
-- T-SQL syntax DECLARE @i INTEGER = 1;
// All dialects declare(i).set(1)
或者,您可以拆分声明和赋值,或者为变量重新分配新值
-- T-SQL syntax DECLARE @i INTEGER; SET @i = 1; SET @i = 2;
// All dialects declare(i), i.set(1), i.set(2)
某些方言还支持在赋值表达式中使用子查询,以及在其过程语言中使用其他表达式。 例如
-- T-SQL syntax SET @i = (SELECT MAX(col) FROM t);
// All dialects i.set(select(max(T.COL)).from(T))
以上等同于此
-- PL/SQL syntax SELECT MAX(col) INTO i FROM t;
// All dialects select(max(T.COL)).into(i).from(T)
行赋值
某些方言支持变量的行赋值,其他语言称之为“解构”。 当从查询中分配多个值时,这尤其有用
-- HSQLDB syntax SET (i, j) = (SELECT MIN(col), MAX(col) FROM t);
// All dialects row(i, j).set(select(min(T.COL), max(T.COL)).from(T))
以上等同于此
-- PL/SQL syntax SELECT MIN(col), MAX(col) INTO i, j FROM t;
// All dialects select(min(T.COL), max(T.COL)).into(i, j).from(T)
引用
显然,一旦我们为局部变量分配了值,我们也希望在任意表达式和查询中引用它。
为此,org.jooq.Variable
扩展了 org.jooq.Field
,因此,它可以在任何其他 列表达式可以使用的地方使用。 在过程语言中,一个简单的例子是递增一个局部变量
-- PL/SQL syntax i := i + 1;
// All dialects i.set(i.plus(1))
或者在一个更完整的例子中,在 SQL 语句中使用它
-- PL/SQL syntax DECLARE i INT; BEGIN i := 1; INSERT INTO t (col) VALUES (i); END;
// All dialects Variable<Integer> i = var("i", INTEGER); create.begin( declare(i), i.set(1), insertInto(T).columns(T.COL).values(i) ).execute();
方言支持
此示例使用 jOOQ
begin(declare(i), i.set(1))
翻译成以下特定方言的表达式
Aurora Postgres、Postgres、YugabyteDB
DO $$ DECLARE i int; BEGIN i := 1; END; $$
BigQuery
BEGIN DECLARE i int64; SET i = 1; END;
CockroachDB
DO $$ DECLARE i int4; BEGIN i := 1; END; $$
DB2
BEGIN DECLARE i integer; SET i = 1; END
Exasol
BEGIN i int; i := 1; END;
Firebird
EXECUTE BLOCK AS DECLARE i integer; BEGIN :i = 1; END
H2
CREATE ALIAS block_1752830478990_1732120 AS $$ void x(Connection c) throws SQLException { Integer i = null; i = 1; } $$; CALL block_1752830478990_1732120(); DROP ALIAS block_1752830478990_1732120;
Hana
DO BEGIN DECLARE i integer; i = 1; END;
HSQLDB
BEGIN ATOMIC DECLARE i int; SET i = 1; END;
Informix
BEGIN DEFINE i integer; LET i = 1; END;
MariaDB
BEGIN NOT ATOMIC DECLARE i int; SET i = 1; END;
MySQL
CREATE PROCEDURE block_1752830487554_4679654() MODIFIES SQL DATA BEGIN DECLARE i int; SET i = 1; END; CALL block_1752830487554_4679654(); DROP PROCEDURE block_1752830487554_4679654;
Oracle
DECLARE i number(10); BEGIN i := 1; END;
Snowflake
BEGIN LET i number(10); i := 1; END;
SQLDataWarehouse, SQLServer
BEGIN DECLARE @i int; SET @i = 1; END;
Trino
BEGIN DECLARE i int; SET i = 1; END
ASE, Access, Aurora MySQL, ClickHouse, Databricks, Derby, DuckDB, MemSQL, Redshift, SQLite, Sybase, Teradata, Vertica
/* UNSUPPORTED */
使用 jOOQ 3.21 生成。早期 jOOQ 版本的支持可能有所不同。 在我们的网站上翻译您自己的 SQL
反馈
您对此页面有任何反馈吗? 我们很乐意听到!