- 浏览: 2182728 次
文章分类
最新评论
oracle 11g PL/SQL Programming学习二
第二章 PL/SQL基础
PL/SQL语言和SQL一样是一种大小写不敏感的语言.
1.PL/SQL块结构(Oracle PL/SQL Block Structure)
PL/SQL是基于结构化程序的模型理念开发的.它有静态数据类型、模块性、异常管理.
PL/SQL支持两种类型的程序:有名块和匿名块
例:SET SERVEROUTPUT ON SIZE 1000000 --如使用了本博客的SQL*PLUS脚本设置,可省略
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World.');
END;
SQL*PLUS支持替换变量(&)
23:50:29 hr@orcl> DECLARE 23:50:31 2 MY_VAR VARCHAR2(30); 23:50:31 3 BEGIN 23:50:31 4 MY_VAR := '&input';--赋值操作符(:=) 23:50:31 5 DBMS_OUTPUT.PUT_LINE('Hello ' || MY_VAR); 23:50:31 6 END; 23:50:31 7 / 输入 input 的值: cryking Hello cryking PL/SQL 过程已成功完成。
SQLPLUS也可以直接执行SQL脚本文件(使用@)
23:52:49 hr@orcl> @123.SQL 输入 input 的值: CRYKING Hello CRYKING
异常管理方面,例:
23:57:56 hr@orcl> DECLARE 23:58:12 2 MY_VAR VARCHAR2(10); 23:58:12 3 BEGIN 23:58:12 4 MY_VAR := '&input'; 23:58:12 5 DBMS_OUTPUT.PUT_LINE('Hello ' || MY_VAR); 23:58:12 6 EXCEPTION 23:58:12 7 WHEN OTHERS THEN 23:58:12 8 DBMS_OUTPUT.PUT_LINE(SQLERRM); 23:58:12 9 END; 23:58:12 10 / 输入 input 的值: AAAAAAAAAAAAAAAAAA ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小 PL/SQL 过程已成功完成。
匿名块可以嵌套匿名块,有名块也可以嵌套匿名块.最外层的程序块控制整个程序流。
注意:声明模块的异常,本块是无法捕捉到的.
2.变量、赋值和操作符(Variables, Assignments, and Operators)
PL/SQL支持所有的SQL数据类型及其子类型,还支持标量和复杂变量.
变量以字母开头,可以包含字母、数字、$、_、#等.变量有其作用域范围.
声明部分没有显示赋值的变量,都默认为NULL。
00:09:35 hr@orcl> DECLARE 00:09:49 2 VARIABLE_NAME NUMBER; 00:09:49 3 VARIABLE_NAME1 VARCHAR2(10); 00:09:49 4 BEGIN 00:09:49 5 IF VARIABLE_NAME IS NULL THEN 00:09:49 6 DBMS_OUTPUT.PUT_LINE('VARIABLE_NAME is NULL!'); 00:09:49 7 END IF; 00:09:49 8 IF VARIABLE_NAME1 IS NULL THEN 00:09:49 9 DBMS_OUTPUT.PUT_LINE('VARIABLE_NAME1 is NULL!'); 00:09:49 10 END IF; 00:09:49 11 END; 00:09:49 12 / VARIABLE_NAME is NULL! VARIABLE_NAME1 is NULL! PL/SQL 过程已成功完成。
oracle赋值执行很多隐式的转换操作.(可能会丢失精度)
如:
00:13:18 hr@orcl> DECLARE 00:13:20 2 VARIABLE_NAME NUMBER; 00:13:20 3 I_VAR INTEGER; 00:13:20 4 BEGIN 00:13:20 5 VARIABLE_NAME:=2.3234; 00:13:20 6 I_VAR:=VARIABLE_NAME; 00:13:20 7 DBMS_OUTPUT.PUT_LINE(I_VAR);--输出为2,丢失了小数精度0.3234 00:13:20 8 END; 00:13:20 9 / 2 PL/SQL 过程已成功完成。
PLSQL隐式类型转换汇总图如下:
PL/SQL同样也支持等号操作符(=),用来判断两个值是否相等,也支持一般的逻辑操作符,如(>, >=, <,<=,<>, !=, ~=,^=).
你可以在声明部分定义游标语句,游标可以把你视图或表中的数据带到PL/SQL程序中来进行处理.
游标可以有0个或多个参数.
3.控制结构
PL/SQL支持IF,ELSIF,ELSE,CASE等控制语句.
条件结构
IF [NOT] left_operand1 >|=|< right_operand1 [[AND|OR]
[NOT] left_operand2 = right_operand2 [[AND|OR]
[NOT] boolean_operand ]] THEN
NULL;
ELSE
NULL;
END IF;
或
CASE [ TRUE | [selector_variable]]
WHEN [criterion1 | expression1] THEN
criterion1_statements;
WHEN [criterion2 | expression2] THEN
criterion2_statements;
WHEN [criterion(n+1) | expression(n+1)] THEN
criterion(n+1)_statements;
ELSE
block_statements;
END CASE;
注意NULL既不是TRUE也不是FALSE,所以建议变量在可能为NULL时,使用NVL函数先进行转换,再判断.
如:
00:24:28 hr@orcl> DECLARE 00:24:29 2 -- Define a Boolean variable. 00:24:29 3 MY_VAR BOOLEAN; 00:24:29 4 BEGIN 00:24:29 5 -- Use an NVL function to substitute a value for evaluation. 00:24:29 6 IF NOT NVL(MY_VAR, FALSE) THEN 00:24:29 7 DBMS_OUTPUT.PUT_LINE('This should happen!'); 00:24:29 8 ELSE 00:24:29 9 DBMS_OUTPUT.PUT_LINE('This can''t happen!');--注意其中有转义字符' 00:24:29 10 END IF; 00:24:29 11 END; 00:24:29 12 / This should happen! PL/SQL 过程已成功完成。 00:30:44 hr@orcl> BEGIN 00:30:46 2 CASE nvl(NULL,FALSE)--找到为FALSE的 00:30:46 3 WHEN (1 > 3) THEN 00:30:46 4 DBMS_OUTPUT.PUT_LINE('One is greater than three.'); 00:30:46 5 WHEN (3 < 5) THEN 00:30:46 6 DBMS_OUTPUT.PUT_LINE('Three is less than five.'); 00:30:46 7 WHEN (1 = 2) THEN 00:30:46 8 DBMS_OUTPUT.PUT_LINE('One equals two.'); 00:30:46 9 ELSE 00:30:46 10 DBMS_OUTPUT.PUT_LINE('Nothing worked.'); 00:30:46 11 END CASE; 00:30:46 12 END; 00:30:46 13 / One is greater than three. PL/SQL 过程已成功完成。
4.循环结构
PL/SQL支持FOR, SIMPLE,WHILE,LOOP等循环.循环通常和游标结合来处理问题.
1.for循环结构
FOR支持数字和游标的循环.
数字:
FOR i IN starting_number..ending_number LOOP
statement;
END LOOP;
如:
00:35:05 hr@orcl> BEGIN 00:35:07 2 FOR I IN 1 .. 10 LOOP 00:35:07 3 DBMS_OUTPUT.PUT_LINE('The index value is [' || I || ']'); 00:35:07 4 END LOOP; 00:35:07 5 END; 00:35:07 6 / The index value is [1] The index value is [2] The index value is [3] The index value is [4] The index value is [5] The index value is [6] The index value is [7] The index value is [8] The index value is [9] The index value is [10] PL/SQL 过程已成功完成。
游标的:
FOR i IN {cursor_name[(parameter1,parameter(n+1))] | (sql_statement)} LOOP
statement;
END LOOP;
如:
--显示游标
DECLARE
CURSOR C IS
SELECT ITEM_TITLE FROM ITEM;
BEGIN
FOR I IN C LOOP
DBMS_OUTPUT.PUT_LINE('The title is [' || I.ITEM_TITLE || ']');
END LOOP;
END;
--隐式游标
BEGIN
FOR I IN (SELECT ITEM_TITLE FROM ITEM) LOOP
DBMS_OUTPUT.PUT_LINE('The title is [' || I.ITEM_TITLE || ']');
END LOOP;
END;
2.单循环结构(LOOP)
OPEN cursor_name [(parameter1,parameter(n+1))];
LOOP
FETCH cursor_name
INTO row_structure_variable | column_variable1 [,column_variable(n+1)];
EXIT WHEN cursor_name%NOTFOUND;
statement;
END LOOP;
CLOSE cursor_name;
Oracle提供6种游标属性:%FOUND,%NOTFOUND,%ISOPEN,%ROWCOUNT,SQL%BULK_ROWCOUNT,SQL%BULK_EXCEPTIONS
3.while循环
OPEN cursor_name [(parameter1,parameter(n+1))];
WHILE condition LOOP
FETCH cursor_name
INTO row_structure_variable | column_variable1 [,column_variable(n+1)];
EXIT WHEN cursor_name%NOTFOUND;
statement;
END LOOP;
CLOSE cursor_name;
例:
15:01:12 SCOTT@orcl> DECLARE 15:01:14 2 v_name emp.ename%TYPE; 15:01:14 3 CURSOR c IS 15:01:14 4 SELECT ename FROM emp where rownum<5; 15:01:14 5 BEGIN 15:01:14 6 OPEN c; 15:01:14 7 WHILE c%ISOPEN 15:01:14 8 LOOP 15:01:14 9 FETCH c 15:01:14 10 INTO v_name; 15:01:14 11 IF c%NOTFOUND THEN --退出循序的条件,必须要,否则报错 15:01:14 12 CLOSE c; 15:01:14 13 END IF; 15:01:14 14 dbms_output.put_line('The ename is [' || v_name || ']'); 15:01:14 15 END LOOP; 15:01:14 16 END; 15:01:14 17 / The ename is [test110] The ename is [test111] The ename is [SMITH] The ename is [ALLEN] The ename is [ALLEN] PL/SQL 过程已成功完成。
5.函数、存储、包
Oracle用命名空间列表维护所有的表名、视图名、存储名、函数名等.
1.函数
函数原型:
FUNCTION function_name
[( parameter1 [IN][OUT] [NOCOPY] sql_datatype | plsql_datatype
[, parameter2 [IN][OUT] [NOCOPY] sql_datatype | plsql_datatype
[, parameter(n+1) [IN][OUT] [NOCOPY] sql_datatype | plsql_datatype )]]]
RETURN [ sql_data_type | plsql_data_type ]
[ AUTHID [ DEFINER | CURRENT_USER ]]
[ DETERMINISTIC | PARALLEL_ENABLED ]
[ PIPELINED ]
[ RESULT_CACHE [ RELIES ON table_name ]] IS
declaration_statements
BEGIN
execution_statements
RETURN variable;
[EXCEPTION]
exception_handling_statements
END [function_name];
函数必须返回一个值.
如:
CREATE OR REPLACE FUNCTION join_strings
(
string1 VARCHAR2
,string2 VARCHAR2
) RETURN VARCHAR2 IS
BEGIN
RETURN string1 || ' ' || string2 || '.';
END;
2.存储过程
PROCEDURE procedure_name
[( parameter1 [IN][OUT] [NOCOPY] sql_datatype | plsql_datatype
[, parameter2 [IN][OUT] [NOCOPY] sql_datatype | plsql_datatype
[, parameter(n+1) [IN][OUT] [NOCOPY] sql_datatype | plsql_datatype )]]]
[ AUTHID DEFINER | CURRENT_USER ] IS
declaration_statements
BEGIN
execution_statements
[EXCEPTION]
exception_handling_statements
END [procedure_name];
存储过程可以没有形参.形参可以是传值或者传引用类型的.传引用的还分IN和OUT模式.
--传引用的IN模式的变量存储中不能给其赋值(缺省就是传引用的) 15:11:53 SCOTT@orcl> CREATE OR REPLACE PROCEDURE format_string(string_in VARCHAR2) IS 15:12:21 2 BEGIN 15:12:21 3 string_in := '[' || string_in || ']'; 15:12:21 4 END; 15:12:21 5 / 警告: 创建的过程带有编译错误。 已用时间: 00: 00: 00.09 15:12:22 SCOTT@orcl> show err PROCEDURE FORMAT_STRING 出现错误: LINE/COL ERROR -------- ----------------------------------------------------------------- 3/3 PL/SQL: Statement ignored 3/3 PLS-00363: 表达式 'STRING_IN' 不能用作赋值目标
存储过程调用方法(SQLPLUS下)
15:21:52 SCOTT@orcl> VARIABLE session_var VARCHAR2(30); 15:22:39 SCOTT@orcl> CALL join_strings('Hello','World') INTO :session_var;--调用函数join_strings给变量赋值 调用完成。 已用时间: 00: 00: 00.03 15:22:56 SCOTT@orcl> CALL format_string(:session_var);--调用存储,也可以是EXECUTE format_string(:session_var); 调用完成。 已用时间: 00: 00: 00.00 15:23:03 SCOTT@orcl> print session_var SESSION_VAR -------------------------------- [Hello World.]
或者
15:23:10 SCOTT@orcl> DECLARE 15:24:50 2 session_var VARCHAR2(30); 15:24:50 3 BEGIN 15:24:50 4 session_var:=join_strings('Hello','World'); 15:24:50 5 format_string(session_var); 15:24:50 6 DBMS_OUTPUT.PUT_LINE(session_var); 15:24:50 7 END; 15:24:50 8 / [Hello World.] PL/SQL 过程已成功完成。
3.包
在11G里包将是存储的骨干。它由函数和存储组成.它还可以提供函数和存储的重载功能.
包体中的存储\函数必须和包中的存储过程、函数签名一致.
6.事务范围
3个命令(TCL,事务控制语言)控制会话的事务范围.
1.COMMIT语句--提交当前事务的所有的DML改变,并结束当前事务
2.SAVEPOINT语句--把事务分为两期,也就是将事务分为两个相对的时间点
3.ROLLBACK语句--撤销事务的所有的改变,如有设置SAVEPOINT,也可以撤销到指定的状态,否则撤销当前事务所有的改变,并结束当前事务
单一事务范围
BEGIN
-- Set savepoint.
SAVEPOINT new_member;
-- First insert.
INSERT INTO member
VALUES
(member_s1.nextval,
1005,
'D921-71998',
'4444-3333-3333-4444',
1006,
2,
SYSDATE,
2,
SYSDATE);
-- Second insert.
INSERT INTO contact
VALUES
(contact_s1.nextval,
member_s1.currval + 1,
1003,
'Bodwin',
'Jordan',
'',
2,
SYSDATE,
2,
SYSDATE);
-- Print success message and commit records.
dbms_output.put_line('Both succeeded.');
COMMIT;
EXCEPTION
WHEN others THEN
-- Roll back to savepoint, and raise exception message.
ROLLBACK TO new_member;
dbms_output.put_line(SQLERRM);
END;
上面的两个INSERT操作,要么全部成功,要么全部失败.
多事务范围
可以使用AUTONOMOUS_TRANSACTION预编译命令,使得存储或函数、触发器使用自治事务.(与当前事务分离开,成为单独的一个事务)
7.触发器
在触发器中不能使用DCL(COMMIT,ROLLBACK等),除非使用了自治事务.
在11g里,你可以使用5种类型的触发器:
1.DDL触发器--当你创建、更改、重命名、删除对象的时候触发,它们常用来监视数据库对象的各种操作.
2.DML触发器或行级触发器--当你对一个表做DML操作时触发,它们常用来审计、更改值、检查条件、和序列联用生成主键等等.
3.复合触发器--语句级和行级触发的综合,可以捕获4个时间点的信息:a,语句触发前;b,每行改变发生前;c,每行改变发生后;d,语句触发后
4.INSTEAD OF触发器--停止当前的DML语句,重定向到另外的DML语句.常用来更新视图.
5.系统级或数据库级--当一个数据库的活动事件发生的时候触发,像登录/登出数据库.常用来跟踪数据库系统事件.
第三章 语法基础(比较简单,但比较基础,部分省略,详细请查看官方文档吧)
15:57:27 SCOTT@orcl> begin dbms_output.put_line(3**3); end;--**代表多少次方,如2**10方等于1024 15:57:57 4 / 27 PL/SQL 过程已成功完成。
15:59:16 SCOTT@orcl> DECLARE 16:00:00 2 "End" NUMBER := 1; 16:00:00 3 BEGIN 16:00:00 4 dbms_output.put_line('A quoted identifier End ['||"End"||']'); 16:00:00 5 END; 16:00:01 6 / A quoted identifier End [1] PL/SQL 过程已成功完成。 --类型长度,VARCHAR2和CHAR的区别 16:00:02 SCOTT@orcl> DECLARE 16:10:17 2 c CHAR(32767) := ' '; 16:10:17 3 v VARCHAR2(32767) := ' '; 16:10:17 4 BEGIN 16:10:17 5 dbms_output.put_line('c is [' || LENGTH(c) || ']'); 16:10:17 6 dbms_output.put_line('v is [' || LENGTH(v) || ']'); 16:10:17 7 v := v || ' '; 16:10:17 8 dbms_output.put_line('v is [' || LENGTH(v) || ']'); 16:10:17 9 END; 16:10:17 10 / c is [32767] v is [1] v is [2] PL/SQL 过程已成功完成。 --子类型使用(SUBTYPE) 16:10:18 SCOTT@orcl> DECLARE 16:11:44 2 SUBTYPE code IS CHAR(1 CHAR); 16:11:44 3 c CHAR(1 CHAR) := 'A'; 16:11:44 4 d CODE; 16:11:44 5 BEGIN 16:11:44 6 d := c; 16:11:44 7 END; 16:11:44 8 / PL/SQL 过程已成功完成。 --INTERVAL类型的使用 16:14:06 SCOTT@orcl> DECLARE 16:15:22 2 var2 INTERVAL YEAR(3) TO MONTH; 16:15:22 3 BEGIN 16:15:22 4 -- Shorthand for a 101 year and 3 month interval. 16:15:22 5 var2 := '101-3'; 16:15:22 6 dbms_output.put_line(var2); 16:15:22 7 var2 := INTERVAL '101-3' YEAR TO MONTH; 16:15:22 8 dbms_output.put_line(var2); 16:15:22 9 var2 := INTERVAL '101' YEAR; 16:15:22 10 dbms_output.put_line(var2); 16:15:22 11 var2 := INTERVAL '3' MONTH; 16:15:22 12 dbms_output.put_line(var2); 16:15:22 13 END; 16:15:22 14 / +101-03 +101-03 +101-00 +000-03 PL/SQL 过程已成功完成。 --数组类型的使用 16:15:23 SCOTT@orcl> DECLARE 16:17:12 2 TYPE number_varray IS VARRAY(10) OF NUMBER; 16:17:12 3 list NUMBER_VARRAY := number_varray(1, 2, 3, 4, 5, 6, 7, 8, NULL, NULL); 16:17:12 4 BEGIN 16:17:12 5 FOR i IN 1 .. list.LIMIT 16:17:12 6 LOOP 16:17:12 7 dbms_output.put('[' || list(i) || ']'); 16:17:12 8 END LOOP; 16:17:12 9 dbms_output.new_line; 16:17:12 10 END; 16:17:12 11 / [1][2][3][4][5][6][7][8][][] PL/SQL 过程已成功完成。 --嵌套表类型的使用 16:17:13 SCOTT@orcl> DECLARE 16:18:12 2 TYPE number_table IS TABLE OF NUMBER; 16:18:12 3 list NUMBER_TABLE := number_table(1, 2, 3, 4, 5, 6, 7, 8); 16:18:12 4 BEGIN 16:18:12 5 list.DELETE(2); 16:18:12 6 FOR i IN 1 .. list.COUNT 16:18:12 7 LOOP 16:18:12 8 IF list.EXISTS(i) THEN 16:18:12 9 dbms_output.put('[' || list(i) || ']'); 16:18:12 10 END IF; 16:18:12 11 END LOOP; 16:18:12 12 dbms_output.new_line; 16:18:12 13 END; 16:18:12 14 / [1][3][4][5][6][7] PL/SQL 过程已成功完成。 --关联数组的使用 16:19:49 SCOTT@orcl> DECLARE 16:21:00 2 TYPE number_table IS TABLE OF NUMBER INDEX BY PLS_INTEGER; 16:21:00 3 list NUMBER_TABLE; 16:21:00 4 BEGIN 16:21:00 5 FOR i IN 1 .. 6 16:21:00 6 LOOP 16:21:00 7 list(i) := i; -- Explicit assignment required for associative arrays. 16:21:00 8 END LOOP; 16:21:00 9 list.DELETE(2); 16:21:00 10 FOR i IN 1 .. list.COUNT--COUNT为5 16:21:00 11 LOOP 16:21:00 12 IF list.EXISTS(i) THEN 16:21:00 13 dbms_output.put('[' || list(i) || ']'); 16:21:00 14 END IF; 16:21:00 15 END LOOP; 16:21:00 16 dbms_output.new_line; 16:21:00 17 END; 16:21:01 18 / [1][3][4][5] PL/SQL 过程已成功完成。 --引用型游标的使用 16:27:31 SCOTT@orcl> VARIABLE refcur REFCURSOR 16:28:21 SCOTT@orcl> DECLARE 16:28:26 2 TYPE weakly_typed IS REF CURSOR; 16:28:26 3 quick WEAKLY_TYPED; 16:28:26 4 BEGIN 16:28:26 5 OPEN quick FOR 16:28:26 6 SELECT ename, COUNT(*) 16:28:26 7 FROM emp 16:28:26 8 GROUP BY ename; 16:28:26 9 :refcur := quick; 16:28:26 10 END; 16:28:27 11 / PL/SQL 过程已成功完成。 已用时间: 00: 00: 00.00 16:28:28 SCOTT@orcl> select :refcur from dual; :REFCUR -------------------- CURSOR STATEMENT : 1 CURSOR STATEMENT : 1 ENAME COUNT(*) ---------- ---------- ALLEN 1 JONES 1 FORD 1 CLARK 1 MILLER 1 SMITH 1 WARD 1 MARTIN 1 SCOTT 1 TURNER 1 ADAMS 1 BLAKE 1 KING 1 JAMES 1 test110 1 test111 1 已选择16行。
附plsql标量数据类型汇总图:
相关推荐
Use new Oracle Database 11g tools and techniques such as PL/Scope, the PL/SQL hierarchical profiler, and the SecureFiles technology for large objects Build modular PL/SQL applications using ...
Considered the best Oracle PL/SQL programming guide by the Oracle community, this definitive guide is precisely what you need to make the most of Oracle’s powerful procedural language. The sixth ...
Oracle 10g PL/SQL Programming examples
Oracle PL/SQL Programming
本书内容丰富,结构合理,全面涵盖Oracle Database 11g 的新增特性和实用工具,并提供详细的说明、可剪切-粘贴的语法示例和真实的案例分析。通过学习书中的代码和图例,您不仅能访问和修改数据库信息,编写功能强大...
Thoroughly updated for Oracle Database 11g Release 2, this edition reveals new PL/SQL features and provides extensive code samples, ranging from simple examples to complex and complete applications, ...
Oracle database 10g PL/SQL Programming一书的代码
oracle database 11g pl/sql programming,内容是全英文的,我加了一个中文的索引,里面介绍pl/sql编程,很全面,值得学习
At the heart of much of Oracle’s software is PL/SQL—a programming language that provides procedural extensions to Oracle’s version of SQL (Structured Query Language) and serves as the programming ...
oracle8 pl/sql programming 中文 pdf
Use new Oracle Database 11g tools and techniques such as PL/Scope, the PL/SQL hierarchical profiler, and the SecureFiles technology for large objects Build modular PL/SQL applications using ...
Oracle9i PL/SQL Programming 一书中pl sql的代码 浅显易懂 覆盖全面
PL/SQL, Oracle's procedural extension of SQL, is an advanced fourth-generation programming language (4GL). It offers modern features such as data encapsulation, overloading, collection types, ...
Oracle PL/SQL Programming 6th Edition by Steven Feuerstein, Bill Pribyl
Filled with detailed examples and expert strategies from an Oracle ACE, Oracle Database 12c PL/SQL Programming explains how to retrieve and process data, write PL/SQL statements, execute effective ...
This book explains the best way to construct packages, a powerful part of Oracle's PL/SQL procedural language that can dramatically improve your programming productivity and code quality, while ...
application logic move into the Oracle Server, so that PL/SQL programming has become a significant part of the total development process. PL/SQL Developer focuses on ease of use, code quality and...
Oracle8 PL/SQL程序设计中的例子脚本 162K SQL(英文) The example code used in Oracle8 PL/SQL Programming