您的位置:首页 > 数据库 > Oracle

Oracle 使用小计(4)

2015-07-17 14:41 726 查看

1.oracle字符串分割函数split

(1)定义split_type类型:

CREATE OR REPLACE TYPE split_type IS TABLE OF VARCHAR2 (4000)

(2)定义split函数:

CREATE OR REPLACE FUNCTION split (

p_str IN VARCHAR2,

p_delimiter IN VARCHAR2 default(',') --分隔符,默认逗号

)

RETURN split_type

IS

j INT := 0;

i INT := 1;

len INT := 0;

len1 INT := 0;

str VARCHAR2 (4000);

my_split split_type := split_type ();

BEGIN

len := LENGTH (p_str);

len1 := LENGTH (p_delimiter);

WHILE j < len

LOOP

j := INSTR (p_str, p_delimiter, i);

IF j = 0

THEN

j := len;

str := SUBSTR (p_str, i);

my_split.EXTEND;

my_split (my_split.COUNT) := str;

IF i >= len

THEN

EXIT;

END IF;

ELSE

str := SUBSTR (p_str, i, j - i);

i := j + len1;

my_split.EXTEND;

my_split (my_split.COUNT) := str;

END IF;

END LOOP;

RETURN my_split;

END split;

(3)测试split函数:

select * from table (split('1,2,3,4',','))

出处: http://www.chinasb.org/archives/2011/02/1442.shtml#viewSource

2.循环控制结构语句

2.1.基本循环

LOOP

statement1;

......

EXIT [WHEN condition];

END LOOP;

EG:

DECLARE

I INT:= 1

BEGIN

LOOP

INSERT INTO COMPANY VALUES('PZDNDD' || I );

EXISTS WHEN I = 10;

I := I + 1;

END LOOP;

END;

2.2 while循环

WHILE condition LOOP

statement1;

statement2;

.....

END LOOP;

EG:

DECLARE

I INT:= 1

BEGIN

WHILE I <= 10 LOOP

INSERT INTO COMPANY VALUES ('PZDNDD' || I);

I := I + 1;

END LOOP;

END;

2.3 for循环

FOR counter in [REVERSE] lower_bound. .upper_bound LOOP

statement1;

statement2;

.......

END LOOP;

counter是循环控制变量,并且该变量由oracle隐含定义,不需要显式定义。lower_bound和upper_bound分别对应于循环控制变量的下界值和上界值,默认情况下,当使用FOR循环时,每次循环时循环控制变量会自动增1.如果指定REVERSE选项,那么每次循环时循环控制变量会自动减1.

EG:

BEGIN

FOR I IN REVERSE 1..10 LOOP

INSERT INTO COMPANY VALUES ('PZDNDD' || I);

END LOOP;

END;

3.分支控制结构

–情形1

IF CONDITION THEN

......

END IF;

–情形2

IF CONDITION THEN

......

ELSE

......

END IF

–情形3

IF CONDITION THEN

......

ELSIF CONDITION2 THEN

......

ELSIF CONDITION3 THEN

......

END IF;

4.instr函数

语法:

instr( string1, string2 [, start_position [, nth_appearance ] ] )

参数:

string1 源字符串,要在此字符串中查找。

string2 要在string1中查找的字符串。

start_position 代表string1 的哪个位置开始查找。此参数可选,如果省略默认为1。字符串索引从1开始。如果此参数为正,从左到右开始检索,如果此参数为负,从右到左检索,返回要查找的字符串在源字符串中的开始索引。

nth_appearance 代表要查找第几次出现的string2. 此参数可选,如果省略,默认为 1.如果为负数系统会报错。

返回值:

string2在string1中的第一个字母的位置。如果String2在String1中没有找到,则返回0。

EG:Freq=day;中的等号位置

INSTR(TT.COLUMN_VALUE,'=',1,1)

5.substr函数

语法:

substr( string, start_position, [ length ] )

参数:

string:源字符串

start_position:要截取的子串的开始位置。为负数表示从源字符串的末尾开始匹配。

length:要截取的字符的长度。不填表示到源字符串的末尾。

示例:Freq=day;,获取day。

SUBSTR(TT.COLUMN_VALUE,INSTR(TT.COLUMN_VALUE,'=',1,1)+1)

6.日期函数

6.1日期相加

计算基准:1天为1个单位。add_months(sysdate,12)

SELECT SYSDATE FROM DUAL;

SELECT SYSDATE + 1 * 7 FROM DUAL;

SELECT SYSDATE + 1 FROM DUAL;

SELECT SYSDATE + 1/24 FROM DUAL;

SELECT SYSDATE + 1/24/60 FROM DUAL;

add_months(sysdate,12)

以上分别加一周、一天、一小时、一分钟。加一个月。

另外指定计算:

select sysdate,sysdate + interval '2' SECOND from dual

select sysdate,sysdate + interval '2' MINUTE from dual

select sysdate,sysdate + interval '2' HOUR from dual

select sysdate,sysdate + interval '2' day from dual

select sysdate,sysdate + interval '2' month from dual

select sysdate,sysdate + interval '2' year from dual

以上分别加两(秒,分,时,天,月,年)。

6.2 日期格式表

格式

含义

yyyy

yyyy 用4位数表示年

mm

表示两位的月

dd

表示当月的第几天

hh

表示12小时的时间

hh24

表示24小时制的时间

mi

表示2位数的分钟

ss

表示2位数的秒

ddd

表示当年的第几天

dy

表示当周的第几天

q

季度(1-4)

以上格式就可以在to_char和to_date中使用。

6.3相差计算

计算基准:默认时间相减获得相差的天数。

select To_date('2015-07-17 13:31:00' , 'yyyy-mm-dd hh24-mi-ss') -

To_date('2015-07-17 13:31:50' , 'yyyy-mm-dd hh24-mi-ss') 相差天数 FROM DUAL;



7.判断日期部分相等(同一天)

TRUNC(TO_DATE(TMP_DT,'yyyy-mm-dd')-TO_DATE(SYSDATE,'yyyy-mm-dd')) = 0

8.select into 与insert into语句

SELECT vale1, value2 into Table2 from Table1

要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中,请注意vale1,vale2一定要是Table1有的字段,否则就会出错

Insert into Table2(field1,field2,...) select value1,value2,... from Table1

插入数据的另一种形式

9.插入一条数据,并返回主键

INSERT INTO a VALUES (xxx, xxx)

RETURNING 列名 INTO 变量;

10. ORA-04091: table xxx is mutating, trigger/function may not see it

参考:http://www.cnblogs.com/dingyingsi/archive/2013/10/09/3358675.html

触发器访问所依赖的table规则

对于after 类型的 for each row 级别的triggers,不论哪种insert语句触发了trigger,都不允许在 trigger 中访问本trigger所依赖的table的;

对于before 类型的 for each row 级别的triggers,如果使用 insert into ... values 语句触发此trigger ,则在trigger 中访问本table没有问题;
但如果使用 insert into select .. from 语句触发此trigger ,则在trigger 中访问本table就报ora-04091错误;

所以,如果有insert into select ...from语句的,可以使用表变量来改进

11.复合数据类型值Index-By表

index_by表或则PL/SQL表,其数据结构模型为hash表。

主要是通过键值的方式访问。key是binary_interger;value为任意类型。

其定义语法如下:

type 表类型名 is table of 类型 index by binary_integer;

表变量名 表类型;

EG:

TYPE TABLETYPE1 IS TABLE OF TASK_USER%ROWTYPE INDEX BY BINARY_INTEGER;

TABLE1 TABLETYPE1;

其中,TASK_USER为数据库中一个表。

类型可以是number 、varchar2、date 等数据类型,index by binary_integer 子句代表以符号整数为索引,这样访问表类型变量中的数据方法就是"表变量名(索引符号整数)"。

示例1:定义值为单一数据类型的Index-By表。

DECLARE

--value 为varchar2(10) 类型

TYPE tabletype1 IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER;

table1 tabletype1;

--value 为TASK表中CODE字段的类型

TYPE tabletype2 IS TABLE OF TASK.CODE%TYPE INDEX BY BINARY_INTEGER;

table2 tabletype2;

BEGIN

table1(1) := '大学'; --通过键 1 访问

table1(2) := '大专';

table2(1) := '150716003';

table2(2) := '150716002'; --通过键 2 访问

dbms_output.put_line(table1(1)||table2(1));

dbms_output.put_line(table1(2)||table2(2));

END;

注:下面的程序定义了名为tabletype1和tabletype2的两个Index-By表。table1和table2分别是两种表类型变量。

示意图:



示例2:定义一个值为TASK表类型的Index-By表。

DECLARE

TYPE TABLETYPE1 IS TABLE OF TASK_USER%ROWTYPE INDEX BY BINARY_INTEGER;

T1 TABLETYPE1;

BEGIN

SELECT * INTO T1(1) FROM TASK_USER TU WHERE TU.TASK_CODE = '150716003';

dbms_output.put_line(T1(1).USER_TYPE);

END;

注意:一定要使用索引,比如T1(1),如果写成T1则不行,访问的时候也一样。

示意图:



参考:http://www.linuxidc.com/Linux/2010-08/27830.htm

12. In和Exist

exits性能高于In只需要有1条存在即可,无需检索子查询的所有记录。

在写SQL的时候,适当把IN改为exists

且exist可以用于多个字段的比较。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: