我已经看到很多使用Multiset和AS SYS.ODCIVARCHAR2LIST等的答案。我无法理解其背后的逻辑/如何运作。请查看以下示例(实际上取自另一个问题)。请求您解释工作流程/工作以了解multiset。是的,我试着阅读与之相关的文件。
CREATE TABLE table_name ( Id, Column1, Column2 ) AS
SELECT 1, 'A,B,C', 'H' FROM DUAL UNION ALL
SELECT 2, 'D,E', 'J,K' FROM DUAL UNION ALL
SELECT 3, 'F', 'L,M,N' FROM DUAL;
查询:
SELECT t.id,
c1.COLUMN_VALUE AS c1,
c2.COLUMN_VALUE AS c2
FROM table_name t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT REGEXP_SUBSTR( t.Column1, '[^,]+', 1, LEVEL )
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT( t.Column1, '[^,]+' )
) AS SYS.ODCIVARCHAR2LIST
)
) c1
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT REGEXP_SUBSTR( t.Column2, '[^,]+', 1, LEVEL )
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT( t.Column2, '[^,]+' )
) AS SYS.ODCIVARCHAR2LIST
)
) c2
结果::
| ID | C1 | C2 |
|----|----|----|
| 1 | A | H |
| 1 | B | H |
| 1 | C | H |
| 2 | D | J |
| 2 | D | K |
| 2 | E | J |
| 2 | E | K |
| 3 | F | L |
| 3 | F | M |
| 3 | F | N |
提前致谢。
Oracle提供三种不同类型的集合,在其他语言中术语“数组”更为常见。
看看Collections Types,看看差异以及可以使用哪一个。
从简单的事情开始,例如
create type number_table_type as table of number;
您可以通过多种方式使用它们,三个selects
是等效的。他们都选择表emp
并将emp_id
值存储到嵌套表emp_T
中。
create table emp (
emp_id number,
emp_name varchar2(100));
insert into emp values (10, 'Scott');
insert into emp values (20, 'King');
insert into emp values (30, 'Tiger');
declare
emp_T number_table_type:
begin
select cast(collect(emp_id) as number_table_type)
into emp_T
from emp;
select emp_id
bulk collect into emp_T
from emp;
SELECT CAST(MULTISET(SELECT emd_id FROM emp) AS number_table_type)
into emp_T
FROM dual;
emp_T := number_table_type(10,20,30);
for i in 1..3 loop
emp_T.EXTEND;
emp_T(i) := 10*i;
end loop;
end;
换句话说,即将嵌套表转换为“普通”表使用TABLE
函数:
select *
from TABLE(emp_T);
Oracle提供Multiset Operators和Multiset Conditions。它们提供了连接两个数组,使值不同等功能。许多时候我看到开发人员在他们的代码中编写一个LOOP
,其中Mulitset运算符/条件将使用单个命令执行相同的操作。
一旦熟悉了这样的基本数组,您还可以尝试更复杂的结构。然而,根据我的感觉,这种复杂的结构在培训材料和文档中很常见,但很少用于“现实生活”。 Oracle的优势在于存储和操作关系数据,而不是面向对象的数据。
SYS.ODCIVARCHAR2LIST
,et al。只是一些predefined types。实际上,使用它们或创建自己的类型并不重要。
好吧,你应该从最深层次审查这样的代码并向上导航,以便弄清楚发生了什么。
这是基于表格的第一行:正如您所看到的,“regexp”魔术将逗号分隔值(即列)转换为行。
SQL> with test as
2 (select 1, 'A,B,C' column1 from dual)
3 select regexp_substr(t.column1, '[^,]+', 1, level)
4 from test t
5 connect by level <= regexp_count(t.column1, '[^,]+');
REGEXP_SUBSTR(T.COLU
--------------------
A
B
C
SQL>
MULTISET创建这些值的“集合”,而CAST将其“转换”为SYS.ODCIVARCHAR2LIST类型。正如您所看到的,它由SYS拥有,并且就像您创建了自己的类型(使用CREATE TYPE命令)一样,其中包含VARCHAR2值。当类型与此类型“简单”或包含数字的类型(因此您使用SYS.ODCINUMBERLIST)时,您可以使用预定义的类型而不是创建自己的类型。因此,该集合包含A,B和C.
最后,TABLE函数生成一组可以查询的行,就像它是一个“普通”表一样。