在 oracle sql 中计算 ipaddress 十进制表示
calculating ipaddress decimal representation in oracle sql
我想获取 SQL
中给定 IP 地址的十进制值
例如 192.168.0.0
其十进制表示形式为 3232235520
。 IP - 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,想出了上面的方法。
- 使用
ult_raw.cast_from_binary_integer
将八位字节转换为二进制表示,但内部二进制被转换为十六进制表示。因此,内部查询的输出基本上是八位字节的十六进制表示。
- 十六进制表示是通过组合 4 个二进制示例 (1000)2 = (8)16
因此得到 (10001000)2 的十进制值等于得到 (88)16
的值
- 我附加了保留八位位组顺序的十六进制表示
cnt
列并将结果与 LISTAGG
组合在一起
更新
我正在使用 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
我想获取 SQL
中给定 IP 地址的十进制值
例如 192.168.0.0
其十进制表示形式为 3232235520
。 IP - 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,想出了上面的方法。
- 使用
ult_raw.cast_from_binary_integer
将八位字节转换为二进制表示,但内部二进制被转换为十六进制表示。因此,内部查询的输出基本上是八位字节的十六进制表示。 - 十六进制表示是通过组合 4 个二进制示例 (1000)2 = (8)16 因此得到 (10001000)2 的十进制值等于得到 (88)16 的值
- 我附加了保留八位位组顺序的十六进制表示
cnt
列并将结果与LISTAGG
组合在一起
更新
我正在使用 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