Delete element from Varray Oracle

蓝咒 提交于 2020-06-28 06:21:11

问题


I have created Varray as :

CREATE TYPE mytype IS VARRAY (4) OF VARCHAR2(50); /

Then Created table as :

CREATE TABLE tbl( a NUMBER, b VARCHAR2(30), c mytype); /

Inserted values as :

INSERT INTO tbl(a, b, c) VALUES (1,'Eng', mytype('qq','rr', 'yy', 'ttt'));

How I can delete only the element 'ttt'?? Thanks !!


回答1:


The Oracle documentation states that this is not possible directly via SQL:

5.3.2.3 Performing Atomical Changes on VARRAYs and Nested Tables

You can make atomical changes to nested tables and VARRAYs.

Note: While nested tables can also be changed in a piecewise fashions, varrays cannot.

Example 5-25 shows how you can manipulate SQL varray object types with PL/SQL statements. In this example, varrays are transferred between PL/SQL variables and SQL tables. You can insert table rows containing collections, update a row to replace its collection, and select collections into PL/SQL variables.

However, you cannot update or delete individual varray elements directly with SQL; you have to select the varray from the table, change it in PL/SQL, then update the table to include the new varray. You can also do this with nested tables, but nested tables have the option of doing piecewise updates and deletes.

Furthermore, you can also not just delete a random given element within a VARRAY as they are dense arrays (no gaps within them). Although it is possible in your example to just remove the very last entry from the VARRAY using the TRIM function, therefore removing ttt, you can't just go ahead and for example delete rr without some clever PL/SQL to create a new VARRAY that has that entry not within it. Here is the clever 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;
/

Which results in all of this:

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')


来源:https://stackoverflow.com/questions/49846221/delete-element-from-varray-oracle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!