序列引用
使用NEXT VALUE和PREVIOUS VALUE表达式指定序列名称,即可引用序列。
sequence-reference
- NEXT VALUE FOR 序列名
- NEXT VALUE 表达式为指定的序列生成并返回下一个值。 当NEXT VALUE表达式指定序列名称时,将为序列生成一个新值。 但是,如果查询中存在多个NEXT VALUE表达式,且指定了相同的序列名称,则序列值仅针对结果中的每一行递增一次,且所有 NEXT VALUE 结果行返回相同的值。 该表达式并非外部动作的确定性因素,因为它会导致序列值递增。 NEXT VALUE 表达式对外部操作不是确定性的,因为它会导致序列值递增。
当序列的下一个值生成时,如果超出了逻辑序列的递增序列的最大值或递减序列的最小值,并且 NO CYCLE 选项生效时,则会发生错误。 为了避免这种错误,要么修改序列属性以扩展值范围,要么启用序列循环,要么删除并重新创建具有更大值范围的序列。
NEXT VALUE 表达式结果的数据类型和长度属性与指定序列相同。 结果不能为空。
- PREVIOUS VALUE FOR 序列名
- 对于当前应用程序进程中的先前语句,PREVIOUS VALUE 表达式为指定序列返回最新生成的值。 通过使用PREVIOUS VALUE表达式来指定序列的名称,可以反复引用该值。 在单个语句中,可以有多个PREVIOUS VALUE表达式指定相同的序列名称,它们都返回相同的值。
只有在当前应用程序进程中引用了指定相同序列名称的下一个值表达式时,才能使用上一个值表达式。
PREVIOUS VALUE 表达式结果的数据类型和长度属性与指定序列相同。 结果不能为空。
- 序列名
- 标识要引用的序列。 名称与隐式或显式模式名称的组合必须标识当前服务器上存在的序列。 序列名不能是 Db2 为标识列生成的内部序列对象的名称。
有关如何确定无限定序列名称的隐式限定符的信息,请参阅无限定对象名称解析。
注意
- 授权:
- 如果语句中引用了序列,则该语句的授权ID所拥有的权限必须至少包含以下一项:
- 对于声明中确定的顺序:
- 序列上的 USAGE 特权
- 序列的所有权
SYSADM 或 DATAACCESS 权限
- 对于声明中确定的顺序:
- 通过NEXT VALUE创造价值:
- 当为序列生成值时,该值被使用,下次请求值时,将会生成新的值。 即使包含 NEXT VALUE 表达式的语句失败或回滚时,情况也是如此。
- 下一个值和上一个值的范围:
- PREVIOUS VALUE 的值无法直接设置,并且是执行序列的 NEXT VALUE 表达式的结果。 上一个值(PREVIOUS VALUE)的值将一直保持到当前会话中序列的下一个值生成、序列被放弃或更改或应用程序会话结束为止。
如果由于某种形式的线程重用、重新登录或连接池生效,在本地或远程应用程序的提交或回滚后, Db2 应用程序线程或服务器线程被分配给其他用户或 Db2 连接,则序列的值不能在提交或回滚后持续存在。 例如, CICS® -Db2 应用程序、客户端应用程序或中间件产品可能会出现这种情况,它们保存会话状态,然后恢复会话状态以供后续处理,因为它们无法恢复序列的下一个或上一个值。 在这些情况下,序列值的可用性只能持续到交易结束。 此类情况可能发生在以下应用中:
- 发出EXEC CICS SYNCPOINT命令
- 使用XA协议
- 使用连接池
- 使用连接集中器
- 使用Sysplex工作负载均衡
- 连接到使用DDF非活动线程的 z/OS® 服务器
当需要在交易边界内为受线程重用、重新登录或连接池约束的本地或分布式应用程序保存与NEXT VALUE或PREVIOUS VALUE表达式相关的值时,请采取以下措施之一,以防止本地或服务器线程被重新登录、被其他用户重用或进入池:
- 将至少一个光标定义为“保留”,并保留为“打开”状态。
- 指定绑定选项 KEEPDYNAMIC(YES)。
- 作为唯一的关键值使用:
- 通过对第一行使用 NEXT VALUE 表达式引用序号(这会生成序列值),而对其他行使用 PREVIOUS VALUE 表达式引用序号(PREVIOUS VALUE 的实例引用当前会话中最近生成的序列值),相同序号可以在两个单独的表中用作唯一键值,如以下示例所示:
INSERT INTO ORDER (ORDERNO, CUSTNO) VALUES (NEXT VALUE FOR ORDER_SEQ, 123456); INSERT INTO LINE_ITEM (ORDERNO, PARTNO, QUANTITY) VALUES (PREVIOUS VALUE FOR ORDER_SEQ, 987654, 1); - 允许使用“下一个值”和“上一个值”:
- NEXT VALUE和PREVIOUS VALUE表达式可以在以下位置指定:
- 在SELECT语句或不含 DISTINCT 关键字、 GROUP BY 子句、 ORDER BY 子句或集合运算符。
- INSERT语句中,包括多行INSERT语句,其中包含多个 VALUES INSERT语句的子句,包括具有多个子句的多行INSERT语句 VALUES 子句和MERGE语句的插入操作,其中MERGE语句可以为每个 VALUES 子句。
- 在 INSERT 语句的全查询的 select 子句中。
- UPDATE语句的搜索或定位子句中,包括MERGE语句的更新操作,尽管NEXT VALUE不能在表达式的全选(fullselect)的select子句中指定,但在 SET UPDATE语句的搜索或定位子句中,包括MERGE语句的更新操作,尽管NEXT VALUE不能在 SET 子句中。更新操作(UPDATE或MERGE语句)的子句中,但NEXT VALUE表达式只能用于 SET 更新操作(UPDATE或MERGE语句)的子句中,但NEXT VALUE表达式只能在 SET 子句中,前提是它不在表达式的全选(fullselect) 的select子句中。 例如,支持以下序列引用用法:
不支持以下序列引用用法:UPDATE T SET C1 = (SELECT PREVIOUS VALUE FOR S1 FROM T); UPDATE T SET C1 = PREVIOUS VALUE FOR S1; UPDATE T SET C1 = NEXT VALUE FOR S1;UPDATE T SET C1 = (SELECT NEXT VALUE FOR S1 FROM T); SET :C2 = (SELECT NEXT VALUE FOR S1 FROM T); - 在 SET host-variable 或 assignment-statement 中,除了在表达式的 fullselect 的 select-clause 中。序列引用支持以下用途:
不支持以下序列引用用法:SET ORDERNUM = NEXT VALUE FOR INVOICE; SET ORDERNUM = PREVIOUS VALUE FOR INVOICE;SET X = (SELECT NEXT VALUE FOR S1 FROM T); SET X = (SELECT PREVIOUS VALUE FOR S1 FROM T); - 在 VALUES 或 VALUES INTO 语句中,但不能在表达式的全选子句的select子句中。
- 在SQL程序的CREATE或ALTER PROCEDURE语句的 SQL常规主体中。
- 在SQL函数的CREATE FUNCTION语句的RETURN语句中。
- 在CREATE TRIGGER语句的 SQL触发器主体中(不允许使用PREVIOUS VALUE)。
- 在嵌套应用中使用“前一个值”:
- 上一个值被定义为在应用程序会话中具有线性范围。 因此,在进入嵌套函数、过程或触发器时,嵌套应用程序会继承序列最近生成的值。 也就是说,在嵌套应用程序中调用PREVIOUS VALUE(前一个值)会反映在进入嵌套应用程序之前在调用环境中完成的序列活动。 此外,在从函数、过程或触发器返回时,调用应用程序会受到下层应用程序中任何序列活动的影响。 也就是说,在嵌套应用程序返回后,调用应用程序中的PREVIOUS VALUE会反映在较低层应用程序中发生的任何序列活动。
- 使用“下一个值”和“上一个值”的限制:
- 无法指定NEXT VALUE和PREVIOUS VALUE表达式的地方包括:
- 全部外连接的连接条件
- CREATE TABLE 或 ALTER TABLE 语句中某列的 DEFAULT 值
- 在CREATE TABLE或ALTER TABLE语句中定义查询表
- 检查约束的条件
- LOAD的输入值说明
- CREATE VIEW 语句
- 包含非原子数据更改语句的子选择的 SELECT 列表
- 在OLAP规范中使用的ORDER BY子句
此外,NEXT VALUE表达式不能在以下位置使用:
- CASE 表达式
- 聚合函数的参数列表
- 在明确允许的上下文之外进行子查询
- SELECT语句,其中外部SELECT包含DISTINCT运算符或GROUP BY子句
- SELECT语句,其中外层SELECT与另一SELECT语句使用集合运算符组合在一起
- 连接条件之一
- 嵌套表表达式
- 表格函数的参数列表
- UPDATE、DELETE或MERGE语句的SET子句中表达式的全选子句。
- 最外层的SELECT语句的WHERE子句或DELETE、UPDATE或MERGE语句
- 最外层的SELECT语句中的ORDER BY子句
包含 OFFSET 子句的全选的选择列表
- SQL程序中的IF、WHILE、DO UNTIL或 CASE 语句
- 使用带有光标的序列表达式:
- 通常情况下,一个
SELECT NEXT VALUE FOR ORDER_SEQ FROM T1会生成一个结果表,其中包含从序列ORDER_SEQ中生成的值,数量与从 T1 中检索的行数相同。 对游标的 select 语句中的 NEXT VALUE 表达式的引用将引用为结果表行生成的值。 每次检索一行时,都会为NEXT VALUE表达式生成一个序列值。如果在灾难恢复数据环境中的客户端进行阻塞,序列值可能会在 Db2 服务器上生成,然后才处理应用程序的FETCH语句。 如果客户端应用程序没有明确获取从数据库中检索到的所有行,那么应用程序将永远看不到序列中生成但未获取的所有值(与未获取的行一样多)。 这些生成但未取用的值可能会导致序列中出现空值。 如果必须防止序列中出现这种空隙,请执行以下操作:
- 仅在不受光标控制且客户端的块获取对其没有影响的情况下使用NEXT VALUE。
- 如果您必须在游标定义的 SELECT 语句中使用 NEXT VALUE,请权衡防止出现空值与执行以下操作对性能和其他方面造成的影响:
- 在SELECT语句中使用FETCH FOR 1 ROW ONLY子句。
- 尝试通过 “块提取” 中记录的其他方法阻止块提取。
- 使用带有光标的“上一个值”表达式:
- 游标的SELECT语句中引用PREVIOUS VALUE表达式的计算在OPEN时进行。 换句话说,在游标的 SELECT 语句中引用 PREVIOUS VALUE 表达式,是指在游标打开之前,此应用程序过程为指定的序列生成的最后一个值,并且在 OPEN 时间评估后,游标的 SELECT 语句中 PREVIOUS VALUE 返回的值不会从 FETCH 更改为 FETCH,即使使用游标的 SELECT 语句调用 NEXT VALUE。 光标关闭后,PREVIOUS VALUE(上一个值)的值将是应用程序进程生成的最后一个NEXT VALUE(下一个值)。
如果光标打开时在光标的 SELECT 语句中使用 PREVIOUS VALUE,则 PREVIOUS VALUE 的值将为光标打开前为序列生成的最后一个 NEXT VALUE。 光标关闭后,上一个值的值将是应用程序进程生成的最后一个下一个值。
- 语法替代和同义词:
- 为了兼容性,关键词NEXTVAL和PREVVAL可以分别作为NEXT VALUE和PREVIOUS VALUE的同义词。
sequence-name.NEXTVAL可以指定为 , 可以指定为。 NEXT VALUE FOR 序列名sequence-name.CURRVALPREVIOUS VALUE FOR 序列名
示例
CREATE SEQUENCE ORDER_SEQ START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO CYCLE
CACHE 24 以下示例说明了如何使用NEXT VALUE表达式生成ORDER_SEQ序列号: INSERT INTO ORDER (ORDERNO, CUSTNO)
VALUES (NEXT VALUE FOR ORDER_SEQ, 123456);
UPDATE ORDER SET ORDERNO = NEXT VALUE FOR ORDER_SEQ
WHERE CUSTNO = 123456;
VALUES NEXT VALUE FOR ORDER_SEQ INTO :HV_SEQ; 