sql - 虚拟列 - 在 View 中使用它 (Oracle)

标签 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;


虚拟列工作正常,它确实填充了我想要在虚拟列中实现的目标。但是当我使用虚拟列的表创建 View 时出现了问题;性能变得非常糟糕( View 的填充)。在这里,我想提一下,如果我不使用该功能(即电子邮件的空列),该 View 工作得很好。 查看代码如下

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

最佳答案

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

我敢打赌,结果中的每一行都会一遍又一遍地调用该函数。因此,对于结果中的每一行,您在 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_;

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

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; 

这样就不需要额外的选择,它应该可以正常运行。

关于sql - 虚拟列 - 在 View 中使用它 (Oracle),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8457032/

相关文章:

javascript - 计数器严重增加(Javascript)

ios - 尝试在 Swift 中使用来自 CKRecord 的原始数据形式

sql - 更优雅的批量验证电话号码的方法

sql - 如何: Manage multiple overlapping indexes in SQL Server 2005

php - Laravel 5.1 内部连接查询中的问题

sql - 在什么条件下 ROWNUM=1 会显着提高 "exists"syle 查询的性能

sql - 使用sql查询显示团队名称和父名称

xml - 正则表达式oracle sql 11g解析XML

mysql - 关系数据库设计 - 为支付类型创建一个实体类?

javascript - 将属性或函数附加到函数对象时是否存在任何问题