Oracle
 sql >> Base de données >  >> RDS >> Oracle

Comment pouvez-vous forcer une fonction dans une clause where à s'exécuter une fois dans Oracle?

Pourquoi utilisez-vous PL/SQL pour cela ? D'après ce que vous avez dit, vous faites des calculs, pourquoi ne pas simplement le faire en SQL ? Ce sera également possible avec une combinaison de INSTR et SUBSTR, mais c'est plus joli à regarder avec 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

Démonstration SQL Fiddle de la sortie REGEXP_SUBSTR

Si vous avez pour ce faire en PL/SQL, vous devez faire deux choses :

  1. Vérifiez si vous pouvez déclarer votre fonction en tant que déterministe .
  2. Essayez de profiter de sub -mise en cache des requêtes .

Il semble que vous en fassiez déjà 2, mais vous pouvez essayer de l'étendre en utilisant une clause 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