【问题标题】:Delete element from Varray Oracle从 Varray Oracle 中删除元素
【发布时间】:2018-04-15 20:01:08
【问题描述】:

我已将 Varray 创建为:

创建类型 mytype 是 VARRAY (4) OF VARCHAR2(50); /

然后创建表为:

创建表 tbl( 一个号码, b VARCHAR2(30), c我的类型); /

插入值:

插入到 tbl(a, b, c) 值(1,'Eng', mytype('qq','rr', 'yy', 'ttt'));

我怎样才能只删除元素'ttt'?谢谢!!

【问题讨论】:

    标签: oracle collections varray


    【解决方案1】:

    Oracle 文档指出,这是无法直接通过 SQL 实现的:

    5.3.2.3 Performing Atomical Changes on VARRAYs and Nested Tables

    您可以对嵌套表和 VARRAY 进行原子更改。

    注意:虽然嵌套表也可以分段更改,但 varray 不能。

    示例 5-25 展示了如何使用 PL/SQL 语句操作 SQL 可变数组对象类型。在本例中,可变数组在 PL/SQL 变量和 SQL 表之间传输。您可以插入包含集合的表行、更新行以替换其集合,以及将集合选择到 PL/SQL 变量中。

    但是,您不能直接使用 SQL 更新或删除单个 varray 元素;您必须从表中选择 varray,在 PL/SQL 中更改它,然后更新表以包含新的 varray。您也可以对嵌套表执行此操作,但嵌套表可以选择进行分段更新和删除。

    此外,您还可以不只是删除 VARRAY 中的随机给定元素,因为它们是密集数组(其中没有间隙)。尽管在您的示例中可以使用TRIM 函数从VARRAY 中删除最后一个条目,因此删除ttt,但您不能直接删除rr,而不需要一些聪明的PL /SQL 创建一个新的VARRAY,其中不包含该条目。这是聪明的 PL/SQL:

    CREATE OR REPLACE FUNCTION delete_entry(p_record IN mytype, p_val IN VARCHAR2)
    RETURN mytype
    IS
       v_ret  mytype := mytype();
    BEGIN
       FOR n IN p_record.FIRST..p_record.LAST LOOP
          IF p_record(n) != p_val THEN
            v_ret.EXTEND;
            v_ret(v_ret.LAST) := p_record(n);
          END IF;
       END LOOP;
       RETURN v_ret;
    END;
    /
    

    这导致了这一切:

    SQL> CREATE TYPE mytype IS VARRAY(4) OF VARCHAR2(50);
      2  /
    
    Type created.
    
    SQL> CREATE TABLE tbl( a NUMBER, b VARCHAR2(30), c mytype);
    
    Table created.
    
    SQL> INSERT INTO tbl(a, b, c)
      VALUES (1,'Eng', mytype('qq','rr', 'yy', 'ttt'));
      2
    1 row created.
    
    SQL> select * from tbl;
    
         A B
    ---------- ------------------------------
    C
    --------------------------------------------------------------------------------
         1 Eng
    MYTYPE('qq', 'rr', 'yy', 'ttt')
    
    
    SQL> CREATE OR REPLACE FUNCTION delete_entry(p_record IN mytype, p_val IN VARCHAR2)
    RETURN mytype
    IS
       v_ret  mytype := mytype();
    BEGIN
       FOR n IN p_record.FIRST..p_record.LAST LOOP
          IF p_record(n) != p_val THEN
            v_ret.EXTEND;
            v_ret(v_ret.LAST) := p_record(n);
          END IF;
       END LOOP;
       RETURN v_ret;
    END;
    /
      2    3    4    5    6    7    8    9   10   11   12   13   14
    Function created.
    
    SQL> UPDATE tbl SET c = delete_entry(c, 'ttt');
    
    1 row updated.
    
    SQL> select * from tbl;
    
         A B
    ---------- ------------------------------
    C
    --------------------------------------------------------------------------------
         1 Eng
    MYTYPE('qq', 'rr', 'yy')
    

    【讨论】:

      猜你喜欢
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 2018-06-14
      • 1970-01-01
      • 2013-02-14
      • 2018-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多