我写了函数
CREATE FUNCTION ip2int(text) RETURNS bigint AS $$
SELECT split_part($1,'.',1)::bigint*16777216 + split_part($1,'.',2)::bigint*65536 +
split_part($1,'.',3)::bigint*256 + split_part($1,'.',4)::bigint;
$$ LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT;
SELECT ip2int('200.233.1.2');
适用于postgres数据库。 但是当我在Oracle上运行时它给了我以下错误
错误(1,21):PLS-00103:遇到符号")"当期待一个 以下内容:in out double double ref char time timestamp interval date binarynational character nchar
这是什么解决方案? 有没有办法让它与数据库无关?
答案 0 :(得分:1)
我意识到在PostgreSQL中,将一种比较常用的编程语言称为" plsql"是常见的,但PostgreSQL支持的语言恰当地称为" plpgsql& #34;和PL / SQL和PL / pgSQL是两种相似但不同的语言。此函数的语法不是Oracle定义的有效PL / SQL。 PL / SQL不使用$$来引用例程的文本; text
参数是无类型的,PL / SQL中不允许这样做; PL / SQL不支持$ 1,$ 2等参数标记; Oracle中不支持bigint
(尽管您可以定义NUMBER的子类型来处理此问题); Oracle不支持::
强制转换运算符;没有提供split_part
(虽然我想你可以写自己的);并且最后没有使用LANGUAGE SQL IMMUTABLE
...的东西。 Oracle要求函数由语句块(DECLARE...BEGIN...END
)组成,而此函数纯粹是SELECT语句;并且函数中的SELECT语句对Oracle无效,因为Oracle需要FROM子句。所以,基本上,这个函数是无效的PL / SQL。您可以将其转换为类似
CREATE OR REPLACE FUNCTION ip2int(text IN VARCHAR2)
RETURN NUMBER
AS
nRetval NUMBER;
BEGIN
SELECT TO_NUMBER(REGEXP_SUBSTR(text, '[0-9]', 1, 1)) * 16777216 +
TO_NUMBER(REGEXP_SUBSTR(text, '[0-9]', 1, 2)) * 65536 +
TO_NUMBER(REGEXP_SUBSTR(text, '[0-9]', 1, 3)) * 256 +
TO_NUMBER(REGEXP_SUBSTR(text, '[0-9]', 1, 4))
INTO nRetval
FROM DUAL;
RETURN nRetval;
END IP2INT;
但做出如此激进的改动似乎并不是你想要做的事情。
The PostgreSQL documentation on converting from PL/SQL to PL/pgSQL可能会为您提供有关此问题所涉及的挑战的一些想法。
祝你好运。
答案 1 :(得分:0)
CREATE OR REPLACE FUNCTION split_part(string VARCHAR2, delimiter VARCHAR2, n NUMBER)
RETURN VARCHAR2
IS
v_start NUMBER(5) := 1;
v_end NUMBER(5);
BEGIN
-- Find the position of n-th -1 delimiter
IF n > 1 THEN
v_start := INSTR(string, delimiter, 1, n - 1);
-- Delimiter not found
IF v_start = 0 THEN
RETURN NULL;
END IF;
v_start := v_start + LENGTH(delimiter);
END IF;
-- Find the position of n-th delimiter
v_end := INSTR(string, delimiter, v_start, 1);
-- If not found return until the end of string
IF v_end = 0 THEN
RETURN SUBSTR(string, v_start);
END IF;
RETURN SUBSTR(string, v_start, v_end - v_start);
END;
CREATE OR REPLACE FUNCTION ip2int(text IN VARCHAR2)
RETURN NUMBER
AS
nRetval NUMBER;
BEGIN
SELECT TO_NUMBER(split_part(text,'.',1)) * 16777216 +
TO_NUMBER(split_part(text,'.',2)) * 65536 +
TO_NUMBER(split_part(text,'.',3)) * 256 +
TO_NUMBER(split_part(text,'.',4))
INTO nRetval
FROM DUAL;
RETURN nRetval;
END IP2INT;
答案 2 :(得分:0)
create or replace FUNCTION ip_to_number(ip IN VARCHAR2)
RETURN NUMBER
AS
a varchar(20 char);
b varchar(20 char);
c varchar(20 char);
d varchar(20 char);
i integer;
j integer;
k integer;
ip_value integer;
begin
i := instr(ip, '.');
j := instr(ip, '.', 1, 2);
k := instr(ip, '.', 2, 3);
if (k = 0) then
raise_application_error(-20101, 'Incorrect IP format (missing at least one dot)');
end if;
a := substr(ip, 1, i - 1);
b := substr(ip, i + 1, j - i - 1);
c := substr(ip, j + 1, k - j - 1);
d := substr(ip, k + 1);
if (a not between 0 and 255) or (b not between 0 and 255) or (c not between 0 and 255) or (d not between 0 and 255) then
raise_application_error(-20102, 'Incorrect IP format (octet out of bounds)');
end if;
ip_value := to_number(a) * 16777216 + to_number(b) * 65536 + to_number(c) * 256 + to_number(d);
RETURN ip_value;
end;