Representing IPv4/IPv6 addresses in Oracle

前端 未结 7 2189
清歌不尽
清歌不尽 2020-12-06 10:27

In Oracle, what is the appropriate data type or technique for representing network addresses, which addresses may be IPv4 or IPv6?

Background: I\'m converting a tab

7条回答
  •  旧巷少年郎
    2020-12-06 10:53

    you could also use a custom oracle object.

    SQL>set SERVEROUTPUT on
    SQL>drop table test;
    
    Table dropped.
    
    SQL>drop type body inaddr;
    
    Type body dropped.
    
    SQL>drop type inaddr;
    
    Type dropped.
    
    SQL>create type inaddr as object
      2  ( /* TODO enter attribute and method declarations here */
      3  A number(5),
      4  B number(5),
      5  C number(5),
      6  D number(5),
      7  E number(5),
      8  F number(5),
      9  G number(5),
     10  H NUMBER(5),
     11  MAP MEMBER FUNCTION display RETURN VARCHAR2,
     12  MEMBER FUNCTION toString( SELF IN INADDR , CONTRACT BOOLEAN DEFAULT TRUE) RETURN VARCHAR2,
     13  CONSTRUCTOR FUNCTION INADDR(SELF IN OUT NOCOPY INADDR, INADDRASSTRING VARCHAR2)  RETURN SELF AS RESULT
     14  
     15  ) NOT FINAL;
     16  /
    
    SP2-0816: Type created with compilation warnings
    
    SQL>
    SQL>
    SQL>CREATE TYPE BODY INADDR AS
      2  
      3  MAP MEMBER FUNCTION display RETURN VARCHAR2
      4  IS BEGIN
      5  return tostring(FALSE);
      6  END;
      7  
      8  
      9  MEMBER FUNCTION TOSTRING( SELF IN  INADDR , CONTRACT BOOLEAN DEFAULT TRUE) RETURN VARCHAR2 IS
     10  IP4 VARCHAR2(6) := 'FM990';
     11  ip6 varchar2(6) := 'FM0XXX';
     12    BEGIN
     13  IF CONTRACT THEN
     14    ip6 := 'FMXXXX';
     15  end if;
     16  
     17  IF CONTRACT AND A =0 AND B=0 AND C = 0 AND D=0 AND E =0 AND F = 65535 THEN --ipv4
     18      RETURN  '::FFFF:'||TO_CHAR(TRUNC(G/256),'FM990.')||TO_CHAR(MOD(G,256),'FM990.')||TO_CHAR(TRUNC(H/256),'FM990.')||TO_CHAR(MOD(H,256),'FM990');
     19  ELSE
     20      RETURN
     21  TO_CHAR(A,ip6)||':'||
     22  TO_CHAR(B,IP6)||':'||
     23  TO_CHAR(C,ip6)||':'||
     24  TO_CHAR(D,ip6)||':'||
     25  TO_CHAR(E,ip6)||':'||
     26  TO_CHAR(F,ip6)||':'||
     27  TO_CHAR(G,ip6)||':'||
     28  TO_CHAR(H,ip6);
     29  end if;
     30    end;
     31  
     32      CONSTRUCTOR FUNCTION inaddr(SELF IN OUT NOCOPY inaddr, inaddrasstring VARCHAR2)
     33                                 RETURN SELF AS RESULT IS
     34      begin
     35          if instr(inaddrasstring,'.') > 0 then
     36            --ip4
     37  null;
     38              a := 0;
     39              B := 0;
     40              C := 0;
     41              D := 0;
     42              E := 0;
     43              F := TO_NUMBER('FFFF', 'XXXX');
     44              G := TO_NUMBER(TO_CHAR(TO_NUMBER(REGEXP_SUBSTR(INADDRASSTRING,'([0-9]{1,3}).',1,1,'i',1),'999'),'FM0X')
     45  ||TO_CHAR(TO_NUMBER(REGEXP_SUBSTR(INADDRASSTRING,'([0-9]{1,3}).',1,2,'i',1),'999'),'FM0X')
     46  ,'XXXX');
     47              h := TO_NUMBER(TO_CHAR(TO_NUMBER(REGEXP_SUBSTR(INADDRASSTRING,'([0-9]{1,3}).',1,3,'i',1),'999'),'FM0X')
     48  ||TO_CHAR(TO_NUMBER(REGEXP_SUBSTR(INADDRASSTRING,'([0-9]{1,3})',1,4,'i',1),'999'),'FM0X')
     49  ,'XXXX');
     50  
     51          ELSIF instr(inaddrasstring,':') > 0 then
     52              --ip6
     53              a := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,1,'i',1),'XXXX');
     54              b := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,2,'i',1),'XXXX');
     55              c := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,3,'i',1),'XXXX');
     56              d := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,4,'i',1),'XXXX');
     57              E := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,5,'i',1),'XXXX');
     58              f := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,6,'i',1),'XXXX');
     59              g := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,7,'i',1),'XXXX');
     60              H := TO_NUMBER(REGEXP_SUBSTR(inaddrasstring,'([0-9a-fA-F]{1,4})',1,8,'i',1),'XXXX');
     61          end if;
     62  
     63          RETURN;
     64      END;
     65  end;
     66  /
    
    Type body created.
    
    SQL>
    SQL>create table test
      2  (id integer primary key,
      3  address inaddr);
    
    Table created.
    
    SQL>
    SQL>select * from test;
    
    no rows selected
    
    SQL>
    SQL>
    SQL>insert into test values (1, INADDR('fe80:0000:0000:0000:0202:b3ff:fe1e:8329') );
    
    1 row created.
    
    SQL>INSERT INTO TEST VALUES (2, INADDR('192.0.2.128') );
    
    1 row created.
    
    SQL>insert into test values (3, INADDR('20.0.20.1') );
    
    1 row created.
    
    SQL>insert into test values (4, INADDR('fe80:0001:0002:0003:0202:b3ff:fe1e:8329') );
    
    1 row created.
    
    SQL>insert into test values (5, INADDR('fe80:0003:0002:0003:0202:b3ff:fe1e:8329') );
    
    1 row created.
    
    SQL>INSERT INTO TEST VALUES (6, INADDR('fe80:0003:0001:0003:0202:b3ff:fe1e:8329') );
    
    1 row created.
    
    SQL>INSERT INTO TEST VALUES (7, INADDR('fe80:0003:0001:0003:0202:b3ff:fe1e:8328') );
    
    1 row created.
    
    SQL>INSERT INTO TEST VALUES (8, INADDR('dead:beef:f00d:cafe:dea1:aced:b00b:1234') );
    
    1 row created.
    
    SQL>
    SQL>COLUMN INET_ADDRESS_SHORT FORMAT A40
    SQL>column inet_address_full format a40
    SQL>
    SQL>select t.address.toString() inet_address_short, t.address.display( ) inet_address_full
      2  from test T
      3  order by t.address ;
    
    INET_ADDRESS_SHORT                       INET_ADDRESS_FULL
    ---------------------------------------- ----------------------------------------
    ::FFFF:20.0.20.1                         0000:0000:0000:0000:0000:FFFF:1400:1401
    ::FFFF:192.0.2.128                       0000:0000:0000:0000:0000:FFFF:C000:0280
    DEAD:BEEF:F00D:CAFE:DEA1:ACED:B00B:1234  DEAD:BEEF:F00D:CAFE:DEA1:ACED:B00B:1234
    FE80:0:0:0:202:B3FF:FE1E:8329            FE80:0000:0000:0000:0202:B3FF:FE1E:8329
    FE80:1:2:3:202:B3FF:FE1E:8329            FE80:0001:0002:0003:0202:B3FF:FE1E:8329
    FE80:3:1:3:202:B3FF:FE1E:8328            FE80:0003:0001:0003:0202:B3FF:FE1E:8328
    FE80:3:1:3:202:B3FF:FE1E:8329            FE80:0003:0001:0003:0202:B3FF:FE1E:8329
    FE80:3:2:3:202:B3FF:FE1E:8329            FE80:0003:0002:0003:0202:B3FF:FE1E:8329
    
    8 rows selected.
    
    SQL>spool off
    

    i just put this together in the last hour (and taught myself objects at the same time) so im sure it can be improved upon. if i make updates i'll repost them here

提交回复
热议问题