繁体   English   中英

将函数从 Oracle 转换为 PostgreSQL

[英]Converting function from Oracle to PostgreSQL

我正在将一些东西从 Oracle 转换为 PostgreSQL。 在 Oracle 文件中有一个函数:

instr(string,substring,starting point,nth location)

或在我的文件中

instr(string,chr(10),instr(string,substring),1)

在 PostgreSQL 中这不存在,所以我查找了一个等效的函数。 我发现:

position(substring in string)

但这不允许起始位置和第 n 个位置参数。

有没有办法让这个函数从给定的点开始? 或者是否有更好的函数可以在 PostgreSQL 中使用,我可以在其中指定起始位置和第 n 个位置?

这必须适用于 PostgreSQL 8.2.15,因为这是我们在数据库上运行的版本。

Postgres 中的函数strpos(str, sub)等价于 Oracle 中的instr(str, sub) 不幸的是,该函数没有第三个和第四个参数,因此 Postgres 中的表达式必须更复杂。

函数substr(str, n)n位置开始给出str的子串。

instr(str, ch, instr(str, sub), 1);                               --oracle
strpos(substr(str, strpos(str, sub)), ch) + strpos(str, sub) - 1; --postgres

由于instr()是一个强大的函数,我根据自己的需要在 plpgsql 中编写了它。

create or replace function instr(str text, sub text, startpos int = 1, occurrence int = 1)
returns int language plpgsql
as $$
declare 
    tail text;
    shift int;
    pos int;
    i int;
begin
    shift:= 0;
    if startpos = 0 or occurrence <= 0 then
        return 0;
    end if;
    if startpos < 0 then
        str:= reverse(str);
        sub:= reverse(sub);
        pos:= -startpos;
    else
        pos:= startpos;
    end if;
    for i in 1..occurrence loop
        shift:= shift+ pos;
        tail:= substr(str, shift);
        pos:= strpos(tail, sub);
        if pos = 0 then
            return 0;
        end if;
    end loop;
    if startpos > 0 then
        return pos+ shift- 1;
    else
        return length(str)- length(sub)- pos- shift+ 3;
    end if;
end $$;

一些检查(来自OLAP DML 函数的示例):

select instr('Corporate Floor', 'or', 3, 2);  -- gives 14
select instr('Corporate Floor', 'or', -3, 2); -- gives 2

Postgres 8.2 中没有reverse()函数。 你可以使用这个:

-- only for Postgres 8.4 or earlier!
create or replace function reverse(str text)
returns text language plpgsql
as $$
declare
    i int;
    res text = '';
begin
    for i in 1..length(str) loop
        res:= substr(str, i, 1) || res;
    end loop;
    return res;
end $$;

最简单的形式:

instr(string, substring) ::= strpos(string, substring)

使用position参数:

对于正position值:

instr(string, substring, position) ::= strpos(substr(string, position), substring) + position - 1

对于负position值:

instr(string, substring, position) ::= strpos(substr(string, char_length(string) + position + 1), substring) + char_length(string) + position

使用occurrence参数:

这在 PostgreSQL 中不存在。 您似乎不需要它(示例给出occurrence = 1 ),但是如果您这样做了,那么您需要编写一个函数,该函数递归地处理从第二个版本中提取的子字符串。

所以:

instr(string,chr(10),instr(string,substring),1)

变成

strpos(substr(string, strpos(string, substring)), chr(10)) + strpos(string, substring) - 1

您可以在 postgres 中使用split_part()函数

参考以下链接

https://www.postgresqltutorial.com/postgresql-split_part/

SELECT SPLIT_PART('A,B,C', ',', 2);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM