了解Oracle中的MultiSet及其优点,重要性

问题描述 投票:1回答:2

我已经看到很多使用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
2个回答
2
投票

Oracle提供三种不同类型的集合,在其他语言中术语“数组”更为常见。

  • 关联数组(或索引表)
  • VARRAY(可变大小数组)
  • 嵌套表

看看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 OperatorsMultiset Conditions。它们提供了连接两个数组,使值不同等功能。许多时候我看到开发人员在他们的代码中编写一个LOOP,其中Mulitset运算符/条件将使用单个命令执行相同的操作。

一旦熟悉了这样的基本数组,您还可以尝试更复杂的结构。然而,根据我的感觉,这种复杂的结构在培训材料和文档中很常见,但很少用于“现实生活”。 Oracle的优势在于存储和操作关系数据,而不是面向对象的数据。

SYS.ODCIVARCHAR2LIST,et al。只是一些predefined types。实际上,使用它们或创建自己的类型并不重要。


1
投票

好吧,你应该从最深层次审查这样的代码并向上导航,以便弄清楚发生了什么。

这是基于表格的第一行:正如您所看到的,“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函数生成一组可以查询的行,就像它是一个“普通”表一样。

© www.soinside.com 2019 - 2024. All rights reserved.