在PL/SQL中处理关联数组或嵌套表等集合类型时,您需要查询元素、增删改查或进行集合间的比较与运算。为了简化这些操作,PolarDB PostgreSQL版(兼容Oracle)提供了一套丰富的内置集合方法和运算符。这些工具使您能够像操作标准数据结构一样,直观、高效地管理集合数据,从而增强代码的可读性和维护性。
功能简介
集合操作是针对PL/SQL集合类型(如关联数组、嵌套表)的一系列内置方法和运算符。它们提供了查询、修改、管理和比较集合的功能,语法简洁直观。用于对两个兼容类型的集合进行比较或运算,例如判断子集关系(SUBMULTISET
)或计算并集(MULTISET UNION
)。
collection_variable.method_name[(parameters)]
适用范围
您的PolarDB PostgreSQL版(兼容Oracle)集群的修订版本需为2.0.14.17.36.0及以上
操作说明
多重集合操作方法
IS_EMPTY
检查一个集合是否为空。
collection IS EMPTY
返回值
BOOLEAN
类型
TRUE
:如果集合为空或未初始化。FALSE
:如果集合包含至少一个元素。
特点
功能上等价于
collection.COUNT = 0
,但性能更优。对
NULL
集合返回TRUE
。
IS_NOT_EMPTY
检查一个集合是否非空。
collection IS NOT EMPTY
返回值
BOOLEAN
类型
TRUE
:如果集合包含至少一个元素。FALSE
:如果集合为空或未初始化。
特点
等价于
collection.COUNT > 0
。是
IS EMPTY
的逻辑反操作。
IS_IN
检查指定的值是否存在于集合中。
element_value IN (collection)
参数说明
element_value
:要查找的值。
返回值
BOOLEAN
类型
TRUE
:如果值存在于集合中。FALSE
:如果值不存在于集合中。
特点
支持
NULL
值比较。对于嵌套表和VARRAY特别有用。
时间复杂度为 O(n)。
IS_NOT_IN
检查指定的值是否不存在于集合中。
element_value NOT IN (collection)
参数说明
element_value
:要查找的值。
返回值
BOOLEAN
类型
TRUE
:如果值不存在于集合中。FALSE
:如果值存在于集合中。
特点
是
IN
运算符的逻辑反操作。处理
NULL
值时需要特别注意。
IS_SUBMULTISET
检查第一个集合是否为第二个集合的子多重集合。
collection1 SUBMULTISET collection2
返回值
BOOLEAN
类型
TRUE
:如果collection1
是collection2
的子集。FALSE
:如果collection1
不是collection2
的子集。
特点
判断时会考虑元素的重复次数。例如,
{1}
是{1, 2}
的子集,但{1, 1}
不是。空集合是任何集合的子集。
任何集合都是其自身的子集。
IS_NOT_SUBMULTISET
检查第一个集合是否不是第二个集合的子多重集合。
collection1 NOT SUBMULTISET collection2
返回值
BOOLEAN
类型
TRUE
:如果collection1
不是collection2
的子集。FALSE
:如果collection1
是collection2
的子集。
IS_MEMBER
检查指定元素是否存在于集合中。
element_value IN (collection)
参数说明
element_value
:要检查的元素值。
返回值
BOOLEAN
类型
TRUE
:如果元素是集合的成员。FALSE
:如果元素不是集合的成员。
特点
功能类似于
IS_IN
运算符,但语法不同。支持复杂数据类型(如
RECORD
类型)的比较。
IS_NOT_MEMBER
检查指定元素是否不存在于集合中。
element_value NOT MEMBER collection
参数说明
element_value
:要检查的元素值。
返回值
BOOLEAN
类型
TRUE
:如果元素不是集合的成员。FALSE
:如果元素是集合的成员。
IS_SET
检查一个集合是否不包含重复元素(即符合数学意义上的集合定义)。
collection IS A SET
返回值
BOOLEAN
类型
TRUE
:如果集合中没有重复元素。FALSE
:如果集合中存在重复元素。
特点
对于关联数组,此方法总是返回
TRUE
,因为它们的键是唯一的。对于嵌套表需要检查值的唯一性。
IS_NOT_SET
检查一个集合是否包含重复元素。
collection IS NOT A SET
返回值
BOOLEAN
类型
TRUE
:如果集合中存在重复元素。FALSE
:如果集合中没有重复元素。
多重集合运算符
MULTISET_UNION
计算两个集合的并集,并返回一个新的集合。
collection1 MULTISET UNION [ALL | DISTINCT] collection2
变体
MULTISET UNION
:默认行为。返回的结果包含collection1
和collection2
中的所有元素。如果一个元素在两个集合中都存在,它会在结果中出现两次。MULTISET UNION ALL
:等同于MULTISET UNION
。MULTISET UNION DISTINCT
:返回的结果包含collection1
和collection2
中的所有元素,但会去除重复项,每个元素只出现一次。
返回值
一个新的集合,包含两个集合的所有元素,且其元素类型与输入集合相同。
MULTISET_INTERSECT
计算两个集合的交集,并返回一个新的集合。
collection1 MULTISET INTERSECT [ALL | DISTINCT] collection2
变体
MULTISET INTERSECT
:默认行为。返回两个集合共有的元素。如果一个元素在collection1
中出现n
次,在collection2
中出现m
次,那么它在结果中将出现MIN(n, m)
次。MULTISET INTERSECT ALL
:等同于MULTISET INTERSECT
。MULTISET INTERSECT DISTINCT
:返回两个集合共有的元素,但会去除重复项,每个元素只出现一次。
返回值
一个新的集合,包含两个集合的共同元素。
MULTISET_EXCEPT
计算两个集合的差集(属于collection1
但不属于collection2
的元素),并返回一个新的集合。
collection1 MULTISET EXCEPT [ALL | DISTINCT] collection2
变体
MULTISET EXCEPT
:默认行为。从collection1
中移除在collection2
中也存在的元素。如果一个元素在collection1
中出现n
次,在collection2
中出现m
次,那么它在结果中将出现MAX(n - m, 0)
次。MULTISET EXCEPT ALL
:等同于MULTISET EXCEPT
。MULTISET EXCEPT DISTINCT
:在计算差集前,先对collection1
和collection2
进行去重,然后返回仅存在于去重后collection1
中的元素。
返回值
一个新的集合,包含第一个集合中不在第二个集合中的元素。
使用示例
以下示例展示了集合方法和运算符的实际应用。
示例1:使用集合方法管理关联数组
本示例演示了如何使用COUNT
、FIRST
、LAST
、EXISTS
和DELETE
等方法来管理一个关联数组。
DECLARE
TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);
aarray aarray_type;
BEGIN
-- 初始化数组
aarray('apple') := 10;
aarray('banana') := 20;
aarray('cherry') := 30;
-- 1. 查询集合状态
RAISE NOTICE '元素数量 (COUNT): %', aarray.COUNT;
RAISE NOTICE '第一个键 (FIRST): %', aarray.FIRST;
RAISE NOTICE '最后一个键 (LAST): %', aarray.LAST;
-- 2. 检查元素是否存在
RAISE NOTICE '键 "banana" 是否存在 (EXISTS): %', aarray.EXISTS('banana');
RAISE NOTICE '键 "date" 是否存在 (EXISTS): %', aarray.EXISTS('date');
-- 3. 删除元素
RAISE NOTICE '删除前: %', aarray;
aarray.DELETE('banana');
RAISE NOTICE '删除 "banana" 后: %', aarray;
-- 4. 清空集合
aarray.DELETE;
RAISE NOTICE '全部删除后,元素数量: %', aarray.COUNT;
END;
/
预期输出:
NOTICE: 元素数量 (COUNT): 3
NOTICE: 第一个键 (FIRST): apple
NOTICE: 最后一个键 (LAST): cherry
NOTICE: 键 "banana" 是否存在 (EXISTS): t
NOTICE: 键 "date" 是否存在 (EXISTS): f
NOTICE: 删除前: (apple=>10,banana=>20,cherry=>30)
NOTICE: 删除 "banana" 后: (apple=>10,cherry=>30)
NOTICE: 全部删除后,元素数量: 0
示例2:使用NEXT
和PRIOR
遍历集合
本示例展示了如何使用FIRST
和NEXT
组合来安全地遍历关联数组的所有元素。
DECLARE
TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);
aarray aarray_type;
v_key VARCHAR(10);
BEGIN
aarray('alpha') := 1;
aarray('beta') := 2;
aarray('gamma') := 3;
-- 使用循环遍历
v_key := aarray.FIRST;
WHILE v_key IS NOT NULL LOOP
RAISE NOTICE '键: %, 值: %', v_key, aarray(v_key);
v_key := aarray.NEXT(v_key);
END LOOP;
-- 查询前一个键
RAISE NOTICE '键 "gamma" 的前一个键 (PRIOR): %', aarray.PRIOR('gamma');
END;
/
预期输出(注意:关联数组内部会按键排序):
NOTICE: 键: alpha, 值: 1
NOTICE: 键: beta, 值: 2
NOTICE: 键: gamma, 值: 3
NOTICE: 键 "gamma" 的前一个键 (PRIOR): beta
示例3:使用多重集合运算符
本示例演示了如何使用MULTISET UNION
、MULTISET INTERSECT
和MULTISET EXCEPT
对两个嵌套表进行集合运算。
DECLARE
TYPE ntable_type IS TABLE OF INT;
ntable1 ntable_type := ntable_type(1, 2, 2, 3);
ntable2 ntable_type := ntable_type(2, 3, 4, 4);
result_table ntable_type;
BEGIN
-- 1. 并集 (UNION)
result_table := ntable1 MULTISET UNION ntable2;
RAISE NOTICE '并集 (UNION): %', result_table;
-- 2. 交集 (INTERSECT)
result_table := ntable1 MULTISET INTERSECT ntable2;
RAISE NOTICE '交集 (INTERSECT): %', result_table;
-- 3. 差集 (EXCEPT)
result_table := ntable1 MULTISET EXCEPT ntable2;
RAISE NOTICE '差集 (EXCEPT): %', result_table;
END;
/
预期输出:
NOTICE: 并集 (UNION): {1,2,2,3,2,3,4,4}
NOTICE: 交集 (INTERSECT): {2,3}
NOTICE: 差集 (EXCEPT): {1,2}
示例4:使用EXTEND
管理嵌套表
本示例展示了如何使用EXTEND
方法向一个嵌套表中添加新元素。
DECLARE
TYPE ntable_type IS TABLE OF INT;
ntable ntable_type := ntable_type(10, 20);
BEGIN
RAISE NOTICE '原始嵌套表: %', ntable;
-- 扩展2个NULL元素
ntable.EXTEND(2);
RAISE NOTICE '扩展2个元素后: %', ntable;
-- 为新元素赋值
ntable(3) := 30;
ntable(4) := 40;
RAISE NOTICE '赋值后: %', ntable;
END;
/
预期输出:
NOTICE: 原始嵌套表: {10,20}
NOTICE: 扩展2个元素后: {10,20,NULL,NULL}
NOTICE: 赋值后: {10,20,30,40}