抽空写段代码,简单测试成功,
请大侠们帮看看, 有没有更简练的方法,本菜鸟想学习,谢谢!
-- ------------------------------------------------------------------
-- Name : split_pac.sql
-- Author : 追寻
-- Created : 2010-12-29
-- purpose : 实现类似于Java语言中String的split方法
-- Srl No Date Name Description
-- ------ -------------- ----------- ------------------
-- 1 29/Dec/2010 追寻 Original Version
-- ------------------------------------------------------------------
CREATE OR REPLACE PACKAGE split_pac AS TYPE ArrayList IS TABLE OF VARCHAR2(500) INDEX BY BINARY_INTEGER;
PROCEDURE split_pro( inpString IN VARCHAR2,
splitChar IN CHAR,
outArr OUT ArrayList); END split_pac;
/
CREATE OR REPLACE PACKAGE BODY split_pac AS PROCEDURE split_pro( inpString IN VARCHAR2,
splitChar IN CHAR,
outArr OUT ArrayList) IS
v_tempString VARCHAR2(2000):= NULL;
-- 分割符
v_splitChar CHAR:= NULL;
v_outArr ArrayList;
v_splitCharCount NUMBER(4,0):= 0; v_Count NUMBER(4,0):= 0;
BEGIN
v_tempString := inpString;
v_splitChar := splitChar;
LOOP
--{
v_Count := v_Count +1;
-- INSTR(x, find_string [,start] [,occourrence])
-- 在 x 中查找字符串find_string,然后返回find_string的位置
-- start 指定该函数从该位置查找 (小于0时 ?)
-- occurrence 指定第几次出现的位置
IF (instr(v_tempString,v_splitChar) = 0) OR (v_tempString IS NULL) THEN
--{
v_outArr(v_Count) := v_tempString;
EXIT;
--}
END IF;
IF instr(v_tempString,v_splitChar) = 1 THEN
--{
-- SUBSTR(x, start [,length])
-- 返回x中的一个子字符串,
-- start 指定开始位置,当 start < 0 时,倒着数start个开始从左向右截取
-- length 指定子字符串的长度
v_tempString := substr(v_tempString,(length(v_splitChar)+1));
v_tempString := ltrim(v_tempString,v_splitChar);
--}
ELSE
--{
v_outArr(v_Count) := substr(v_tempString,1,(instr(v_tempString,v_splitChar)-1));
v_tempString := substr(v_tempString,(instr(v_tempString,v_splitChar)+length(v_splitChar)));
--}
END IF;
--}
END LOOP;
outArr := v_outArr;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(' exists errs ');
END split_pro;END split_pac;
/下面是测试代码:DECLARE
arrList dbscust.split_pac.ArrayList;
i NUMBER:=0;BEGIN
split_pac.split_pro('D:\work\2010-12-20','\',arrList);
LOOP
i:=i+1; IF arrList(i) IS NULL THEN
EXIT;
ELSE
dbms_output.put_line(arrList(i));
END IF;
END LOOP;END;再次表示感谢!
请大侠们帮看看, 有没有更简练的方法,本菜鸟想学习,谢谢!
-- ------------------------------------------------------------------
-- Name : split_pac.sql
-- Author : 追寻
-- Created : 2010-12-29
-- purpose : 实现类似于Java语言中String的split方法
-- Srl No Date Name Description
-- ------ -------------- ----------- ------------------
-- 1 29/Dec/2010 追寻 Original Version
-- ------------------------------------------------------------------
CREATE OR REPLACE PACKAGE split_pac AS TYPE ArrayList IS TABLE OF VARCHAR2(500) INDEX BY BINARY_INTEGER;
PROCEDURE split_pro( inpString IN VARCHAR2,
splitChar IN CHAR,
outArr OUT ArrayList); END split_pac;
/
CREATE OR REPLACE PACKAGE BODY split_pac AS PROCEDURE split_pro( inpString IN VARCHAR2,
splitChar IN CHAR,
outArr OUT ArrayList) IS
v_tempString VARCHAR2(2000):= NULL;
-- 分割符
v_splitChar CHAR:= NULL;
v_outArr ArrayList;
v_splitCharCount NUMBER(4,0):= 0; v_Count NUMBER(4,0):= 0;
BEGIN
v_tempString := inpString;
v_splitChar := splitChar;
LOOP
--{
v_Count := v_Count +1;
-- INSTR(x, find_string [,start] [,occourrence])
-- 在 x 中查找字符串find_string,然后返回find_string的位置
-- start 指定该函数从该位置查找 (小于0时 ?)
-- occurrence 指定第几次出现的位置
IF (instr(v_tempString,v_splitChar) = 0) OR (v_tempString IS NULL) THEN
--{
v_outArr(v_Count) := v_tempString;
EXIT;
--}
END IF;
IF instr(v_tempString,v_splitChar) = 1 THEN
--{
-- SUBSTR(x, start [,length])
-- 返回x中的一个子字符串,
-- start 指定开始位置,当 start < 0 时,倒着数start个开始从左向右截取
-- length 指定子字符串的长度
v_tempString := substr(v_tempString,(length(v_splitChar)+1));
v_tempString := ltrim(v_tempString,v_splitChar);
--}
ELSE
--{
v_outArr(v_Count) := substr(v_tempString,1,(instr(v_tempString,v_splitChar)-1));
v_tempString := substr(v_tempString,(instr(v_tempString,v_splitChar)+length(v_splitChar)));
--}
END IF;
--}
END LOOP;
outArr := v_outArr;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(' exists errs ');
END split_pro;END split_pac;
/下面是测试代码:DECLARE
arrList dbscust.split_pac.ArrayList;
i NUMBER:=0;BEGIN
split_pac.split_pro('D:\work\2010-12-20','\',arrList);
LOOP
i:=i+1; IF arrList(i) IS NULL THEN
EXIT;
ELSE
dbms_output.put_line(arrList(i));
END IF;
END LOOP;END;再次表示感谢!
解决方案 »
- select * from tbak where rownum <&dd order by 1 desc;
- 我的存储过程编译出问题
- date'2009-11-11'是什么语法
- 需要一个SQL排名
- 问一个sql的问题
- 安装oracle,字符集选缺省的,但不能输入中文!可修改否?如何修改?
- 在ORACLE中使用别名的问题
- 如何随机删除一个表中的若干条记录?
- 有关配置Oracle® Designer 6i
- 求助:ora-06502:pl/sql:数字或值错误:字符到数值的转换错误ora06512在line 14
- 高分求助:update语句;产品制定了统一零售价后,分销价格的销售价,最高/最低价必须和统一零售价一致,并更改状态。。
- 新手求一SQL解决方法
再不然自己写一个function啊,也没这么复杂吧
drop table Tab
Go
Create table Tab([Col1] int,[COl2] nvarchar(5))
Insert Tab
select 1,N'a,b,c' union all
select 2,N'd,e' union all
select 3,N'f'
Go--SQL2000用辅助表:
if object_id('Tempdb..#Num') is not null
drop table #Num
go
select top 100 ID=Identity(int,1,1) into #Num from syscolumns a,syscolumns b
Select
a.Col1,COl2=substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID)
from
Tab a,#Num b
where
charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','
--2000不使用辅助表
Select
a.Col1,COl2=substring(a.Col2,b.number,charindex(',',a.Col2+',',b.number)-b.number)
from
Tab a join master..spt_values b
ON B.type='p' AND B.number BETWEEN 1 AND LEN(A.col2)
where
substring(','+a.COl2,b.number,1)=','ms sql 里的处理方法 。我按照这个思路改的,
不过好像报错,呵呵。declare
str:='D:\work\2010-12-20'
begin
select substr(str,n,instr(str+'\','\',n)-n)
from (select rownum as n from tab)t
where substr(str,n,1)='\';
end
str:='D:\work\2010-12-20'
*第 2 行出现错误:
ORA-06550: 第 2 行, 第 5 列:
PLS-00103: 出现符号 "="在需要下列之一时: constant
exception
<an identifier> <a double-quoted delimited-identifier> table
LONG_ double ref char time timestamp interval date binary
national character nchar
from
(select 'D:\work\2010-12-20' as str from dual) a,
(select rownum as n from tab)t
where substr('\'||str,n,1)='\';COL
-------
D:
work
2010-12-20 这个可以
connect by rownum<=length('D:\work\2010-12-20')-length(replace('D:\work\2010-12-20','\\',''))+1
-------不要使用双斜杠
SQL>
SQL> select regexp_substr('D:\work\2010-12-20', '[^\]+', 1, rownum)
2 from dual
3 connect by rownum <= length('D:\work\2010-12-20') -
4 length(replace('D:\work\2010-12-20', '\', '')) + 1
5 ;REGEXP_SUBSTR('D:\WORK\2010-12
------------------------------------------------------------------------
D:
work
2010-12-20SQL>
谁说忽略了,只是他显示在最后一行而已。你如果要去掉为空的嵌套一下,在where里加上is not null
呵呵。。
testSQL>
SQL> select nvl(regexp_substr('D:\work\\2010-12-20', '[^\]+', 1, rownum),'this row is null')
2 from dual
3 connect by rownum <= length('D:\work\\2010-12-20') -
4 length(replace('D:\work\\2010-12-20', '\', '')) + 1
5 ;NVL(REGEXP_SUBSTR('D:\WORK\\20
----------------------------------------------------------------------------
D:
work
2010-12-20
this row is nullSQL>
--固定的格式的
scott@ORCL> create or replace package pack_arr
2 as
3 type arr_type is table of varchar2(100);
4 function fun_arr(c_str varchar2,c_sepstr varchar2) return arr_type pipelined;
5 end;
6 /程序包已创建。scott@ORCL> ed
已写入 file afiedt.buf 1 create or replace package body pack_arr
2 as
3 function fun_arr(c_str varchar2,c_sepstr varchar2) return arr_type pipelined
4 as
5 arr pack_arr.arr_type:=pack_arr.arr_type();
6 str varchar2(1000);
7 cnt number;
8 begin
9 cnt:=length(c_str)-length(replace(c_str,c_sepstr,''))+1;
10 str:=c_sepstr||c_str||c_sepstr;
11 for i in 1..cnt loop
12 arr.extend;
13 select
14 substr(str,instr(str,c_sepstr,1,i)+1,abs(instr(str,c_sepstr,1,i+1)-instr(str,c_sepstr,1,i)-1))
15 into arr(i) from dual;
16 pipe row(arr(i));
17 end loop;
18 return;
19 end fun_arr;
20* end;
scott@ORCL> /程序包体已创建。scott@ORCL> select * from table(pack_arr.fun_arr('D:\work\2010-12-20','\'))
2 /COLUMN_VALUE
--------------------------------------------------------------------------------
D:
work
2010-12-20
create or replace function split(p_list varchar2,p_sep varchar2 := ',') return type_split pipelined
IS
l_idx pls_integer;
v_list varchar2(4000) := p_list; begin
loop
l_idx := instr(v_list,p_sep);
if l_idx > 0 then
pipe row(substr(v_list,1,l_idx-1));
v_list := substr(v_list,l_idx+length(p_sep));
else
pipe row(v_list);
exit;
end if; end loop;
return;
end split;
regexp_substr() 里 1的位置是start 即指定开始位置,rownum 是指第几次匹配的位置,
问题如下:SELECT nvl(regexp_substr('D:\work\2010-12-20\', '[^\]+',1, 3),'null')
FROM dual
-- 结果是: 2010-12-20 而不是: D:\work\2010-12-20
-- 说明: 3 是指第三次匹配到'[^\]+'的末尾的位置,而1是指指第三次匹配到'[^\]+'的开头的位置的位置-- 按上面的推断下面的结果是D后面的冒号
SELECT nvl(regexp_substr('D:\work\2010-12-20\', '[^\]+',2, 1),'null')
FROM dual
--对的,结果是D后面的冒号
-- 如果上面的推断没错的话, 将start 位置改为2,结果应该是: 010-12-20
SELECT nvl(regexp_substr('D:\work\2010-12-20\', '[^\]+',2, 3),'null')
FROM dual
-- 但结果也是:2010-12-20
-- 如果将start 位置改为3的话,结果却变成了: null为什么会这样?:[ ] Bracket expression for specifying a matching list that should match any
one of the expressions represented in the list. A nonmatching list
expression begins with a circumflex (^) and specifies a list that matches
any character except for the expressions represented in the list.