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

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

要实现这个目的,第一是要从数据库里把相应的字段取出来, 第二是要写一个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. SQL Server2012连接SQL Server2000完美解决方案

    在SQL Server2012中连接其他SQL Server数据库时可以使用以下代码: exec sp_addlinkedserver 'ITSV', '', 'SQLOLEDB', 'serveri ...

  2. [C#学习]在多线程中如何调用Winform[转]

    问题的产生: 我的WinForm程序中有一个用于更新主窗口的工作线程(worker thread),但文档中却提示我不能在多线程中调用这个form(为什么?),而事实上我在调用时程序常常会崩掉.请问如 ...

  3. CSS一级导航-天蓝色(带阴影)

    一款亮丽的导航,能给网站一个画龙点睛的作用.导航在指引用户搜寻内容时,还能改变用户浏览网站的心情,浏览网站也像一场旅行,有创意的导航栏让用户欣赏起来也会更加愉悦,增加对网站的兴趣. 本人不擅长美工制作 ...

  4. Ext.Array 方法

    1. Ext.Array.clean(arr); 过滤数组中的空元素 var arr = [1,"",2,"",3]; Ext.clean(arr); // [ ...

  5. Java 不定长度参数

    在调用某个方法时,若是方法的参数个数事先无法确定该如何处理?例如System.out.printf()方法中并没有办法事先决定要给的参数个数,像是: ? 1 2 3 System.out.printf ...

  6. php 获取客户端IP地址

    /** * 获取真实IP地址 */ /* 在PHP中getenv(参数)函数是一个用于获取环境变量的函数,根据提供不同的参数可以获取不同的环境变量, getenv("REMOTE_ADDR& ...

  7. 工程经济学economics of project summarize

    什么是财务杠杆效应 财务杠杆效应是指由于固定费用的存在而导致的,当某一财务变量以较小幅度变动时.另一相关变量会以较大幅度变动的现象.也就是指在企业运用负债筹资方式(如银行借款.发行债券)时所产生的普通 ...

  8. 获取网络图片的大小 改变 图片色值 灰度什么的方法集合-b

    直接上代码了 头文件 // 图片处理 0 半灰色  1 灰度   2 深棕色    3 反色 +(UIImage*)imageWithImage:(UIImage*)image grayLevelTy ...

  9. 【Java】Java Platform

    The Java platform has two components: The Java Virtual Machine The Java Application Programming Inte ...

  10. python手记(30)

    #!/usr/bin/env python #-*- coding: utf-8 -*- import cv2 import numpy as np fn="test3.png" ...