Oracle
 sql >> Database >  >> RDS >> Oracle

Come puoi forzare una funzione in una clausola where per l'esecuzione una volta in Oracle?

Perché stai usando PL/SQL per questo? Da quello che hai detto che stai facendo un po' di matematica, perché non farlo semplicemente in SQL? Questo sarà possibile anche con una combinazione di INSTR e SUBSTR, ma è più carino da vedere 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

Dimostrazione SQL Fiddle dell'output REGEXP_SUBSTR

Se hai per farlo in PL/SQL dovresti fare due cose:

  1. Vedi se puoi dichiarare la tua funzione come deterministico .
  2. Prova a sfruttare sub -interroga la memorizzazione nella cache .

Sembra che tu ne stia già facendo 2, ma puoi provare ad estenderlo utilizzando una clausola 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