【问题标题】:Split IPv4 address into 4 numbers in Oracle sql在Oracle sql中将IPv4地址拆分为4个数字
【发布时间】:2018-05-02 16:31:38
【问题描述】:

我正在尝试将给定的 IPv4 地址拆分为四个数字。

在 SQL Server 中,这个查询很适合我:

select CAST (PARSENAME('10.20.30.40',4) AS INT) 

结果:10

select CAST (PARSENAME('10.20.30.40',3) AS INT)

结果:20

等等。

我需要 Oracle SQL 中的等效语法,但找不到。有什么想法吗?

【问题讨论】:

  • this 答案中可能有一些有价值的东西。虽然它是为 SQL Server 编写的,但它避免了 ParseName 并提供了 VarChar(n)BigInt 之间的转换。
  • 为什么坚持使用Vintage IP?
  • 所有答案的共同说明:您使用PARSENAME 的提议仅适用于四个(或更少)元素,即 IPv4。如果需要,您可以轻松修改所有给出的答案以支持 IPv6。
  • 致那些不赞成这个问题的人:如果你能解释你反对什么,这会有所帮助。这个问题似乎很清楚,OP 展示了他对解决它的了解(另一种 SQL 方言的解决方案)并要求 Oracle 等价物。这个问题有什么遗漏、错误或不清楚的地方?为什么投反对票?如果您希望他们对他人有所帮助,请解释您的反对意见。
  • @MartinSchröder - OP 并不坚持使用 Vintage IP(我不这么认为)。 OP 需要处理现有数据。您是否在问为什么可能存储在十年前的数据不使用更新类型的地址?

标签: sql sql-server oracle


【解决方案1】:

你可以使用regexp_substr:

select ip,
       regexp_substr(ip, '\d+',1,1) as first_octet,
       regexp_substr(ip, '\d+',1,2) as second_octet,
       regexp_substr(ip, '\d+',1,3) as third_octet,
       regexp_substr(ip, '\d+',1,4) as fourth_octet
from  (select '10.20.30.40' AS ip from dual )ips;

Rextester Demo

【讨论】:

    【解决方案2】:

    您可以使用比正则表达式快得多的简单字符串函数(INSTRSUBSTR):

    SQL Fiddle

    Oracle 11g R2 架构设置

    CREATE TABLE sample_data ( ip_address ) AS
    SELECT '10.20.30.40' FROM DUAL
    

    查询 1

    SELECT TO_NUMBER(
             SUBSTR( ip_address, 1, first_sep - 1 )
           ) AS ClassA,
           TO_NUMBER(
             SUBSTR( ip_address, first_sep + 1, second_sep - first_sep )
           ) AS ClassB,
           TO_NUMBER(
             SUBSTR( ip_address, second_sep + 1, third_sep - second_sep )
           ) AS ClassC,
           TO_NUMBER(
             SUBSTR( ip_address, third_sep + 1 )
           ) AS ClassD
    FROM   (
      SELECT ip_address,
             INSTR( ip_address, '.', 1, 1 ) AS first_sep,
             INSTR( ip_address, '.', 1, 2 ) AS second_sep,
             INSTR( ip_address, '.', 1, 3 ) AS third_sep
      FROM   sample_data
    )
    

    Results

    | CLASSA | CLASSB | CLASSC | CLASSD |
    |--------|--------|--------|--------|
    |     10 |     20 |     30 |     40 |
    

    【讨论】:

      【解决方案3】:

      如果您需要一个功能,这是另一种解决方案:

      SELECT REGEXP_SUBSTR('10.20.30.40', '\d+', 1, LEVEL) as octet, level
      FROM dual 
      CONNECT BY LEVEL <= 4;
      
      
      OCTET   LEVEL
      10      1
      20      2
      30      3
      40      4
      

      【讨论】:

      • 仍然不够“一体化”,因为您是硬编码 4. 最好用 1 + 点数替换它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      • 2011-01-31
      • 2014-12-12
      • 2016-04-18
      • 2018-10-28
      • 1970-01-01
      相关资源
      最近更新 更多