- 浏览: 19102 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
文章分类
最新评论
-
zhaojj19870824:
公司都挺好,前一个看你在哪个部门了。我在那个不怎么好。
IBM ISSC和深圳日立环球存储 哪个好一点. -
叶智光:
IBM gdc我曾经呆过,网上很多人骂,但是我个人经历觉得是个 ...
IBM ISSC和深圳日立环球存储 哪个好一点. -
workman93:
小徐是谁阿?不会是徐志摩吧?
occasional -
-+lizzy+-:
看到一个帖子里面小徐的诗,正好在看英语,就想知道我用英语会怎么 ...
occasional -
workman93:
呵呵。看不懂。最近还很忙么?
occasional
Oracle 自定义TYPE 的几种用法
Oracle中的类型有很多种,主要可以分为以下几类:
1、字符串类型。如:char、nchar、varchar2、nvarchar2。
2、数值类型。如:int、number(p,s)、integer、smallint。
3、日期类型。如:date、interval、timestamp。
4、PL/SQL类型。如:pls_integer、binary_integer、binary_double(10g)、binary_float(10g)、boolean。plsql类型是不能在sql环境中使用的,比如建表时。
5、自定义类型。
下面简单的枚举下常用的几种自定义类型。
1、子类型。
这种类型最简单,类似类型的一个别名,主要是为了对常用的一些类型简单化,它基于原始的某个类型。如:
有些应用会经常用到一些货币类型:number(16,2)。如果在全局范围各自定义这种类型,一旦需要修改该类型的精度,则需要一个个地修改。
那如何实现定义的全局化呢?于是就引出了子类型:
subtype cc_num is number(16,2);
这样就很方便地解决了上述的麻烦。
2、普通类型
如:
create or replace type typ_calendar as object(
年 varchar2(8),
月 varchar2(8),
星期日 varchar2(8),
星期一 varchar2(8),
星期二 varchar2(8),
星期三 varchar2(8),
星期四 varchar2(8),
星期五 varchar2(8),
星期六 varchar2(8),
本月最后一日 varchar2(2)
);
这种类型可以在表结构定义的时候使用:
create table tcalendar of typ_calendar;
插入数据测试:
SQL> insert into tcalendar
2 select typ_calendar('2010','05','1','2','3','4','5','6','7','31') from dual
3 /
注意:插入的数据需要用typ_calendar进行转换。
1 row inserted
--查看结果
SQL> select * from tcalendar;
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 05 1 2 3 4 5 6 7 31
3、带成员函数的类型体(type body)
这种类型包含了对类型中数据的内部处理,调用该类型时,可将处理后的数据返回给调用方。
对上面的例子进行扩展。要求给当天加上特殊标识(【】)来突出显示。
首先,在typ_calendar中增加一个成员函数声明:
create or replace type typ_calendar as object(
年 varchar2(8),
月 varchar2(8),
星期日 varchar2(8),
星期一 varchar2(8),
星期二 varchar2(8),
星期三 varchar2(8),
星期四 varchar2(8),
星期五 varchar2(8),
星期六 varchar2(8),
本月最后一日 varchar2(2),
member function format(
curday date := sysdate,
fmtlen pls_integer := 8
)return typ_calendar
)
然后,创建一个type body,在type body中实现该成员函数:
create or replace type body typ_calendar as
member function format(
curday date := sysdate,
fmtlen pls_integer := 8
) return typ_calendar as
v_return typ_calendar := typ_calendar('','','','','','','','','','');
v_dd varchar2(2) := to_char(curday, 'dd');
function fmt(
fmtstr varchar2
)return varchar2 as
begin
return lpad(fmtstr, fmtlen, ' ');
end fmt;
begin
v_return.年 := 年;
v_return.月 := 月;
v_return.星期日 := fmt(星期日);
v_return.星期一 := fmt(星期一);
v_return.星期二 := fmt(星期二);
v_return.星期三 := fmt(星期三);
v_return.星期四 := fmt(星期四);
v_return.星期五 := fmt(星期五);
v_return.星期六 := fmt(星期六);
v_return.本月最后一日 := 本月最后一日;
if (年 || lpad(月, 2, '0') = to_char(curday, 'yyyymm')) then
case v_dd
when 星期日 then
v_return.星期日 := fmt('【' || 星期日 || '】');
when 星期一 then
v_return.星期一 := fmt('【' || 星期一 || '】');
when 星期二 then
v_return.星期二 := fmt('【' || 星期二 || '】');
when 星期三 then
v_return.星期三 := fmt('【' || 星期三 || '】');
when 星期四 then
v_return.星期四 := fmt('【' || 星期四 || '】');
when 星期五 then
v_return.星期五 := fmt('【' || 星期五 || '】');
when 星期六 then
v_return.星期六 := fmt('【' || 星期六 || '】');
else null;
end case;
end if;
return v_return;
end format;
end;
插入测试数据:
SQL> insert into tcalendar
2 select typ_calendar('2010','05','1','2','3','4','5','6','7','31') from dual
3 /
1 row inserted
SQL> insert into tcalendar
2 select typ_calendar('2010','05','1','2','3','4','5','6','7','31').format() from dual
3 /
1 row inserted
SQL> insert into tcalendar
2 select typ_calendar('2010','05','11','12','13','14','15','16','17','31').format() from dual
3 /
1 row inserted
SQL> select * from tcalendar;
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 05 1 2 3 4 5 6 7 31
2010 05 1 2 3 4 5 6 7 31
2010 05 11 【12】 13 14 15 16 17 31
可以看到数据已经居中处理了,并且到了第三条已经可以突出显示当前日期了。
在这里type 中的成员函数(member function)和静态函数(static function)的区别有必要说明一下:
成员函数有隐含参数self,即自身类型,可以在执行的时候引用当前的数据并对数据进行操作。它的调用可以如下:object_expression.method()
静态函数没有该隐含参数。它的调用如下:type_name.method();
举个例子:
首先,创建一个带静态函数声明的类型头:
SQL> create or replace type typ_col as object(
2 col_name varchar2(30),
3 tab_name varchar2(30),
4 static function to_upper return typ_col
5 )
6 /
Type created
然后创建类型体:
SQL>
SQL> create or replace type body typ_col as
2 static function to_upper
3 return typ_col as
4 begin
5 return typ_col(upper(col_name), upper(tab_name));
6 end to_upper;
7 end;
8 /
Warning: Type body created with compilation errors
SQL> show errors
Errors for TYPE BODY LYON.TYP_COL:
LINE/COL ERROR
-------- ---------------------------------------------------
5/30 PLS-00588: 非限定实例属性引用只允许在成员方法中使用
5/9 PL/SQL: Statement ignored
错误信息表明,实例属性只能在成员方法中使用。这里隐去了self的调用,其实:
typ_col(upper(col_name), upper(tab_name));
等价于:
typ_col(upper(self.col_name), upper(self.tab_name));
而这种方式的使用根据前面的定义,只能在成员函数中实现:
SQL> create or replace type typ_col as object(
2 col_name varchar2(30),
3 tab_name varchar2(30),
4 member function to_upper return typ_col
5 )
6 /
Type created
SQL>
SQL> create or replace type body typ_col as
2 member function to_upper
3 return typ_col as
4 begin
5 return typ_col(upper(self.col_name), upper(self.tab_name));
6 end to_upper;
7 end;
8 /
Type body created
那两者调用上又有什么差别呢?
按照前面的定义,静态函数的用法是type_name.method(),所以有:
SQL> select typ_col.to_lower(x).tab_name, typ_col.to_lower(x).col_name from tcol
2 /
TYP_COL.TO_LOWER(X).TAB_NAME TYP_COL.TO_LOWER(X).COL_NAME
------------------------------ ------------------------------
ipseg_int_db_tmp start_ip
ipseg_int_db_tmp end_ip
ipseg_int_db_tmp area_code
px_city city_id
px_city city_name
px_city province_id
px_citygdp gdp_cycle_id
px_citygdp city_id
px_citygdp gdp
px_citygdp province_id
10 rows selected
SQL> select typ_col(column_name, table_name).to_upper().tab_name,
2 typ_col(column_name, table_name).to_upper().col_name
3 from user_tab_columns t
4 where rownum <= 10;
TYP_COL(COLUMN_NAME,TABLE_NAME TYP_COL(COLUMN_NAME,TABLE_NAME
------------------------------ ------------------------------
DEMO X
IPSEG_INT_DB_TMP START_IP
IPSEG_INT_DB_TMP END_IP
IPSEG_INT_DB_TMP AREA_CODE
PX_CITY CITY_ID
PX_CITY CITY_NAME
PX_CITY PROVINCE_ID
PX_CITYGDP GDP_CYCLE_ID
PX_CITYGDP CITY_ID
PX_CITYGDP GDP
10 rows selected
也就是说,静态函数主要是用于处理并返回外部数据的,而成员函数是用于处理并返回内部数据的。
然后可以在函数中使用该类型,下面是一个显示日历的函数,并调用类型的成员函数对结果做了格式化:
create or replace function show_calendar(
v_yermonth varchar2 := to_char(sysdate, 'yyyymm'))
return tbl_calendar as
v_cal tbl_calendar;
v_seg pls_integer := 6;
v_len pls_integer := 8;
v_yer varchar2(4) := substr(v_yermonth, 1, 4);
v_mon varchar2(2) := lpad(substr(v_yermonth, 5, 2), 2, '0');
v_ini date := to_date(v_yermonth || '01', 'yyyymmdd');
begin
select typ_calendar(v_yer, v_mon,
case when rn >= wkn - 1 and rn - wkn + 2 <= mxdays
then rn - wkn + 2 end,
case when rn >= wkn - 2 and rn - wkn + 3 <= mxdays
then rn - wkn + 3 end,
case when rn >= wkn - 3 and rn - wkn + 4 <= mxdays
then rn - wkn + 4 end,
case when rn >= wkn - 4 and rn - wkn + 5 <= mxdays
then rn - wkn + 5 end,
case when rn >= wkn - 5 and rn - wkn + 6 <= mxdays
then rn - wkn + 6 end,
case when rn >= wkn - 6 and rn - wkn + 7 <= mxdays
then rn - wkn + 7 end,
case when rn >= wkn - 7 and rn - wkn + 8 <= mxdays
then rn - wkn + v_len end,
mxdays).format()
bulk collect into v_cal
from (select (rownum - 1)*7 rn,
to_number(to_char(trunc(v_ini, 'mm'), 'd')) wkn,
to_number(to_char(last_day(v_ini), 'dd')) mxdays
from dual
connect by rownum <= v_seg) b
where rn - wkn + 2 <= mxdays; --过滤空行
return v_cal;
end show_calendar;
获得当前月的日历:
SQL> select * from table(show_calendar);
/
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 05 1 31
2010 05 2 3 4 5 6 7 8 31
2010 05 9 10 11 【12】 13 14 15 31
2010 05 16 17 18 19 20 21 22 31
2010 05 23 24 25 26 27 28 29 31
2010 05 30 31 31
6 rows selected
获取指定月份的日历:
SQL> select * from table(show_calendar('201001'));
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 01 1 2 31
2010 01 3 4 5 6 7 8 9 31
2010 01 10 11 12 13 14 15 16 31
2010 01 17 18 19 20 21 22 23 31
2010 01 24 25 26 27 28 29 30 31
2010 01 31 31
6 rows selected
显示多个月的日历:
SQL> select b.*
2 from (select to_char(add_months(date'1998-01-01', rownum-1), 'yyyymm') c from dual connect by rownum <= 10) a,
3 table(show_calendar(to_char(a.c))) b
4 /
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
1998 01 1 2 3 31
1998 01 4 5 6 7 8 9 10 31
1998 01 11 12 13 14 15 16 17 31
1998 01 18 19 20 21 22 23 24 31
1998 01 25 26 27 28 29 30 31 31
1998 02 1 2 3 4 5 6 7 28
1998 02 8 9 10 11 12 13 14 28
1998 02 15 16 17 18 19 20 21 28
...............
1998 09 1 2 3 4 5 30
1998 09 6 7 8 9 10 11 12 30
1998 09 13 14 15 16 17 18 19 30
1998 09 20 21 22 23 24 25 26 30
1998 09 27 28 29 30 30
1998 10 1 2 3 31
1998 10 4 5 6 7 8 9 10 31
1998 10 11 12 13 14 15 16 17 31
1998 10 18 19 20 21 22 23 24 31
1998 10 25 26 27 28 29 30 31 31
51 rows selected
上面是一个特殊的table函数使用方法。
即将a表中构造的月份,作为参数传入到table函数中的show_calendar函数中,然后show_calendar函数根据指定的月份返回
该月的日历。实现了获取多个月日历的要求。
自定义type的一个限制是不能使用rowid类型:
SQL> create or replace type typ_rowid as object(rid urowid);
2 /
Warning: Type created with compilation errors
SQL> show errors;
Errors for TYPE CUSTOMER21.TYP_ROWID:
LINE/COL ERROR
-------- ---------------------------------------------------
1/30 PLS-00530: 为此对象类型属性使用了非法类型: UROWID。
其他的特殊使用还有自定义聚集函数,典型的例子就是字符串相加的问题。
我们知道,对数字列的相加很简单,直接求sum即可。但是如何对字符列进行相加呢?
如:
SQL> with tmp as (
2 select '1' c from dual union all
3 select '2' c from dual union all
4 select '3' c from dual union all
5 select '4' c from dual)
6 select * from tmp
7 /
C
-
1
2
3
4
1,2,3,4要合并为1->2->3->4,该如何实现?
一个办法是用层级查询来实现(用sys_connect_by_path即可)。
另外,10g下,还可以用wm_sys.wm_concat函数来实现。
还有就是自定义聚集函数了。自定义聚集函数首先要定义一个类型,在类型中调用了Oracle内部实现的几个接口函数:
CREATE OR REPLACE TYPE "TYP_STRCAT" as object
(
strsum varchar2(4000),
strcnt number,
strdelimit varchar2(10),
static function ODCIAggregateInitialize(
actx in out typ_strcat)
return number,
member function ODCIAggregateIterate(
self in out typ_strcat,
val in varchar2)
return number,
member function ODCIAggregateTerminate(
self in typ_strcat,
returnvalue out varchar2,
flags in number)
return number,
member function ODCIAggregateMerge(
self in out typ_strcat,
ctx2 typ_strcat)
return number
)
CREATE OR REPLACE TYPE BODY "TYP_STRCAT" as
static function ODCIAggregateInitialize(actx in out typ_strcat)
return number as
begin
actx := typ_strcat(null, 1, ',');
return ODCICONST.Success;
end;
member function ODCIAggregateIterate(self in out typ_strcat,
val in varchar2) return number as
begin
self.strsum := self.strsum || strdelimit || val;
self.strcnt := self.strcnt + 1;
return ODCICONST.Success;
end;
member function ODCIAggregateTerminate(self in typ_strcat,
returnvalue out varchar2,
flags in number) return number as
begin
returnvalue := ltrim(self.strsum, strdelimit);
return Odciconst.Success;
end;
member function ODCIAggregateMerge(self in out typ_strcat,
ctx2 in typ_strcat) return number as
begin
self.strsum := ctx2.strsum || self.strsum;
return Odciconst.Success;
end;
end;
然后创建函数:
CREATE OR REPLACE FUNCTION "SSUM" (p_str varchar2)
return varchar2
/*parallel_enable*/ aggregate using typ_strcat;
然后,就可以使用字符串相加的功能了:
SQL> with tmp as (
2 select '1' c from dual union all
3 select '2' c from dual union all
4 select '3' c from dual union all
5 select '4' c from dual)
6 select replace(ssum(c), ',', '->') from tmp
7 /
REPLACE(SSUM(C),',','->')
--------------------------------------------------------------------------------
1->2->3->4
4.表类型
这种类型类似于一个数组类型,可以申明一维或多维。
比如说,创建一个元素长度为4000的字符串数组,则有:
create or replace type tbl_varchar2 as table of varchar2(4000)
然后可以如下使用该类型:
SQL> select * from table(tbl_varchar2('1','1','3','4','5','6'));
COLUMN_VALUE
--------------------------------------------------------------------------------
1
1
3
4
5
6
6 rows selected
如果要获取多字段的,则可以取上面例子:
SQL> select *
2 from table(tbl_calendar(
3 typ_calendar('2008','2','3','4','5','6','7','8','9','28'),
4 typ_calendar('2009','12','13','4','5','6','7','8','9','31'),
5 typ_calendar('2010','12','13','4','5','6','7','8','9','31')));
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2008 2 3 4 5 6 7 8 9 28
2009 12 13 4 5 6 7 8 9 31
2010 12 13 4 5 6 7 8 9 31
以上使用的类型都基于schema级别,如果是定义在包、函数、过程等这些结构里是不能给table函数使用的。
这种类型可以使用在管道函数中(pipelined function)。也可以存放中间处理的数据,类似于临时表的作用,但是是存放在内存中的。
Oracle中的类型有很多种,主要可以分为以下几类:
1、字符串类型。如:char、nchar、varchar2、nvarchar2。
2、数值类型。如:int、number(p,s)、integer、smallint。
3、日期类型。如:date、interval、timestamp。
4、PL/SQL类型。如:pls_integer、binary_integer、binary_double(10g)、binary_float(10g)、boolean。plsql类型是不能在sql环境中使用的,比如建表时。
5、自定义类型。
下面简单的枚举下常用的几种自定义类型。
1、子类型。
这种类型最简单,类似类型的一个别名,主要是为了对常用的一些类型简单化,它基于原始的某个类型。如:
有些应用会经常用到一些货币类型:number(16,2)。如果在全局范围各自定义这种类型,一旦需要修改该类型的精度,则需要一个个地修改。
那如何实现定义的全局化呢?于是就引出了子类型:
subtype cc_num is number(16,2);
这样就很方便地解决了上述的麻烦。
2、普通类型
如:
create or replace type typ_calendar as object(
年 varchar2(8),
月 varchar2(8),
星期日 varchar2(8),
星期一 varchar2(8),
星期二 varchar2(8),
星期三 varchar2(8),
星期四 varchar2(8),
星期五 varchar2(8),
星期六 varchar2(8),
本月最后一日 varchar2(2)
);
这种类型可以在表结构定义的时候使用:
create table tcalendar of typ_calendar;
插入数据测试:
SQL> insert into tcalendar
2 select typ_calendar('2010','05','1','2','3','4','5','6','7','31') from dual
3 /
注意:插入的数据需要用typ_calendar进行转换。
1 row inserted
--查看结果
SQL> select * from tcalendar;
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 05 1 2 3 4 5 6 7 31
3、带成员函数的类型体(type body)
这种类型包含了对类型中数据的内部处理,调用该类型时,可将处理后的数据返回给调用方。
对上面的例子进行扩展。要求给当天加上特殊标识(【】)来突出显示。
首先,在typ_calendar中增加一个成员函数声明:
create or replace type typ_calendar as object(
年 varchar2(8),
月 varchar2(8),
星期日 varchar2(8),
星期一 varchar2(8),
星期二 varchar2(8),
星期三 varchar2(8),
星期四 varchar2(8),
星期五 varchar2(8),
星期六 varchar2(8),
本月最后一日 varchar2(2),
member function format(
curday date := sysdate,
fmtlen pls_integer := 8
)return typ_calendar
)
然后,创建一个type body,在type body中实现该成员函数:
create or replace type body typ_calendar as
member function format(
curday date := sysdate,
fmtlen pls_integer := 8
) return typ_calendar as
v_return typ_calendar := typ_calendar('','','','','','','','','','');
v_dd varchar2(2) := to_char(curday, 'dd');
function fmt(
fmtstr varchar2
)return varchar2 as
begin
return lpad(fmtstr, fmtlen, ' ');
end fmt;
begin
v_return.年 := 年;
v_return.月 := 月;
v_return.星期日 := fmt(星期日);
v_return.星期一 := fmt(星期一);
v_return.星期二 := fmt(星期二);
v_return.星期三 := fmt(星期三);
v_return.星期四 := fmt(星期四);
v_return.星期五 := fmt(星期五);
v_return.星期六 := fmt(星期六);
v_return.本月最后一日 := 本月最后一日;
if (年 || lpad(月, 2, '0') = to_char(curday, 'yyyymm')) then
case v_dd
when 星期日 then
v_return.星期日 := fmt('【' || 星期日 || '】');
when 星期一 then
v_return.星期一 := fmt('【' || 星期一 || '】');
when 星期二 then
v_return.星期二 := fmt('【' || 星期二 || '】');
when 星期三 then
v_return.星期三 := fmt('【' || 星期三 || '】');
when 星期四 then
v_return.星期四 := fmt('【' || 星期四 || '】');
when 星期五 then
v_return.星期五 := fmt('【' || 星期五 || '】');
when 星期六 then
v_return.星期六 := fmt('【' || 星期六 || '】');
else null;
end case;
end if;
return v_return;
end format;
end;
插入测试数据:
SQL> insert into tcalendar
2 select typ_calendar('2010','05','1','2','3','4','5','6','7','31') from dual
3 /
1 row inserted
SQL> insert into tcalendar
2 select typ_calendar('2010','05','1','2','3','4','5','6','7','31').format() from dual
3 /
1 row inserted
SQL> insert into tcalendar
2 select typ_calendar('2010','05','11','12','13','14','15','16','17','31').format() from dual
3 /
1 row inserted
SQL> select * from tcalendar;
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 05 1 2 3 4 5 6 7 31
2010 05 1 2 3 4 5 6 7 31
2010 05 11 【12】 13 14 15 16 17 31
可以看到数据已经居中处理了,并且到了第三条已经可以突出显示当前日期了。
在这里type 中的成员函数(member function)和静态函数(static function)的区别有必要说明一下:
成员函数有隐含参数self,即自身类型,可以在执行的时候引用当前的数据并对数据进行操作。它的调用可以如下:object_expression.method()
静态函数没有该隐含参数。它的调用如下:type_name.method();
举个例子:
首先,创建一个带静态函数声明的类型头:
SQL> create or replace type typ_col as object(
2 col_name varchar2(30),
3 tab_name varchar2(30),
4 static function to_upper return typ_col
5 )
6 /
Type created
然后创建类型体:
SQL>
SQL> create or replace type body typ_col as
2 static function to_upper
3 return typ_col as
4 begin
5 return typ_col(upper(col_name), upper(tab_name));
6 end to_upper;
7 end;
8 /
Warning: Type body created with compilation errors
SQL> show errors
Errors for TYPE BODY LYON.TYP_COL:
LINE/COL ERROR
-------- ---------------------------------------------------
5/30 PLS-00588: 非限定实例属性引用只允许在成员方法中使用
5/9 PL/SQL: Statement ignored
错误信息表明,实例属性只能在成员方法中使用。这里隐去了self的调用,其实:
typ_col(upper(col_name), upper(tab_name));
等价于:
typ_col(upper(self.col_name), upper(self.tab_name));
而这种方式的使用根据前面的定义,只能在成员函数中实现:
SQL> create or replace type typ_col as object(
2 col_name varchar2(30),
3 tab_name varchar2(30),
4 member function to_upper return typ_col
5 )
6 /
Type created
SQL>
SQL> create or replace type body typ_col as
2 member function to_upper
3 return typ_col as
4 begin
5 return typ_col(upper(self.col_name), upper(self.tab_name));
6 end to_upper;
7 end;
8 /
Type body created
那两者调用上又有什么差别呢?
按照前面的定义,静态函数的用法是type_name.method(),所以有:
SQL> select typ_col.to_lower(x).tab_name, typ_col.to_lower(x).col_name from tcol
2 /
TYP_COL.TO_LOWER(X).TAB_NAME TYP_COL.TO_LOWER(X).COL_NAME
------------------------------ ------------------------------
ipseg_int_db_tmp start_ip
ipseg_int_db_tmp end_ip
ipseg_int_db_tmp area_code
px_city city_id
px_city city_name
px_city province_id
px_citygdp gdp_cycle_id
px_citygdp city_id
px_citygdp gdp
px_citygdp province_id
10 rows selected
SQL> select typ_col(column_name, table_name).to_upper().tab_name,
2 typ_col(column_name, table_name).to_upper().col_name
3 from user_tab_columns t
4 where rownum <= 10;
TYP_COL(COLUMN_NAME,TABLE_NAME TYP_COL(COLUMN_NAME,TABLE_NAME
------------------------------ ------------------------------
DEMO X
IPSEG_INT_DB_TMP START_IP
IPSEG_INT_DB_TMP END_IP
IPSEG_INT_DB_TMP AREA_CODE
PX_CITY CITY_ID
PX_CITY CITY_NAME
PX_CITY PROVINCE_ID
PX_CITYGDP GDP_CYCLE_ID
PX_CITYGDP CITY_ID
PX_CITYGDP GDP
10 rows selected
也就是说,静态函数主要是用于处理并返回外部数据的,而成员函数是用于处理并返回内部数据的。
然后可以在函数中使用该类型,下面是一个显示日历的函数,并调用类型的成员函数对结果做了格式化:
create or replace function show_calendar(
v_yermonth varchar2 := to_char(sysdate, 'yyyymm'))
return tbl_calendar as
v_cal tbl_calendar;
v_seg pls_integer := 6;
v_len pls_integer := 8;
v_yer varchar2(4) := substr(v_yermonth, 1, 4);
v_mon varchar2(2) := lpad(substr(v_yermonth, 5, 2), 2, '0');
v_ini date := to_date(v_yermonth || '01', 'yyyymmdd');
begin
select typ_calendar(v_yer, v_mon,
case when rn >= wkn - 1 and rn - wkn + 2 <= mxdays
then rn - wkn + 2 end,
case when rn >= wkn - 2 and rn - wkn + 3 <= mxdays
then rn - wkn + 3 end,
case when rn >= wkn - 3 and rn - wkn + 4 <= mxdays
then rn - wkn + 4 end,
case when rn >= wkn - 4 and rn - wkn + 5 <= mxdays
then rn - wkn + 5 end,
case when rn >= wkn - 5 and rn - wkn + 6 <= mxdays
then rn - wkn + 6 end,
case when rn >= wkn - 6 and rn - wkn + 7 <= mxdays
then rn - wkn + 7 end,
case when rn >= wkn - 7 and rn - wkn + 8 <= mxdays
then rn - wkn + v_len end,
mxdays).format()
bulk collect into v_cal
from (select (rownum - 1)*7 rn,
to_number(to_char(trunc(v_ini, 'mm'), 'd')) wkn,
to_number(to_char(last_day(v_ini), 'dd')) mxdays
from dual
connect by rownum <= v_seg) b
where rn - wkn + 2 <= mxdays; --过滤空行
return v_cal;
end show_calendar;
获得当前月的日历:
SQL> select * from table(show_calendar);
/
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 05 1 31
2010 05 2 3 4 5 6 7 8 31
2010 05 9 10 11 【12】 13 14 15 31
2010 05 16 17 18 19 20 21 22 31
2010 05 23 24 25 26 27 28 29 31
2010 05 30 31 31
6 rows selected
获取指定月份的日历:
SQL> select * from table(show_calendar('201001'));
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2010 01 1 2 31
2010 01 3 4 5 6 7 8 9 31
2010 01 10 11 12 13 14 15 16 31
2010 01 17 18 19 20 21 22 23 31
2010 01 24 25 26 27 28 29 30 31
2010 01 31 31
6 rows selected
显示多个月的日历:
SQL> select b.*
2 from (select to_char(add_months(date'1998-01-01', rownum-1), 'yyyymm') c from dual connect by rownum <= 10) a,
3 table(show_calendar(to_char(a.c))) b
4 /
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
1998 01 1 2 3 31
1998 01 4 5 6 7 8 9 10 31
1998 01 11 12 13 14 15 16 17 31
1998 01 18 19 20 21 22 23 24 31
1998 01 25 26 27 28 29 30 31 31
1998 02 1 2 3 4 5 6 7 28
1998 02 8 9 10 11 12 13 14 28
1998 02 15 16 17 18 19 20 21 28
...............
1998 09 1 2 3 4 5 30
1998 09 6 7 8 9 10 11 12 30
1998 09 13 14 15 16 17 18 19 30
1998 09 20 21 22 23 24 25 26 30
1998 09 27 28 29 30 30
1998 10 1 2 3 31
1998 10 4 5 6 7 8 9 10 31
1998 10 11 12 13 14 15 16 17 31
1998 10 18 19 20 21 22 23 24 31
1998 10 25 26 27 28 29 30 31 31
51 rows selected
上面是一个特殊的table函数使用方法。
即将a表中构造的月份,作为参数传入到table函数中的show_calendar函数中,然后show_calendar函数根据指定的月份返回
该月的日历。实现了获取多个月日历的要求。
自定义type的一个限制是不能使用rowid类型:
SQL> create or replace type typ_rowid as object(rid urowid);
2 /
Warning: Type created with compilation errors
SQL> show errors;
Errors for TYPE CUSTOMER21.TYP_ROWID:
LINE/COL ERROR
-------- ---------------------------------------------------
1/30 PLS-00530: 为此对象类型属性使用了非法类型: UROWID。
其他的特殊使用还有自定义聚集函数,典型的例子就是字符串相加的问题。
我们知道,对数字列的相加很简单,直接求sum即可。但是如何对字符列进行相加呢?
如:
SQL> with tmp as (
2 select '1' c from dual union all
3 select '2' c from dual union all
4 select '3' c from dual union all
5 select '4' c from dual)
6 select * from tmp
7 /
C
-
1
2
3
4
1,2,3,4要合并为1->2->3->4,该如何实现?
一个办法是用层级查询来实现(用sys_connect_by_path即可)。
另外,10g下,还可以用wm_sys.wm_concat函数来实现。
还有就是自定义聚集函数了。自定义聚集函数首先要定义一个类型,在类型中调用了Oracle内部实现的几个接口函数:
CREATE OR REPLACE TYPE "TYP_STRCAT" as object
(
strsum varchar2(4000),
strcnt number,
strdelimit varchar2(10),
static function ODCIAggregateInitialize(
actx in out typ_strcat)
return number,
member function ODCIAggregateIterate(
self in out typ_strcat,
val in varchar2)
return number,
member function ODCIAggregateTerminate(
self in typ_strcat,
returnvalue out varchar2,
flags in number)
return number,
member function ODCIAggregateMerge(
self in out typ_strcat,
ctx2 typ_strcat)
return number
)
CREATE OR REPLACE TYPE BODY "TYP_STRCAT" as
static function ODCIAggregateInitialize(actx in out typ_strcat)
return number as
begin
actx := typ_strcat(null, 1, ',');
return ODCICONST.Success;
end;
member function ODCIAggregateIterate(self in out typ_strcat,
val in varchar2) return number as
begin
self.strsum := self.strsum || strdelimit || val;
self.strcnt := self.strcnt + 1;
return ODCICONST.Success;
end;
member function ODCIAggregateTerminate(self in typ_strcat,
returnvalue out varchar2,
flags in number) return number as
begin
returnvalue := ltrim(self.strsum, strdelimit);
return Odciconst.Success;
end;
member function ODCIAggregateMerge(self in out typ_strcat,
ctx2 in typ_strcat) return number as
begin
self.strsum := ctx2.strsum || self.strsum;
return Odciconst.Success;
end;
end;
然后创建函数:
CREATE OR REPLACE FUNCTION "SSUM" (p_str varchar2)
return varchar2
/*parallel_enable*/ aggregate using typ_strcat;
然后,就可以使用字符串相加的功能了:
SQL> with tmp as (
2 select '1' c from dual union all
3 select '2' c from dual union all
4 select '3' c from dual union all
5 select '4' c from dual)
6 select replace(ssum(c), ',', '->') from tmp
7 /
REPLACE(SSUM(C),',','->')
--------------------------------------------------------------------------------
1->2->3->4
4.表类型
这种类型类似于一个数组类型,可以申明一维或多维。
比如说,创建一个元素长度为4000的字符串数组,则有:
create or replace type tbl_varchar2 as table of varchar2(4000)
然后可以如下使用该类型:
SQL> select * from table(tbl_varchar2('1','1','3','4','5','6'));
COLUMN_VALUE
--------------------------------------------------------------------------------
1
1
3
4
5
6
6 rows selected
如果要获取多字段的,则可以取上面例子:
SQL> select *
2 from table(tbl_calendar(
3 typ_calendar('2008','2','3','4','5','6','7','8','9','28'),
4 typ_calendar('2009','12','13','4','5','6','7','8','9','31'),
5 typ_calendar('2010','12','13','4','5','6','7','8','9','31')));
年 月 星期日 星期一 星期二 星期三 星期四 星期五 星期六 本月最后一日
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------
2008 2 3 4 5 6 7 8 9 28
2009 12 13 4 5 6 7 8 9 31
2010 12 13 4 5 6 7 8 9 31
以上使用的类型都基于schema级别,如果是定义在包、函数、过程等这些结构里是不能给table函数使用的。
这种类型可以使用在管道函数中(pipelined function)。也可以存放中间处理的数据,类似于临时表的作用,但是是存放在内存中的。
相关推荐
Oracle2: 1. 《Oracle8 优化技术》摘录 (第一章 安装) 2. 《Oracle8 优化技术》摘录 (第二章 ...50. 怎样在SQLPlus中使用 '&' 来实现自定义参数变量? 51. 怎样在查询记录时给记录加锁 52. 自动备份Oracle数据库
其一、就业面广:全球前100强企业99家都在使用ORACLE相关技术,中国政府机构,大中型企事业单位都能有ORACLE技术的工程师岗位。 其二、技术层次深:如果期望进入IT服务或者产品公司(类似毕博、DELL、IBM等),...
第二种方法: 将该文件作为模板,直接在上面用模板语言书写要插入的代码片段,每次解析完这个模板片段后,再插入这段模版,如此往复.而这些模板片段可以包含在编译语言 的注释块中(不是模版语言的注释块),不会对应用...
<jp:mondrianQuery dataSource="" id="query01" jdbcDriver="oracle.jdbc.driver.OracleDriver" jdbcUrl="jdbc:oracle:thin:ngykt/ngyktadmin@172.16.46.241:1521:orcl10" catalogUri="/WEB-INF/queries/feeSchema....
首先确认系统中已经安装了“bos.content_list”文件集(fileset), 如果没有安装, 请使用smitty installp进行安装. 运行which_fileset命令, 根据文件查找对应的文件集. 例如: #which_fileset iostat /usr/bin/...
1、测试流程管理、测试度量方法 按照尽早进行测试的原则,测试人员应该在需求阶段就介入,并贯穿软件开发的全过程。就测试过程本身而言,应该包含以s下几个阶段。 -测试需求的分析和确定。 -测试计划。 -...
其中save(FileActionForm fileForm)方法,将封装在fileForm中的上传文件保存到数据库中,这里我们使用FileActionForm作为方法入参,FileActionForm是Web层的表单数据对象,它封装了提交表单的数据。将...
9、说明:in 的使用方法 select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’) 10、说明:两张关联表,删除主表中已经在副表中没有的信息 delete from table1 where not exists ( select * ...
9、说明:in 的使用方法 select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’) 10、说明:两张关联表,删除主表中已经在副表中没有的信息 delete from table1 where not exists ( select * ...
9、说明:in 的使用方法 select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’) 10、说明:两张关联表,删除主表中已经在副表中没有的信息 delete from table1 where not exists ( select * ...
下载和安装都很容易,按照安装文档,只需要十几分钟就可以搞定,而且还可以为JIRA配置单独的外包数据库(可以使用的数据库有MySQL、MS SQL、Oracle等)。 安装好之后就首先要在服务器上通过http://localhost:8080来对...
Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML浏览器,使用方法: 可直接输入文件名或网络地址,但必需事先连入网络。 Java编写的山寨QQ,多人聊天+用户在线 21个目标文件 摘要:JAVA源码,...
Java编写的HTML浏览器源代码,一个很简单甚至不算是浏览器的HTML浏览器,使用方法: 可直接输入文件名或网络地址,但必需事先连入网络。 Java编写的山寨QQ,多人聊天+用户在线 21个目标文件 摘要:JAVA源码,...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...