【问题标题】:Virtual Column - Using it in view (Oracle)虚拟列 - 在视图中使用它 (Oracle)
【发布时间】:2012-01-17 10:14:31
【问题描述】:

我在 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,从而使其太大或太重而无法填充。我应该怎么做才能使视图填充。我需要有一个虚拟列,因为应用程序没有输入电子邮件。 需要帮助。

【问题讨论】:

    标签: sql oracle function plsql oracle11g


    【解决方案1】:

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

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

    编辑:我对上述说法有误。虚拟列的函数只有在它所基于的列更新时才会被调用。

    您可以通过在函数中仅执行一次 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; 
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 2019-01-20
      相关资源
      最近更新 更多