虚拟列 - 在视图中使用它(Oracle)

时间:2011-12-10 14:03:50

标签: sql oracle function plsql oracle11g

我使用以下代码在Oracle中创建了一个虚拟列。

CREATE OR REPLACE function email_address (ID_ varchar2)
return varchar2
deterministic
as

lname varchar2 (256);
snumber varchar2 (256);
 email varchar2 (256);
    BEGIN
    select substr( p.name, instr( p.name, ' ', -1 ) + 1 ) into lname
    from person p where p.id = id_;

    SELECT regexp_replace(p.service_no, '[^0-9]*', '') into snumber
    FROM person p where p.ID = id_;

  email:= snumber||lname||'@met.af';

return email;
end email_address;


虚拟列工作正常,它确实填充了我想在虚拟列中实现的内容。但是当我使用虚拟列表创建视图时会出现问题;表现非常糟糕(观点的人口)。在这里,我想提一下,如果我不使用该功能(即电子邮件的空列),该视图可以正常工作。 视图代码如下

select  distinct
    person.SERVICE_NO as Service_No,
    person.CNIC_NO as CNIC, person.NAME as NAME ,
    card.CPLC_SERIAL_NO as Card_Number,
    child_dc.NAME as Child_DC,
    root_dc.NAME as Root_DC, person.OU as OU,
    person.EMAIL as Email
from

 person_card inner join person
 on person_card.PERSON_ID = person.ID
 inner join card
 on person_card.CARD_ID = card.ID
    left outer join child_dc
 on person.CHILD_DC_ID = child_dc.ID
    left outer join root_dc
 on child_dc.ID = root_dc.ID; 


我猜想当我创建一个虚拟列时,oracle强行要求我将数据类型长度保持为4000,因为它太大或太重而无法填充。我该怎么做才能填充视图。我需要有一个虚拟列,因为应用程序没有输入电子邮件。 需要帮助。

1 个答案:

答案 0 :(得分:7)

我不认为这是列的大小(顺便说一句:不要“推测”,测试)。

我敢打赌,对于结果中的每一行,一遍又一遍地调用该函数。因此,对于结果中的每一行,您可以在人员表上进行两次(!)选择。

编辑:上述声明我错了。仅当基于其的列更新时才调用虚拟列的函数。

只需在函数中执行一个SELECT即可略微改善:

select substr( p.name, instr( p.name, ' ', -1 ) + 1 ), 
       regexp_replace(p.service_no, '[^0-9]*', '')
   into lname, snumber
from person p where p.id = id_;

但我建议简单地将该逻辑放入视图中并在视图中构建电子邮件字符串:

select  distinct
        person.SERVICE_NO as Service_No,
        person.CNIC_NO as CNIC, person.NAME as NAME ,
        card.CPLC_SERIAL_NO as Card_Number,
        child_dc.NAME as Child_DC,
        root_dc.NAME as Root_DC, person.OU as OU,
        regexp_replace(p.service_no, '[^0-9]*', '')||substr( p.name, instr( p.name, ' ', -1 ) + 1 )||'@met.af' as email
from person_card 
inner join person
 on person_card.PERSON_ID = person.ID
inner join card
 on person_card.CARD_ID = card.ID
    left outer join child_dc
 on person.CHILD_DC_ID = child_dc.ID
    left outer join root_dc
 on child_dc.ID = root_dc.ID; 

这样就不需要额外的选择,它应该运行得很好。