sql >> Databasteknik >  >> RDS >> Oracle

Hur kan du tvinga en funktion i en where-klausul att köras en gång i oracle?

Varför använder du PL/SQL för detta överhuvudtaget? Av det du har sagt att du gör lite matematik, varför inte bara göra det i SQL? Detta kommer också att vara möjligt med en kombination av INSTR och SUBSTR men det är snyggare att titta på med 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 av REGEXP_SUBSTR-utgång

Om du har för att göra detta i PL/SQL bör du göra två saker:

  1. Se om du kan deklarera din funktion som deterministisk .
  2. Försök och dra nytta av sub -frågecache .

Det verkar som om du redan gör 2, men du kan försöka utöka detta genom att använda en WITH-sats:

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


  1. Det går inte att lagra datum i databasen i php

  2. Skapa tabellnamn som är reserverade ord/sökord i MS SQL Server

  3. Varför kan jag inte fråga direkt på jsonb_array_elements?

  4. GIN-index på smallint[] kolumn används inte eller feloperatorn är inte unik