Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como você pode forçar uma função em uma cláusula where para executar uma vez no oracle?


Por que você está usando PL/SQL para isso? Pelo que você disse que está fazendo algumas contas, por que não fazer isso apenas no SQL? Isso também será possível com uma combinação de INSTR e SUBSTR, mas é mais bonito de se ver com REGEXP_SUBSTR.
select to_number(regexp_substr(ip, '[^.]+', 1, 1)) * power(2,24)
        + to_number(regexp_substr(ip, '[^.]+', 1, 2)) * power(2,16)
        + to_number(regexp_substr(ip, '[^.]+', 1, 3)) * power(2,8)
        + to_number(regexp_substr(ip, '[^.]+', 1, 4))
     , icb.*
     , icl.* 
  from ip_city_block icb
  join ip_city_location icl
    on icl.locid = icb.locid  
 where to_number(regexp_substr(ip, '[^.]+', 1, 1)) * power(2,24)
        + to_number(regexp_substr(ip, '[^.]+', 1, 2)) * power(2,16)
        + to_number(regexp_substr(ip, '[^.]+', 1, 3)) * power(2,8)
        + to_number(regexp_substr(ip, '[^.]+', 1, 4))
       between icb.startipnum and icb.endipnum

Demonstração do SQL Fiddle da saída REGEXP_SUBSTR

Se você tem para fazer isso em PL/SQL você deve fazer duas coisas:
  1. Veja se você pode declarar sua função como determinista .
  2. Experimente e aproveite sub -cache de consulta .

Parece que você já está fazendo 2, mas você pode tentar estender isso usando uma cláusula WITH:
with the_ip as ( select get_ip_integer('74.253.103.98') as ip from dual )
select the_ip.ip
     , icb.*
     , icl.* 
  from ip_city_block icb
  join ip_city_location icl
    on icl.locid = icb.locid
  join the_ip
    on the_ip.ip between icb.startipnum and icb.endipnum