PostgreSQL仿照Oracle的instr函数

本文介绍了 PostgreSQL 中模仿 Oracle 的 instr 函数实现方法,提供了三种不同参数组合的自定义函数来定位子字符串的位置,支持从指定位置开始搜索及指定出现次数。

转自:http://www.myexception.cn/operating-system/480929.html


PostgreSQL模仿Oracle的instr函数

[sql]  view plain  copy
  1. --  
  2. -- instr functions that mimic Oracle's counterpart  
  3. -- Syntax: instr(string1, string2, [n], [m]) where [] denotes optional parameters.  
  4. --  
  5. -- Searches string1 beginning at the nth character for the mth occurrence  
  6. -- of string2.  If n is negative, search backwards.  If m is not passed,  
  7. -- assume 1 (search starts at first character).  
  8. --  
  9.   
  10. CREATE FUNCTION instr(varcharvarcharRETURNS integer AS $$  
  11. DECLARE  
  12.     pos integer;  
  13. BEGIN  
  14.     pos:= instr($1, $2, 1);  
  15.     RETURN pos;  
  16. END;  
  17. $$ LANGUAGE plpgsql STRICT IMMUTABLE;  
  18.   
  19.   
  20. CREATE FUNCTION instr(string varchar, string_to_search varchar, beg_index integer)  
  21. RETURNS integer AS $$  
  22. DECLARE  
  23.     pos integer NOT NULL DEFAULT 0;  
  24.     temp_str varchar;  
  25.     beg integer;  
  26.     length integer;  
  27.     ss_length integer;  
  28. BEGIN  
  29.     IF beg_index > 0 THEN  
  30.         temp_str := substring(string FROM beg_index);  
  31.         pos := position(string_to_search IN temp_str);  
  32.   
  33.         IF pos = 0 THEN  
  34.             RETURN 0;  
  35.         ELSE  
  36.             RETURN pos + beg_index - 1;  
  37.         END IF;  
  38.     ELSE  
  39.         ss_length := char_length(string_to_search);  
  40.         length := char_length(string);  
  41.         beg := length + beg_index - ss_length + 2;  
  42.   
  43.         WHILE beg > 0 LOOP  
  44.             temp_str := substring(string FROM beg FOR ss_length);  
  45.             pos := position(string_to_search IN temp_str);  
  46.   
  47.             IF pos > 0 THEN  
  48.                 RETURN beg;  
  49.             END IF;  
  50.   
  51.             beg := beg - 1;  
  52.         END LOOP;  
  53.   
  54.         RETURN 0;  
  55.     END IF;  
  56. END;  
  57. $$ LANGUAGE plpgsql STRICT IMMUTABLE;  
  58.   
  59.   
  60. CREATE FUNCTION instr(string varchar, string_to_search varchar,  
  61.                       beg_index integer, occur_index integer)  
  62. RETURNS integer AS $$  
  63. DECLARE  
  64.     pos integer NOT NULL DEFAULT 0;  
  65.     occur_number integer NOT NULL DEFAULT 0;  
  66.     temp_str varchar;  
  67.     beg integer;  
  68.     i integer;  
  69.     length integer;  
  70.     ss_length integer;  
  71. BEGIN  
  72.     IF beg_index > 0 THEN  
  73.         beg := beg_index;  
  74.         temp_str := substring(string FROM beg_index);  
  75.   
  76.         FOR i IN 1..occur_index LOOP  
  77.             pos := position(string_to_search IN temp_str);  
  78.   
  79.             IF i = 1 THEN  
  80.                 beg := beg + pos - 1;  
  81.             ELSE  
  82.                 beg := beg + pos;  
  83.             END IF;  
  84.   
  85.             temp_str := substring(string FROM beg + 1);  
  86.         END LOOP;  
  87.   
  88.         IF pos = 0 THEN  
  89.             RETURN 0;  
  90.         ELSE  
  91.             RETURN beg;  
  92.         END IF;  
  93.     ELSE  
  94.         ss_length := char_length(string_to_search);  
  95.         length := char_length(string);  
  96.         beg := length + beg_index - ss_length + 2;  
  97.   
  98.         WHILE beg > 0 LOOP  
  99.             temp_str := substring(string FROM beg FOR ss_length);  
  100.             pos := position(string_to_search IN temp_str);  
  101.   
  102.             IF pos > 0 THEN  
  103.                 occur_number := occur_number + 1;  
  104.   
  105.                 IF occur_number = occur_index THEN  
  106.                     RETURN beg;  
  107.                 END IF;  
  108.             END IF;  
  109.   
  110.             beg := beg - 1;  
  111.         END LOOP;  
  112.   
  113.         RETURN 0;  
  114.     END IF;  
  115. END;  
  116. $$ LANGUAGE plpgsql STRICT IMMUTABLE;  
<think>我们在PostgreSQL中需要替代OracleINSTR函数。根据提供的引用,特别是引用[3]中给出了一个自定义函数来实现相同的功能。 然而,在PostgreSQL中,我们也可以使用内置函数来实现部分功能,但OracleINSTR函数功能较多(如从指定位置开始查找,指定出现次数等),因此可能需要自定义函数。 根据引用[2]和引用[3],我们可以知道OracleINSTR函数有多个参数: INSTR(string, substring [, start_position [, occurrence]]) 在PostgreSQL中,有一个内置函数`strpos`,但它只能查找第一次出现的位置,且不能指定开始位置和出现次数。 因此,我们需要创建一个自定义函数来实现INSTR的功能。引用[3]提供了一个自定义函数的实现。 下面我将引用[3]中的函数稍作整理(原函数中可能有笔误,我们根据逻辑修正)并解释: 函数功能:模拟OracleINSTR函数 参数: str: 原字符串 sub: 要查找的子字符串 startpos: 开始位置(可选,默认为1),可以是负数(表示从字符串末尾倒数开始) occurrence: 指定要查找第几次出现(可选,默认为1) 返回值:子字符串在原字符串中的位置(整数),如果找不到则返回0。 注意:原函数中有一个变量名写错了(substr应该是substr函数),并且最后返回的位置计算在负数开始的情况下需要仔细检查。 我重新整理后的函数如下(修正了原函数中的一些小问题,并确保逻辑正确): </think>在 PostgreSQL 中替代 Oracle 的 `INSTR` 函数,可通过以下两种方式实现: ### 方法一:使用 PostgreSQL 内置函数组合 对于基础功能(查找子串首次出现位置),可直接使用 `STRPOS()` 或 `POSITION()`: ```sql -- 查找子串第一次出现的位置(索引从1开始) SELECT STRPOS('a-b-c-d', '-') --> 结果: 2 SELECT POSITION('-' IN 'a-b-c-d') --> 结果: 2 -- 从指定位置开始查找(OracleINSTR(str,sub,3)) SELECT STRPOS(SUBSTR('a-b-c-d', 3), '-') + 2 --> 结果: 4 ``` > ⚠️ **局限**:无法直接实现查找第 N 次出现的位置和反向查找[^2]。 ### 方法二:创建自定义函数(完整替代) 引用[3]提供了完善的 Oracle `INSTR` 函数替代方案: ```sql 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 := 0; pos INT; i INT; BEGIN IF length(str) = 0 THEN RETURN NULL; END IF; IF startpos = 0 OR occurrence <= 0 THEN RETURN 0; END IF; -- 处理反向查找(startpos为负数) IF startpos < 0 THEN str := reverse(str); sub := reverse(sub); pos := -startpos; ELSE pos := startpos; END IF; -- 循环查找第N次出现 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 $$; ``` ### 使用示例 ```sql -- 正向查找(第2次出现) SELECT instr('a-b-c-d', '-', 1, 2); --> 结果: 4 -- 反向查找(从倒数第3位开始) SELECT instr('a-b-c-d', '-', -3, 1); --> 结果: 4 ``` ### 补充说明 1. **参数说明**: - `str`: 原始字符串 - `sub`: 搜索子串 - `startpos`: 起始位置(正数从左,负数从右) - `occurrence`: 第几次出现 (默认1) 2. **性能建议**: - 对于简单查询优先使用内置函数 - 复杂场景使用自定义函数时,建议为搜索列添加索引优化[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值