4

10進整数として格納されたIPアドレスを含むOracleデータベースがあります-これは、Webインターフェイスを介してではなく手動でデータを操作する場合に非常に苦痛ですが、ネットワーク担当者が絶えず奇妙なことをするように要求するため、手動操作は本当に便利ですWebインターフェイスの作成者は予期していませんでした。

誰かがPL/SQLまたはこれらの10進数のIPをドット付き10進数、つまり123.123.123.123形式で表示する他の方法を教えてもらえますか?

つまり、次のようなクエリを実行できるようにしたいと思います。

select hostname, inttoip(ip_address) from host;

inttoip()プロシージャにip_addressを3407801602ではなく203.30.237.2と表示させます。

理想的には、逆関数も提供する手順が必要です。

insert into host (hostname,ip_address) values ('some-hostname', iptoint('203.30.237.2'));

私はこれを行うためのperlを持っていますが、私のPL / SQL/Oracleの知識はそれをPL/SQLに移植するのに十分ではありません。


あるいは、postgresの以下に類似したoracleコンテキスト内で手続き型言語としてperlを実行する方法:

CREATE FUNCTION perl_func (integer) RETURNS integer AS $$
 <some perl>
$$ LANGUAGE plperl;

オラクル内で私が精通している言語で多くの手続き的なことを行うことができたので、可能であれば、おそらくさらに良いでしょう。

4

3 に答える 3

6

これはあなたが必要とする機能です:

create or replace
function inttoip(ip_address integer) return varchar2
deterministic
is
begin
    return to_char(mod(trunc(ip_address/256/256/256),256))
           ||'.'||to_char(mod(trunc(ip_address/256/256),256))
           ||'.'||to_char(mod(trunc(ip_address/256),256))
           ||'.'||to_char(mod(ip_address,256));
end;

(関数を決定論的にし、to_charを使用することについてのコメント-ありがとう)。

Oracle 11Gでは、フォーマットされたIPアドレスをホストテーブルの仮想列にすることができます。

alter table host
add formatted_ip_address varchar2(15)
generated always as
( to_char(mod(trunc(ip_address/256/256/256),256))
          ||'.'||to_char(mod(trunc(ip_address/256/256),256))
          ||'.'||to_char(mod(trunc(ip_address/256),256))
          ||'.'||to_char(mod(ip_address,256))
) virtual;

この列は、必要に応じてクエリのインデックスを作成できます。

クエリは次のようになります。

select hostname, formatted_ip_address from host;
于 2009-07-05T16:53:50.073 に答える
2
CREATE OR REPLACE
FUNCTION inttoip(ip_address IN INTEGER) RETURN VARCHAR2 IS
  v8 VARCHAR2(8);
BEGIN
  -- 1. convert the integer into hexadecimal representation
  v8 := TO_CHAR(ip_address, 'FMXXXXXXXX');
  -- 2. convert each XX portion back into decimal
  RETURN to_number(substr(v8,1,2),'XX')
       || '.' || to_number(substr(v8,3,2),'XX')
       || '.' || to_number(substr(v8,5,2),'XX')
       || '.' || to_number(substr(v8,7,2),'XX');
END inttoip;

CREATE OR REPLACE
FUNCTION iptoint(ip_string IN VARCHAR2) RETURN INTEGER IS
  d1 INTEGER;
  d2 INTEGER;
  d3 INTEGER;
  q1 VARCHAR2(3);
  q2 VARCHAR2(3);
  q3 VARCHAR2(3);
  q4 VARCHAR2(3);
  v8 VARCHAR2(8);
BEGIN
  -- 1. parse the input, e.g. '203.30.237.2'
  d1 := INSTR(ip_string,'.');     -- first dot
  d2 := INSTR(ip_string,'.',1,2); -- second dot
  d3 := INSTR(ip_string,'.',1,3); -- third dot
  q1 := SUBSTR(ip_string, 1, d1 - 1);           -- e.g. '203'
  q2 := SUBSTR(ip_string, d1 + 1, d2 - d1 - 1); -- e.g. '30'
  q3 := SUBSTR(ip_string, d2 + 1, d3 - d2 - 1); -- e.g. '237'
  q4 := SUBSTR(ip_string, d3 + 1);              -- e.g. '2'
  -- 2. convert to a hexadecimal string
  v8 := LPAD(TO_CHAR(TO_NUMBER(q1),'FMXX'),2,'0')
     || LPAD(TO_CHAR(TO_NUMBER(q2),'FMXX'),2,'0')
     || LPAD(TO_CHAR(TO_NUMBER(q3),'FMXX'),2,'0')
     || LPAD(TO_CHAR(TO_NUMBER(q4),'FMXX'),2,'0');
  -- 3. convert to a decimal number
  RETURN TO_NUMBER(v8, 'FMXXXXXXXX');
END iptoint;
于 2009-07-06T06:07:52.853 に答える
0
    -- INET ATON en INET NTOA and helper function GET TOKEN

        CREATE OR REPLACE function inet_ntoa (ip integer) return varchar2
    is
       ip1 integer;
       ip2 integer;
       ip3 integer;
       ip4 integer;
       ipi integer := ip;
    begin
       ip1 := floor(ipi/power(2,24));
       ipi := ipi - (ip1*power(2,24));
       ip2 := floor(ipi/power(2,16));
       ipi := ipi - (ip2*power(2,16));
       ip3 := floor(ipi/power(2,8));
       ipi := ipi - (ip3*power(2,8));
       ip4 := ipi;
       return ip1||'.'||ip2||'.'||ip3||'.'||ip4;

    end;
    /    

CREATE OR REPLACE FUNCTION get_token (the_list VARCHAR2,the_index NUMBER, delim VARCHAR2 := '.') RETURN VARCHAR2
        IS
           start_pos   INTEGER;
           end_pos     INTEGER;
        BEGIN
           IF the_index = 1 THEN
              start_pos := 1;
           ELSE
              start_pos := INSTR (the_list, delim, 1, the_index - 1);
              IF start_pos = 0 THEN
                 RETURN NULL;
              ELSE
                 start_pos := start_pos + LENGTH (delim);
              END IF;
           END IF;
           end_pos := INSTR (the_list, delim, start_pos, 1);
           IF end_pos = 0 THEN
              RETURN SUBSTR (the_list, start_pos);
           ELSE
              RETURN SUBSTR (the_list, start_pos, end_pos - start_pos);
           END IF;
        END get_token;
        /




    CREATE OR REPLACE function inet_aton (ip varchar2) return integer
    is
       invalid_ip_adres exception;
       pragma exception_init(invalid_ip_adres,-6502);
       ipi integer;
    begin
       ipi := get_token(ip,4)
            +(get_token(ip,3)*power(2,8))
                    +(get_token(ip,2)*power(2,16))
                    +(get_token(ip,1)*power(2,24));
       return ipi;
    exception
       when invalid_ip_adres
       then 
          return null;
    end;
    /
于 2009-07-06T07:31:23.167 に答える