如何在 sql (oracle) 中操作 VARRAYS?
How to manipulate VARRAYS in sql (oracle)?
假设我正在使用一个 table 人,并且这些人可能有多个姓氏,因此该属性应该是一个包含 3 个元素的数组(例如,这与存储姓氏的位置无关),这里是一个简单的 sql 用于创建姓氏类型,table 人并在 oracle 的 sql developper (11G XE):
中添加示例行
create type lastn as varray(3) of varchar2(10);
CREATE TABLE person
(
ID NUMBER NOT NULL
, last_name lastn
, CONSTRAINT EXEMPLE_PK PRIMARY KEY
(
ID
)
ENABLE
);
insert into person values(1,lastn('dani','bilel'));
我知道如何一次更新所有姓氏,但我需要保留现有姓氏并添加其他姓氏,或者删除一个姓氏而不影响其他姓氏。简而言之,我希望我的代码像(我不熟悉PL/SQL):
insert into table
(select last_name from example where id=1)
values lastn('new');
在这种情况下,我想让名字为 'bilel',第二个姓氏为 last_name 的人为 'dani'
select * from person where id in (select id from pernom p,table(p.last_name)
where column_value(1)='bilel' and column_value(2)='dani');
我知道它不是那样工作的,但我想知道那种情况下的 CRUD(create update delete) 语句。和 select 在 where 语句中使用 varray 的语句。
感谢您的回复。
Oracle does not support piecewise updates on VARRAY columns. However, VARRAY columns can be inserted into or updated as an atomic unit.
如此处的示例所示,您可以改为通过 PL/SQL 操作集合;包括向数组中添加一个元素:
declare
l_last_name lastn;
begin
select last_name into l_last_name
from person where id = 1;
l_last_name.extend();
l_last_name(l_last_name.count) := 'third';
update person
set last_name = l_last_name
where id = 1;
end;
/
PL/SQL procedure successfully completed.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'bilel', 'third')
您也可以通过 cast(multiset(...) as ...)
:
-- rollback; to reverse PL/SQL block actions above
update person p
set last_name = cast(multiset(
select column_value
from table (last_name)
union all
select 'third' from dual
) as lastn)
where id = 1;
1 row updated.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'bilel', 'third')
这会将现有的 last_name
值分解为多行,合并为一个新值,然后将组合结果转换回您的 varray
类型。
您可以用类似的方式删除或更新元素:
update person p
set last_name = cast(multiset(
select column_value
from table (last_name)
where column_value != 'bilel'
) as lastn)
where id = 1;
1 row updated.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'third')
update person p
set last_name = cast(multiset(
select case column_value when 'third' then 'second' else column_value end
from table (last_name)
) as lastn)
where id = 1;
1 row updated.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'second')
对于 select 语句,我找到了解决方案,它是这样的:
select * from person p where id in (select id from table(p.last_name) where
column_value='bilel' intersect select id from table(p.last_name) where
column_value='dani');
或
select * from agent ag where id in (select id from table(ag.prenom)
t1,table(ag.prenom) t2,table(ag.prenom) t3 where t1.column_value='bilel' and
t2.column_value='dani' and t3.column_value='third');
假设我正在使用一个 table 人,并且这些人可能有多个姓氏,因此该属性应该是一个包含 3 个元素的数组(例如,这与存储姓氏的位置无关),这里是一个简单的 sql 用于创建姓氏类型,table 人并在 oracle 的 sql developper (11G XE):
中添加示例行create type lastn as varray(3) of varchar2(10);
CREATE TABLE person
(
ID NUMBER NOT NULL
, last_name lastn
, CONSTRAINT EXEMPLE_PK PRIMARY KEY
(
ID
)
ENABLE
);
insert into person values(1,lastn('dani','bilel'));
我知道如何一次更新所有姓氏,但我需要保留现有姓氏并添加其他姓氏,或者删除一个姓氏而不影响其他姓氏。简而言之,我希望我的代码像(我不熟悉PL/SQL):
insert into table
(select last_name from example where id=1)
values lastn('new');
在这种情况下,我想让名字为 'bilel',第二个姓氏为 last_name 的人为 'dani'
select * from person where id in (select id from pernom p,table(p.last_name)
where column_value(1)='bilel' and column_value(2)='dani');
我知道它不是那样工作的,但我想知道那种情况下的 CRUD(create update delete) 语句。和 select 在 where 语句中使用 varray 的语句。
感谢您的回复。
Oracle does not support piecewise updates on VARRAY columns. However, VARRAY columns can be inserted into or updated as an atomic unit.
如此处的示例所示,您可以改为通过 PL/SQL 操作集合;包括向数组中添加一个元素:
declare
l_last_name lastn;
begin
select last_name into l_last_name
from person where id = 1;
l_last_name.extend();
l_last_name(l_last_name.count) := 'third';
update person
set last_name = l_last_name
where id = 1;
end;
/
PL/SQL procedure successfully completed.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'bilel', 'third')
您也可以通过 cast(multiset(...) as ...)
:
-- rollback; to reverse PL/SQL block actions above
update person p
set last_name = cast(multiset(
select column_value
from table (last_name)
union all
select 'third' from dual
) as lastn)
where id = 1;
1 row updated.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'bilel', 'third')
这会将现有的 last_name
值分解为多行,合并为一个新值,然后将组合结果转换回您的 varray
类型。
您可以用类似的方式删除或更新元素:
update person p
set last_name = cast(multiset(
select column_value
from table (last_name)
where column_value != 'bilel'
) as lastn)
where id = 1;
1 row updated.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'third')
update person p
set last_name = cast(multiset(
select case column_value when 'third' then 'second' else column_value end
from table (last_name)
) as lastn)
where id = 1;
1 row updated.
select last_name from person where id = 1;
LAST_NAME
--------------------------------------------------
LASTN('dani', 'second')
对于 select 语句,我找到了解决方案,它是这样的:
select * from person p where id in (select id from table(p.last_name) where
column_value='bilel' intersect select id from table(p.last_name) where
column_value='dani');
或
select * from agent ag where id in (select id from table(ag.prenom)
t1,table(ag.prenom) t2,table(ag.prenom) t3 where t1.column_value='bilel' and
t2.column_value='dani' and t3.column_value='third');