现在有这么一个需求, 数据库中的一个手输的‘籍贯’字段,要按一定的规范截取显示在报表上,比如,如果‘籍贯’的内容是:‘山东省潍坊市昌乐县’, 那么报表里要显示为:‘山东昌乐’, 如果‘籍贯’是山东省潍坊市寒亭区 那么就要出来 山东潍坊,简化的基本需求就是这样,取省一级和县一级,如果县一级是个区,那就取到市一级,

没有县一级的话,是数据不规范,但是先将就着取省一级和市一级。

要实现这个目的,第一是要从数据库里把相应的字段取出来, 第二是要写一个oracle截取字符串的函数处理下‘籍贯’字段。

第一步比较简单,就略过,只看我们的截取函数。

create or replace function f_addr(address in varchar2) return varchar2 as
new_addr varchar2(100);
tempstr1 gscodeitems.name%type;
tempstr2 varchar2(100);
tempstr3 varchar2(100);
tempstr4 varchar2(100);
tempn0 number;
tempn1 number;
tempn2 number;
tempn3 number;
tempnn number;
cursor minzustrs is
select name from gscodeitems where gscodeitems.codesetnm = '411CBC8F-35D8-4634-944B-0C1065782F48’;
begin
/*单字县*/
if REGEXP_COUNT(address, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族县])(县))$') > 0
then new_addr := REGEXP_REPLACE(address, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族县])(县))$', '\1\6县');
/*新疆维吾尔*/
elsif REGEXP_COUNT(address, '^新疆') > 0
then new_addr := REGEXP_REPLACE(address, '^(新疆)(维吾尔自治区)((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$', '\1\5\8’);
/*特殊处理双民族两个字的民族在前, 策略是把两个字的民族干掉,就恢复成正常模式*/
elsif regexp_count(address, '([^族]+)族', 4) >= 2
then tempstr1 := regexp_substr(address, '([^族]{2})族', 3);
for minzustr in minzustrs loop
if tempstr1 = minzustr.name then
tempnn := 1; exit;
else tempnn := 0;
end if; end loop;
if tempnn = 1 then
tempn0 := length(tempstr1);
tempn1 := regexp_instr(address,tempstr1);
tempn2 := tempn1 - 1;
tempn3 := tempn1 + tempn0;
tempstr2 := substr(address,0,tempn2);
tempstr3 := substr(address, tempn3);
tempstr4 := concat(tempstr2,tempstr3);
new_addr := REGEXP_REPLACE(tempstr4, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$',
'\1\6\9');
else
tempstr1 := regexp_substr(address, '([^族])族', 3);
tempn0 := length(tempstr1);
tempn1 := regexp_instr(address,tempstr1);
tempn2 := tempn1 - 1;
tempn3 := tempn1 + tempn0;
tempstr2 := substr(address,0,tempn2);
tempstr3 := substr(address, tempn3);
tempstr4 := concat(tempstr2,tempstr3);
new_addr := REGEXP_REPLACE(tempstr4, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$', '\1\6\9');
end if; /*特殊处理单民族 两个字的民族,先干掉广西和宁夏,再取族前两个字判断是否合法,如果合法,就干掉一个字,然后走正常流程*/
elsif regexp_count(address, '([^族]+)族', 4) = 1 then
tempstr1 := regexp_substr(address, '([^族]{2})族', 3);
for minzustr in minzustrs loop
if tempstr1 = minzustr.name then
tempnn := 1; exit;
else tempnn := 0;
end if;
end loop;
if tempnn = 1 then
tempn0 := length(tempstr1);
tempn1 := regexp_instr(address,tempstr1);
tempn2 := tempn1 - 1;
tempn3 := tempn1 + tempn0 - 2;
tempstr2 := substr(address,0,tempn2);
tempstr3 := substr(address, tempn3);
tempstr4 := concat(tempstr2,tempstr3);
new_addr := REGEXP_REPLACE(tempstr4, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$',
'\1\6\9');
else
new_addr := REGEXP_REPLACE(address, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$',
'\1\6\9');
end if;
else
new_addr := REGEXP_REPLACE(address, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$',
'\1\6\9');
end if;
return new_addr;
end f_addr;

这个函数里,比较关键的,其实是一个正则表达式,函数主体用了几个if else 处理几种特殊情况,没有覆盖全部的情况,只是覆盖了几种,这个可以稍后讨论,直接看最后一个else, 这里的这个正则就是用到的最基本的正则了:

new_addr := REGEXP_REPLACE(address, '^([^省区族]+)(省|(.族)?自治区|市)((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$',
'\1\6\9');
这个内置函数,查下oracle的API即可,看到含义也跟猜到个差不多, 是一个返回一个新字符串来替代原字符串的功能,此处简单说下,第一个参数address,是源字符串,
第二个就是我们的正则pattern, 第三个是返回的字符串, 第三个参数‘\1\6\9’,如果熟悉正则的同学,可能会觉得似曾相识,这是取子表达式用的,从左到右,左括号的排序,
就是我们子表达式的排序,取第一第六第九个子表达式,直观的拿出来,就是取 ([^省区族]+)和([^族]+)和(.+),你找对了么。

分析下这里的这个正则,其实很简单,整体用两个括号分为两部分:头和尾。
第一个:^([^省区族]+)(省|(.族)?自治区|市),
第二个:((.+市|.+地区|.+州)?([^族]+)(县|市|.族自治县)|((.+)市)?([^族]+)(区|旗))$
简单的说,
第一个是匹配省、自治区和直辖市的
第二个是匹配市县两级和市区两级的,
\1自然是取省的名称,比如:山东省潍坊市昌乐县,\1就会取到:山东,
\6是取县一级的名称的,比如:山东省潍坊市昌乐县,\6就会取到:昌乐,
\9是取省市区这种行政级别的市一级的名称,比如:山东省潍坊市寒亭区,\9就会取到潍坊
当表达式匹配到\6的时候,\9的返回值会是空字符串,匹配到\9的时候,\6也会返回空字符串,所以这一个表达式,妥妥的满足我们的需求,
其他的情况,在这里先不表,就是特殊处理了下民族自治县,自治州,新疆啊等。

欢迎同学们有疑问的共同探讨。

oracle正则截取字符串的函数的更多相关文章

  1. 【面试题】JS使用parseInt()、正则截取字符串中数字

    JS使用parseInt()和正则截取字符串中数字 点击打开视频讲解更加详细 parseInt() 函数 定义和用法 parseInt() 函数可解析一个字符串,并返回一个整数. 当参数 radix ...

  2. Excel怎样从一串字符中的某个指定“字符”前后截取字符及截取字符串常用函数

    怎么样可以从一串字符中的某个指定位置的前或后截取指定个数的字符. 如:12345.6789,我要截取小数点前(或后)的3个字符.怎么样操作, 另外,怎么样从右边截取字符,就是和left()函数相反的那 ...

  3. 面试题之java 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 要求不能出现截半的情况

    题目:10. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串. 但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输 ...

  4. 数据库截取字符串SUBSTR函数的使用

    背景 今天中午做需求的时候,有类似于根据银行卡卡号的前几位判断出是哪个银行的情况,每个银行需要截取的位数都不一样,这时我就想到了SUBSTR 数据库截取字符串SUBSTR函数的使用 假设有一个表的结构 ...

  5. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。

    一.需要分析 1.输入为一个字符串和字节数,输出为按字节截取的字符串--->按照字节[byte]截取操作字符串,先将String转换成byte类型 2.汉字不可以截半--->汉字截半的话对 ...

  6. java算法面试题:编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串,但要保证汉字不被截取半个, 如“我ABC”,4,应该截取“我AB”,输入“我ABC汉DEF”,6,应该输出“我ABC”,而不是“我ABC+汉的半个”。

    package com.swift; import java.util.Scanner; public class Hanzi_jiequ { public static void main(Stri ...

  7. SQL Server中截取字符串常用函数

    SQL Server 中截取字符串常用的函数: .LEFT ( character_expression , integer_expression ) 函数说明:LEFT ( '源字符串' , '要截 ...

  8. Sql注入截取字符串常用函数

    在sql注入中,往往会用到截取字符串的问题,例如不回显的情况下进行的注入,也成为盲注,这种情况下往往需要一个一个字符的去猜解,过程中需要用到截取字符串.本文中主要列举三个函数和该函数注入过程中的一些用 ...

  9. ABAP自定义截取字符串长度函数

    SAP 中strlen()只能计算字符串的个数,不能计算含有中文字符串的长度,如字符串“SAP大波霸”,strlen('SAP大波霸') = 6,其实真实长度为3+3*2 = 9.我们可以通过cl_a ...

随机推荐

  1. mysql5.7.14安装与配置

    参考文章链接: http://jingyan.baidu.com/article/afd8f4de9006d934e286e9fd.html http://www.cnblogs.com/wenthi ...

  2. 汤姆大叔的6道js题目

    汤姆大叔的6道javascript编程题题解 看汤姆大叔的博文,其中有篇(猛戳这里)的最后有6道编程题,于是我也试试,大家都可以先试试. 1.找出数字数组中最大的元素(使用Math.max函数) 1 ...

  3. 那些年优秀的HTML5活动页面

    一个好的手机活动宣传 更能让人分享 传播是爆炸性的 下面是我平时看到一些好的微信活动宣传页面  分享给大家 其中用到的技术 常做微信活动 专题页面的人 可以看看大神们是怎么做的  这样到自己做的时候 ...

  4. Start an installation from GRUB

    Start an installation from GRUB Description This tip will show you how to start an installation for ...

  5. SNN--Second Name Node

    NameNode有这么几个配置: Property Description Suggested value dfs.name.dir Directory in NameNode’s local fil ...

  6. PDF抽取文字 C# with Adobe API

    前提是PDF里面是有文字的! 一次性取得所有页内容: /// <summary> /// 改进前取得所有页的所有word /// </summary> /// <para ...

  7. SQL Server日期函数之获得一个月中的天数

    SQL Server日期函数之获得一个月中的天数在实际中的应用比例还是占为多数的,如果你对这一技术,心存好奇的话,以下的文章将会揭开它的神秘面纱,望会在以后的学习或是工作中带来很大的帮助. 获得一个月 ...

  8. 趣味C程序100.9 绘制杨辉三角

    说明:1.本问题来源于<C语言经典.趣味.实用程序设计编程百例精解>,所有程序为本人自己编写.与原程序不同之处作有标记. 2.本系列所有程序均使用codeblocks编译,操作系统为Win ...

  9. Spring MVC小结1

    由于最近刚开始学Spring MVC,所以来讲一下自己的理解. 首先进行环境配置: 1.jdk 2.myeclipse 3.tomcat 4.maven 配置maven的时候出现了一个小的问题,JAV ...

  10. PYTHON调用JENKINS的API来进行CI

    我查到的相关API有两套,我主要用的是python-jenkins. https://pypi.python.org/pypi/python-jenkins/ 按语法调用即可... import je ...