Buscar texto jerárquico en base de datos Oracle

Tabla = BLOQUEO (Tiene un índice único compuesto de ambas columnas)

IP_ADDRESS   CIDR_SIZE
=========    ==========
10.10         16
15.0          16
67.7          16
18.0           8

Requisitos:

  • no se permite el subbloque. Por ejemplo 67.7.1 y 24 no están permitidos ya que es hijo de 67.7. En otras palabras, si hay alguna dirección IP en la base de datos que coincida con la parte inicial de la nueva IP, entonces debería fallar. ¿Es posible que lo haga utilizando una consulta SQL de Oracle?

Estaba pensando en hacerlo por ...

  1. Select all records into the memory.
  2. Convert each IP into its binary bits

    10.10 = 00001010.00001010
    15.0 = 00001111.00000000
    67.7 = 01000011.00000111
    18.0 = 00010010.00000000

  3. Convert new IP into binary bit. 67.7.1 = 01000011.00000111.00000001

  4. Check to see if new IP binary bits start with existing IP binary bits.
  5. If true, then the new record exists in the database. For example, new binary bit 01000011.00000111.00000001 does start with existing ip (67.7) binary bits 01000011.00000111. Rest of records don't match.

Estoy buscando para ver si hay una consulta de Oracle que pueda hacer esto por mí, es decir, devolver las direcciones IP correspondientes de la base de datos. Revisé la API de texto de Oracle, pero no encontré nada todavía.

0

2 Respuestas

Sí, puede hacerlo en SQL convirtiendo las IP en números y luego asegurándose de que no sea un registro con un tamaño cidr más pequeño que el mismo ipnum cuando se utiliza su tamaño cidr .

WITH ipv AS
(   SELECT  IP.*
        ,   NVL(REGEXP_SUBSTR( ip, '\d+', 1, 1 ),0) * 256 * 256 * 256  -- octet1
        +   NVL(REGEXP_SUBSTR( ip, '\d+', 1, 2 ),0) * 256 * 256        -- octet2
        +   NVL(REGEXP_SUBSTR( ip, '\d+', 1, 3 ),0) * 256              -- octet3
        +   NVL(REGEXP_SUBSTR( ip, '\d+', 1, 4 ),0)  AS ipnum          -- octet4
        ,   32-bits                 AS ignorebits
    FROM  ips IP
)
SELECT  IP1.ip, IP1.bits
FROM    ipv IP1
WHERE   NOT EXISTS
    (   SELECT  1
        FROM    ipv IP2
        WHERE   IP2.bits < IP1.bits
        AND     TRUNC( IP2.ipnum/POWER( 2, IP2.ignorebits ) )
              = TRUNC( IP1.ipnum/POWER( 2, IP2.ignorebits ) )
    )

Nota: Mi ejemplo usa la tabla equivalente a la suya:

SQL> desc ips
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 IP                                        NOT NULL VARCHAR2(16)
 BITS                                      NOT NULL NUMBER
0
agregado

Is there a reason you can't use the INSTR function? http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions068.htm#i77598

I'd do something like a NOT EXISTS clause that checks for INSTR(b_outer.IP_ADDRESS,b_inner.IP_ADDRESS) <> 1

* edit: pensando en esto, probablemente deberías verificar si el resultado es 1 (lo que significa que las posibles direcciones de IP coinciden con el primer carácter de una dirección IP existente) en lugar de una búsqueda de subcadena general como la tuve originalmente .

0
agregado
El instrumento no funcionará si el número de bits no se superponen en un factor de 8. por ejemplo, 10.224/11 es un padre de 10.240/12 pero no 10.176/12
agregado el autor Sodved, fuente
Gracias. No me importa agregar otra columna a la tabla que mantenga ip_address como su formato de bit binario, si eso me ayuda a lograrlo utilizando solo una consulta, tal vez algo opuesto a la cláusula LIKE.
agregado el autor Sannu, fuente