问题
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