【问题标题】:How to manipulate VARRAYS in sql (oracle)?如何在 sql (oracle) 中操作 VARRAYS?
【发布时间】:2018-12-04 19:06:35
【问题描述】:

假设我正在使用一个表 person,并且 people 可能有多个姓氏,因此该属性应该是一个由 3 个元素组成的 varray(它与存储姓氏的位置无关),这里是一个用于创建在 oracle 的 sql developer (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”,第二个姓氏为“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 语句中带有可变数组的语句。

感谢您的回复。

【问题讨论】:

    标签: sql oracle11g object-relational-model varray


    【解决方案1】:

    From the docs:

    Oracle 不支持对 VARRAY 列进行分段更新。但是,VARRAY 列可以作为原子单元插入或更新。

    如那里的示例所示,您可以改为通过 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')
    

    【讨论】:

    • 你能告诉我在这种情况下如何设置 where 条件吗?我想从 last_name=lastn('bilel'); 的人中选择 last_name那个 sql 不起作用!
    【解决方案2】:

    对于 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');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 2014-07-22
      • 1970-01-01
      • 1970-01-01
      • 2022-08-08
      • 1970-01-01
      相关资源
      最近更新 更多