sql >> Base de Datos >  >> RDS >> Oracle

¿Cómo puede forzar una función en una cláusula where para que se ejecute una vez en Oracle?

¿Por qué estás usando PL/SQL para esto? Por lo que ha dicho que está haciendo algunas matemáticas, ¿por qué no hacer eso en SQL? Esto también será posible con una combinación de INSTR y SUBSTR, pero es más bonito verlo con 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

Demostración de SQL Fiddle de salida REGEXP_SUBSTR

Si tienes para hacer esto en PL/SQL debe hacer dos cosas:

  1. Vea si puede declarar su función como determinista .
  2. Pruebe y aproveche sub -almacenamiento en caché de consultas .

Parece como si ya estuvieras haciendo 2, pero podrías intentar extender esto usando una 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