Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie können Sie eine Funktion in einer Where-Klausel zwingen, einmal in Oracle ausgeführt zu werden?

Warum verwenden Sie dafür überhaupt PL/SQL? Nach dem, was Sie gesagt haben, machen Sie etwas Mathematik, warum tun Sie das nicht einfach in SQL? Das geht auch mit einer Kombination aus INSTR und SUBSTR, ist aber schöner anzusehen mit 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

SQL Fiddle-Demonstration der REGEXP_SUBSTR-Ausgabe

Wenn Sie haben Um dies in PL/SQL zu tun, sollten Sie zwei Dinge tun:

  1. Prüfen Sie, ob Sie Ihre Funktion als deklarieren können deterministisch .
  2. Probieren Sie aus und nutzen Sie sub -Abfrage-Caching .

Es sieht so aus, als ob Sie bereits 2 tun, aber Sie könnten versuchen, dies zu erweitern, indem Sie eine WITH-Klausel verwenden:

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