在 oracle sql 中计算 ipaddress 十进制表示

calculating ipaddress decimal representation in oracle sql

我想获取 SQL 中给定 IP 地址的十进制值 例如 192.168.0.0 其十进制表示形式为 3232235520IP - DECIMAL

select 
       TO_NUMBER(LISTAGG(binary1, '') WITHIN GROUP ( ORDER BY cnt), 'XXXXXXXX') as Numeric1
from (
     select 1 as grp, rownum as cnt
            , NVL(TRIM(LEADING '0' FROM utl_raw.cast_from_binary_integer(regexp_substr('192.168.255.255','\d+', 1, rownum))), '00') as binary1
          from dual connect by rownum <= 4
     ) temp
group by grp

我用的是oracle 11g,想出了上面的方法。

  1. 使用 ult_raw.cast_from_binary_integer 将八位字节转换为二进制表示,但内部二进制被转换为十六进制表示。因此,内部查询的输出基本上是八位字节的十六进制表示。
  2. 十六进制表示是通过组合 4 个二进制示例 (1000)2 = (8)16 因此得到 (10001000)2 的十进制值等于得到 (88)16
  3. 的值
  4. 我附加了保留八位位组顺序的十六进制表示 cnt 列并将结果与​​ LISTAGG
  5. 组合在一起

更新

我正在使用 LISTAGG 并通过 clauses 连接,当我尝试转换 1000 条记录时,这是否有任何性能问题。 this method as suggested is simple and readable but there is no mathematical explanation. second method 这使用了 PL/SQL 函数,我将把它视为最后的手段。

this method的数学解释如下

SELECT
TO_NUMBER(REGEXP_SUBSTR('127.0.0.1','\w+',1,1))*POWER(2,24)
+ TO_NUMBER(REGEXP_SUBSTR('127.0.0.1','\w+',1,2))*POWER(2,16)
+ TO_NUMBER(REGEXP_SUBSTR('127.0.0.1','\w+',1,3))*POWER(2,8)
+ TO_NUMBER(REGEXP_SUBSTR('127.0.0.1','\w+',1,4))*POWER(2,0) IP
FROM
DUAL;

suppose I have IPADDRESS = 255.127.72.1

二进制表示是 11111111.01111111.01001000.00000001

converting to decimal 

first octet
1.231 + 1.230 + 1.229 + 1.228
+ 1.227 + 1.226 + 1.225 + 1.224

= (1.27 + 1.26 + 1.25 + 1.24 
   + 1.23 + 1.22 + 1.21 + 1.1).224
= (28 - 1).224
= (255).224

second octet
0.223 + 1.222 + 1.221 + 1.220
+ 1.219 + 1.218 + 1.217 + 1.216

= (0.27 + 1.26 + 1.25 + 1.24 
   + 1.23 + 1.22 + 1.21 + 1.1).216
= (27 - 1).216
= (127).216

third octet
0.215 + 1.214 + 0.213 + 0.212
+ 1.211 + 0.210 + 0.29 + 0.28

= (0.27 + 1.26 + 0.25 + 0.24 
   + 1.23 + 0.22 + 0.21 + 0.1).216
= (26 + 1.23).216
= (72).216

similarly the last octet

我能够使用以下方法消除子查询

select sum(regexp_substr('255.127.72.1', '\d+', 1, rownum) * POWER(2, 32 - 8*rownum))  as binary1
          from dual connect by rownum <= 4