复合 SQL(直接插入型)语句
复合 SQL (内联) 语句是在运行时在另一个 SQL 语句中内联的复合 SQL 语句。 复合 SQL (直接插入) 语句具有以原子方式执行的属性; 如果任何语句的执行引起错误,那么将回滚完整语句。
调用
此语句可以嵌入在触发器, SQL 函数或 SQL 方法中,也可以通过使用动态 SQL 语句来发出。 它是可动态准备的可执行语句。
授权
该语句的授权标识所拥有的特权还必须包括调用复合语句中指定的 SQL 语句所需的所有特权。
语法
- 1 A label can only be specified when the statement is in a function, method, or trigger definition.
描述
- label
- 定义代码块的标签。 如果指定了起始标签,那么可以使用它来限定在复合 SQL (内联) 语句中声明的 SQL 变量,也可以在 LEAVE 语句中指定。 如果指定了结束标签,那么它必须与开始标签相同。
- ATOMIC
- ATatomic 指示,如果复合语句中发生错误,那么将回滚复合语句中的所有 SQL 语句,并且不会处理复合语句中的任何剩余 SQL 语句。
如果在模块或 SQL 过程中的 SQL 函数中指定了 ATABLE 关键字,那么会将复合语句作为复合 SQL (已编译) 语句进行处理。
- SQL-statement
- 指定要在复合 SQL (内联) 语句中执行的 SQL 语句。
- SQL-variable-declaration
- 声明复合 SQL (内联) 语句的本地变量。
- SQL-variable-name
- 定义局部变量的名称。 SQL 变量名称将转换为大写。 名称不能与以下名称相同:
- 复合语句中的另一个 SQL 变量
- 参数名称
data-type - 指定变量的数据类型。 在触发器中,方法中或作为独立语句使用的复合 SQL (内联) 语句中不支持 XML 数据类型 (SQLSTATE 429BB)。 在 SQL 函数主体中使用复合 SQL (内联) 语句时,支持 XML 数据类型。
- 缺省值
- 定义 SQL 变量的缺省值。 当执行复合 SQL (直接插入) 语句时,将初始化该变量。 缺省值必须与变量的数据类型兼容。 如果未指定缺省值,那么 SQL 变量的缺省值将初始化为空值。
- NULL
- 指定空值作为 SQL 变量的缺省值。 constant
- 指定常量作为 SQL 变量的缺省值。
- 定义局部变量的名称。 SQL 变量名称将转换为大写。 名称不能与以下名称相同:
- condition-declaration
- 声明条件名称和相应的 SQLSTATE 值。
- condition-name
- 指定条件的名称。 此条件名称在声明它的复合语句中必须是唯一的,不包括嵌套在该复合语句中的复合语句中的任何声明 (SQLSTATE 42734)。 条件名称只能在声明它的复合语句中引用,包括嵌套在该复合语句中的任何复合语句 (SQLSTATE 42737)。
- 对于 SQLSTATE string-constant
- 指定与条件关联的 SQLSTATE。 必须将 string-constant 指定为由单引号括起的五个字符, 并且 SQLSTATE 类 (前两个字符) 不得为 "00"。
注意
- 复合 SQL (内联) 语句编译为一个单一语句。 此语句对于涉及少量控制流逻辑但涉及大量数据流的简短脚本有效。 对于具有嵌套控制流或条件处理需求的较大构造,更好的选择是使用复合 SQL (编译型) 语句或 SQL 过程。
- 在复合语句中调用的过程不得发出 COMMIT 或 ROLLBACK 语句 (SQLSTATE 42985)。
- 表访问限制: 如果过程定义为 READS SQL DATA 或 MODIFIED SQL DATA ,那么该过程中的任何语句都不能访问正在由调用该过程的复合语句修改的表 (SQLSTATE 57053)。 如果该过程定义为 MODIFY SQL DATA ,那么该过程中的任何语句都不能修改正在由调用该过程的复合语句读取或修改的表 (SQLSTATE 57053)。
- XML 赋值: 数据类型为 XML 的参数和变量的赋值是通过 SQL 函数主体中的引用完成的。
通过引用传递 XML 值时,将直接使用任何输入节点树。 这种直接使用会保留所有属性,包括文档顺序、原始节点身份和所有父属性。
- 隔离级别: 如果 选择语句, 全查询或 子查询 指定 隔离子句,那么将忽略该子句并返回警告。
示例
此示例说明如何在数据仓储方案中使用内联 SQL PL 进行数据清理。
本示例介绍了三个表。 TARGET 表包含已清除的数据。 EXCEPT 表存储无法清除的行 (异常) , SOURCE 表包含要清除的原始数据。
名为离散化的简单 SQL 函数用于对数据进行分类和修改。 它返回所有错误数据的空值。 然后,复合 SQL (内联) 语句将清除数据。 它在 FOR-loop 中对 SOURCE 表的所有行进行遍历,并根据离散化函数的结果来决定是将当前行插入到 TARGET 还是 EXCEPT 表中。 使用此技术可以实现更精细的机制 (多阶段清理)。
可以使用 SQL 过程或任何其他过程或应用程序以主语言编写相同的代码。 但是,复合 SQL (内联) 语句具有独特的优势,因为 FOR-loop 不会打开游标,并且单行插入不是真正的单行插入。 事实上,该逻辑实际上是来自共享选择的多表插入。
这是通过将复合 SQL (内联) 语句编译为单个语句来实现的。 与将其主体集成到使用它的查询中,然后在查询上下文中作为整体进行编译和优化的视图类似,数据库优化器同时编译和优化控制和数据流。 因此,将在数据库的运行时环境中执行整个逻辑。 不会将任何数据移动到核心数据库引擎外部,这将对过程执行此操作。
CREATE TABLE TARGET
(PK INTEGER NOT NULL
PRIMARY KEY, C1 INTEGER)这将创建一个名为 TARGET 的表,以包含已清理的数据。
CREATE TABLE EXCEPT
(PK INTEGER NOT NULL
PRIMARY KEY, C1 INTEGER)这将创建一个名为 EXCEPT 的表以包含异常。 CREATE TABLE SOURCE
(PK INTEGER NOT NULL
PRIMARY KEY, C1 INTEGER)这将创建一个名为 SOURCE 的表,用于保存要清除的数据。 CREATE FUNCTION DISCRETIZE(RAW INTEGER) RETURNS INTEGER
RETURN CASE
WHEN RAW < 0 THEN CAST(NULL AS INTEGER)
WHEN RAW > 1000 THEN NULL
ELSE ((RAW / 10) * 10) + 5
END INSERT INTO SOURCE (PK, C1)
VALUES (1, -5),
(2, NULL),
(3, 1200),
(4, 23),
(5, 10),
(6, 876) BEGIN ATOMIC
FOR ROW AS
SELECT PK, C1, DISCRETIZE(C1) AS D FROM SOURCE
DO
IF ROW.D IS NULL THEN
INSERT INTO EXCEPT VALUES(ROW.PK, ROW.C1);
ELSE
INSERT INTO TARGET VALUES(ROW.PK, ROW.D);
END IF;
END FOR;
END
SELECT * FROM EXCEPT ORDER BY 1
PK C1
----------- -----------
1 -5
2 -
3 1200
3 record(s) selected.
SELECT * FROM TARGET ORDER BY 1
PK C1
----------- -----------
4 25
5 15
6 875
3 record(s) selected. DROP FUNCTION DISCRETIZE
DROP TABLE SOURCE
DROP TABLE TARGET
DROP TABLE EXCEPT