课程地位 .Net &C# SQL Server XML SPM ASP.NET & WebService Oracle UML SPR: Computer Base HTML&JavaScript SQL Server Base OOP&Java Base C STB JSP /Servlet EJB&WebService WinForms Struts&JSF Testing&SQA Linux
Oracle 默认用户只有用合法的用户帐号才能访问 Oracle 数据库 Oracle 有几个默认的数据库用户 Oracle 默认用户 SYS SYSTEM SCOTT 数据库中所有数据字典表和视图都存储在 SYS 模式中。 SYS 用户主要用来维护系统信息和管理实例。 SYSTEM 是默认的系统管理员,该用户拥有 Oracle 管理工具使用的内部表和视图。通常通过 SYSTEM 用户管理数据库用户、权限和存储等 SCOTT 用户是 Oracle 数据库的一个示范帐户,在数据库安装时创建
28.
创建新用户 要连接到 Oracle数据库,就需要创建一个用户帐户 每个用户都有一个默认表空间和一个临时表空间 CREATE USER 命令用于创建新用户 CREATE USER username IDENTIFIED BY password [DEFAULT TABLESPACE tablespace] [TEMPORARY TABLESPACE tablespace]; CREATE USER 命令的语法是: CREATE USER MARTIN IDENTIFIED BY martinpwd DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP; 创建一个名称为 martin 的用户,其密码为 martinpwd
授予权限 3-2GRANT 命令可用于为用户分配权限或角色 GRANT CONNECT TO MARTIN; CONNECT 角色允许用户连接至数据库, 并创建数据库对象 GRANT RESOURCE TO MARTIN; RESOURCE 角色允许用户使用 数据库中的存储空间 GRANT CREATE SEQUENCE TO MARTIN; 此系统权限允许用户在当前模式中创建 序列,此权限包含在 CONNECT 角色中
31.
授予权限 3-3授予用户 MARTIN 操作 TEST 表对象的权限 GRANT SELECT ON TEST TO MARTIN; 允许用户查询 TEST 表的记录 GRANT UPDATE ON TEST TO MARTIN; 允许用户更新 TEST 表中的记录 GRANT ALL ON TEST TO MARTIN; 允许用户插入、删除、更新和查询 TEST 表中的记录
32.
更改和删除用户 ALTER USER 命令可用于更改口令 ALTER USER MARTIN IDENTIFIED BY martinpass; 修改 MARTIN 用户的密码 DROP USER 命令用于删除用户 DROP USER MARTIN CASCADE; 删除 MARTIN 用户模式
DML – INSERT 命令 2-2 插入来自其它表中的记录 语法: INSERT INTO <table_name> [(cloumn_list)] SELECT column_names FROM <other_table_name>; SQL> INSERT INTO newvendor_master SELECT * FROM vendor_master; SQL> INSERT INTO newvendor_master(vencode,venname) SELECT vencode, venname FROM vendor_master;
55.
事务控制语言 事务是最小的工作单元,作为一个整体进行工作 保证事务的整体成功或失败,称为事务控制用于事务控制的语句有: COMMIT - 提交并结束事务处理 ROLLBACK - 撤销事务中已完成的工作 SAVEPOINT – 标记事务中可以回滚的点 SQL> UPDATE order_master SET del_date = ‘30-8 月 -05’ WHERE orderno <= ’o002’; SQL> SAVEPOINT mark1; SQL> DELETE FROM order_master WHERE orderno = ‘o002’; SQL> SAVEPOINT mark2; SQL> ROLLBACK TO SAVEPOINT mark1; SQL> COMMIT;
56.
数据控制语言 数据控制语言为用户提供权限控制命令 用于权限控制的命令有: GRANT 授予权限 REVOKE 撤销已授予的权限 SQL> GRANT SELECT, UPDATE ON order_master TO MARTIN; SQL> GRANT UPDATE(qty_hand, re_level) ON itemfile TO MARTIN; SQL> GRANT SELECT ON vendor_master TO accounts WITH GRANT OPTION; SQL> REVOKE SELECT, UPDATE ON order_master FROM MARTIN;
算术操作符 算术操作符用于执行数值计算 可以在SQL 语句中使用算术表达式,算术表达式由数值数据类型的列名、数值常量和连接它们的算术操作符组成 算术操作符包括加 (+) 、减 (-) 、乘 (*) 、除 (/) SQL> SELECT itemdesc, max_level - qty_hand avble_limit FROM itemfile WHERE p_category='spares'; SQL > SELECT itemdesc, itemrate*(max_level - qty_hand) FROM itemfile WHERE p_category='spares';
59.
比较操作符 比较操作符用于比较两个表达式的值比较操作符包括 = 、 != 、 < 、 > 、 <= 、 >= 、 BETWEEN…AND 、 IN 、 LIKE 和 IS NULL 等 SQL> SELECT itemdesc, re_level FROM itemfile WHERE qty_hand < max_level/2; SQL> SELECT orderno FROM order_master WHERE del_date IN (‘06-1 月 -05’,‘05-2 月 -05'); SQL> SELECT vencode,venname,tel_no FROM vendor_master WHERE venname LIKE 'j___s';
集合操作符 集合操作符将两个查询的结果组合成一个结果 集合操作符UNION UNION ALL INTERSECT MINUS INTERSECT 操作符只返回两个查询的公共行。 SQL> SELECT orderno FROM order_master INTERSECT SELECT orderno FROM order_detail; SQL> SELECT orderno FROM order_master MINUS SELECT orderno FROM order_detail; MINUS 操作符返回从第一个查询结果中排除第二个查 询中出现的行。
62.
连接操作符 连接操作符用于将多个字符串或数据值合并成一个字符串 SQL>SELECT (venname|| ' 的地址是 ' ||venadd1||' '||venadd2 ||' '||venadd3) address FROM vendor_master WHERE vencode='V001'; 通过使用连接操作符可以将表中 的多个列合并成逻辑上的一行列
63.
操作符的优先级 SQL 操作符的优先级从高到低的顺序是: 算术操作符 -------- 最高优先级 连接操作符 比较操作符 NOT 逻辑操作符 AND 逻辑操作符 OR 逻辑操作符 -------- 最低优先级
字符函数 2-1字符函数 字符函数接受字符输入并返回字符或数值 Hello world Select concat (‘Hello’,’ world’) from dual; Concat (expr1, expr2) cd Select substr(‘abcdefg’,3,2) from dual; Substr (char, m, n) 5 Select instr (‘worldwide’,’d’) from dual; Instr (char, m, n) black and blue Select replace(‘jack and jue’ ,’j’,’bl’) from dual; Replace(char, searchstring,[rep string]) Select translate(‘jack’,’j’ ,’b’) from dual; Select rtrim(‘xyzadams’,’ams’) from dual; Select ltrim( ‘xyzadams’,’xyz’) from dual; Select upper(‘sun’) from dual; Select lower(‘FUN’) from dual; Select initcap(‘hello’) from dual; 输入 adams Ltrim(char,set) xyzad Rtrim(char,set) back Translate(char, from, to) fun Lower(char) Hello Initcap(char) SUN Upper(char) 输出 函数
68.
字符函数 2-2SQL> SELECT CHR(67) FROM dual; 以下是一些其它的字符函数: CHR 和 ASCII LPAD 和 RPAD TRIM LENGTH DECODE SQL> SELECT LPAD(‘function’,15,’=’) FROM dual; SQL> SELECT TRIM(9 from 9999876789999) FROM dual; SQL> SELECT LENGTH('frances') FROM dual; SQL> SELECT vencode, DECODE(venname,'frances','Francis') name FROM vendor_master WHERE vencode='v001';
69.
数字函数 数字函数接受数字输入并返回数值结果 数字函数-1 Select sign(-30) from dual; Sign(n) 2 Select sqrt(4) from dual; Sqrt(n) 100.25 Select trunc(100.256,2) from dual; Trunc(m,n) 100.26 Select round(100.256,2) from dual; Round(m,n) 1 Select mod(10,3) from dual; Mod(m,n) 16 Select power(4,2) from dual; Power(m,n) Select floor(100.2) from dual; Select cosh(0) from dual; Select cos(180) from dual; Select ceil(44.778) from dual; Select abs(-15) from dual; 输入 1 Cosh(n) 100 Floor(n) 45 Ceil(n) 15 Abs(n) -.5984601 Cos(n) 输出 函数
70.
转换函数 转换函数将值从一种数据类型转换为另一种数据类型 常用的转换函数有:TO_CHAR TO_DATE TO_NUMBER SELECT TO_CHAR(sysdate,'YYYY" 年 "fmMM" 月 "fmDD" 日 " HH24:MI:SS') FROM dual; SELECT TO_CHAR(itemrate,‘C99999’) FROM itemfile; SELECT TO_DATE(‘2005-12-06’ , ‘yyyy-mm-dd’) FROM dual; SELECT TO_NUMBER('100') FROM dual;
71.
其它函数 以下是几个用来转换空值的函数: NVLNVL2 NULLIF SELECT itemdesc, NVL(re_level,0) FROM itemfile; SELECT itemdesc, NVL2(re_level,re_level,max_level) FROM itemfile; SELECT itemdesc, NULLIF(re_level,max_level) FROM itemfile;
72.
分组函数 分组函数基于一组行来返回结果 为每一组行返回一个值AVG MIN MAX SUM COUNT SELECT AVG(re_level) FROM itemfile WHERE p_category='accessories'; SELECT MAX(max_level) FROM itemfile; SELECT SUM(itemrate*max_level) FROM itemfile; SELECT COUNT(*) FROM itemfile; SELECT COUNT(itemrate) FROM itemfile; SELECT COUNT(DISTINCT qty_hand) FROM itemfile; 分组函数
73.
GROUP BY 和HAVING 子句 GROUP BY 子句 用于将信息划分为更小的组 每一组行返回针对该组的单个结果 HAVING 子句 用于指定 GROUP BY 子句检索行的条件 SELECT p_category, MAX(itemrate) FROM itemfile GROUP BY p_category; SELECT p_category, MAX(itemrate) FROM itemfile GROUP BY p_category HAVING p_category NOT IN ('accessories');
分析函数 2-2以下三个分析函数用于计算一个行在一组有序行中的排位,序号从 1 开始 ROW_NUMBER 返回连续的排位,不论值是否相等 RANK 具有相等值的行排位相同,序数随后跳跃 DENSE_RANK 具有相等值的行排位相同,序号是连续的 SELECT ename, job, deptno, sal, ROW_NUMBER() OVER (ORDER BY sal DESC) AS SAL_RANK FROM SCOTT.EMP; SELECT deptno, ename, sal, comm, RANK() OVER (PARTITION BY deptno ORDER BY sal DESC, comm) RANK FROM emp; SELECT d.dname, e.ename, e.sal, DENSE_RANK() OVER (PARTITION BY e.deptno ORDER BY e.sal DESC) AS DENRANK FROM emp e, dept d WHERE e.deptno = d.deptno;
行级锁 3-3SELECT … FOR UPDATE 语法 : SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT]; SQL> SELECT * FROM order_master WHERE vencode=’V002’ FOR UPDATE OF odate, del_date; SQL> UPDATE order_master SET del_date=’28-8 月 -05’ WHERE vencode=’V002’; SQL> COMMIT; SQL> SELECT * FROM order_master WHERE vencode=’V002’ FOR UPDATE WAIT 5; SQL> SELECT * FROM order_master WHERE vencode=’V002’ FOR UPDATE NOWAIT;
87.
表级锁 3-1修改表中的行 更新表 拒绝访问 锁定整个表,限制其他用户对表的访问。 GI Joe Barbie Name 45 T002 20 T001 Price Toy_ID
表分区 允许用户将一个表分成多个分区 用户可以执行查询,只访问表中的特定分区将不同的分区存储在不同的磁盘,提高访问性能和安全性 可以独立地备份和恢复每个分区 更新表 只访问 P1 P1 分区 P2 分区 US California 9 th Road Jack Jones US New York 53 rd Road Jim Taylor US New York 12 th Street Bob Simmons US New York LK Rd. Micheal Clarke US California 34 th Rd. John Smith Country State Address Name
表分区的类型 9-2范围分区 以表中的一个列或一组列的值的范围分区 范围分区的语法: PARTITION BY RANGE (column_name) ( PARTITION part1 VALUE LESS THAN(range1), PARTITION part2 VALUE LESS THAN(range2), ... [PARTITION partN VALUE LESS THAN(MAXVALUE)] );
94.
表分区的类型 9-3范围分区示例 SQL> CREATE TABLE Sales ( Product_ID varchar2 (5), Sales_Cost number (10) ) PARTITION BY RANGE (Sales_Cost) ( PARTITION P1 VALUES LESS THAN (1000), PARTITION P2 VALUES LESS THAN (2000), PARTITION P3 VALUES LESS THAN (3000) ); 根据 Sales_Cost 创建分区 分区的名称 包含销售成本低于 1000 的所有产品的值 SQL> CREATE TABLE SALES2 ( PRODUCT_ID VARCHAR2(5), SALES_DATE DATE NOT NULL, SALES_COST NUMBER(10)) PARTITION BY RANGE (SALES_DATE) ( PARTITION P1 VALUES LESS THAN (DATE ‘2003-01-01’), PARTITION P2 VALUES LESS THAN (DATE ‘2004-01-01’), PARTITION P3 VALUES LESS THAN (MAXVALUE) );
表分区的类型 9-7列表分区示例 SQL> CREATE TABLE Employee ( Emp_ID number (4), Emp_Name varchar2 (14), Emp_Address varchar2 (15) ) PARTITION BY LIST (Emp_Address) ( Partition north values (‘ 芝加哥 '), Partition west values (‘ 旧金山’ , ‘ 洛杉矶 '), Partition south values (‘ 亚特兰大’ , ‘ 达拉斯’ , ‘ 休斯顿 '), Partition east values (‘ 纽约’ , ‘ 波斯顿 ') ); 包含住在芝加哥的职员的记录 根据职员住址在表上创建的列表分区 分区的名称
99.
表分区的类型 9-8复合分区 范围分区与散列分区或列表分区的组合 复合分区的语法: PARTITION BY RANGE (column_name1) SUBPARTITION BY HASH (column_name2) SUBPARTITIONS number_of_partitions ( PARTITION part1 VALUE LESS THAN(range1), PARTITION part2 VALUE LESS THAN(range2), ... PARTITION partN VALUE LESS THAN(MAXVALUE) );
100.
表分区的类型 9-9复合分区示例 SQL> CREATE TABLE SALES ( PRODUCT_ID VARCHAR2 (5), SALES_DATE DATE NOT NULL, SALES_COST NUMBER (10) ) PARTITION BY RANGE (SALES_DATE) SUBPARTITION BY HASH (PRODUCT_ID) SUBPARTITIONS 5 ( PARTITION S1 VALUES LESS THAN (TO_DATE(‘01/4 月 /2001', 'DD/MON/YYYY')), PARTITION S2 VALUES LESS THAN (TO_DATE(‘01/7 月 /2001', 'DD/MON/YYYY')), PARTITION S3 VALUES LESS THAN (TO_DATE(‘01/9 月 /2001', 'DD/MON/YYYY')), PARTITION S4 VALUES LESS THAN (MAXVALUE) ); 创建的四个范围分区的名称 在表的 Sales_Date 列中创建范围分区 在表的 Product_ID 列创建散列子分区 在每个范围分区中 创建 5 个散列子分区
101.
操纵已分区的表 在已分区的表中插入数据与操作普通表完全相同,Oracle 会自动将数据保存到对应的分区 查询、修改和删除分区表时可以显式指定要操作的分区 INSERT INTO SALES3 VALUES (‘P001’, ’02-3 月 -2001', 2000); INSERT INTO SALES3 VALUES (‘P002’, ’10-5 月 -2001', 2508); INSERT INTO SALES3 VALUES (‘P003’, ’05-7 月 -2001', 780); INSERT INTO SALES3 VALUES (‘P004’, ’12-9 月 -2001', 1080); SELECT * FROM SALES3 PARTITION (P3); DELETE FROM SALES3 PARTITION (P2);
创建视图 3-3使用 WITH CHECK OPTION 选项创建视图 CREATE OR REPLACE VIEW pause_view AS SELECT * FROM order_master WHERE ostatus = 'p' WITH CHECK OPTION CONSTRAINT chk_pv; 使用 ORDER BY 子句创建视图 CREATE OR REPLACE VIEW ord_ven AS SELECT * FROM vendor_master ORDER BY venname; 创建带有错误的视图 CREATE FORCE VIEW ven AS SELECT * FROM venmaster;
120.
联接视图 2-1Stud_details Sub_details CREATE VIEW Stud_sub_view AS SELECT Studno, Studname, Submrks, Subname FROM Stud_details, Sub_Details WHERE Stud_details.Subno=Sub_details.Subno; Stud_sub_view 联接视图 4 33 James 2 4 40 Jesica 3 2 45 Rob 1 Subno Submrks Studname Studno Science 5 Maths 4 English 2 Subname Subno English 45 Rob 1 Maths 40 Jesica 3 Maths 33 James 2 Subname Submrks Studname Studno
121.
联接视图 2-2创建外联接视图 CREATE VIEW ven_ord_outj_view AS SELECT vm.vencode, venname, orderno, odate, ostatus FROM vendor_master vm, order_master om WHERE vm.vencode = om.vencode(+); SELECT vm.vencode, venname, orderno, odate, ostatus FROM vendor_master vm LEFT OUTER JOIN order_master om ON vm.vencode = om.vencode;
索引 3-3SQL> CREATE INDEX item_index ON itemfile (itemcode) TABLESPACE index_tbs; 创建标准索引 重建索引 SQL> ALTER INDEX item_index REBUILD; 删除索引 SQL> DROP INDEX item_index;
128.
唯一索引 唯一索引确保在定义索引的列中没有重复值 Oracle 自动在表的主键列上创建唯一索引 使用 CREATE UNIQUE INDEX 语句创建唯一索引 SQL> CREATE UNIQUE INDEX item_index ON itemfile (itemcode);
129.
组合索引 组合索引是在表的多个列上创建的索引 索引中列的顺序是任意的如果 SQL 语句的 WHERE 子句中引用了组合索引的所有列或大多数列,则可以提高检索速度 SQL> CREATE INDEX comp_index ON itemfile(p_category, itemrate);
数字数据类型 指定数值的存储格式 数字数据类型NUMBER BINARY_INTEGER PLS_INTEGER NATURAL NATURALLN POSITIVE POSITIVEN DECIMAL FLOAT INTEGER REAL SIGNTYPE 存储有符号整数,所需存储空间少于 NUMBER 类型值 存储整数、实数和浮点数 存储有符号整数,可使算术计算快速而有效
150.
字符数据类型 字符数据类型包括: CHARVARCHAR2 LONG RAW LONG RAW PL/SQL 的数据类型与 SQL 数据类型的比较 1..32767 1..4000 VARCHAR2 1..32767 1..2000 RAW 1..32760 1..2GB LONG RAW 1..32760 1..2GB LONG 1..32767 1..2000 CHAR PL/SQL 类型 SQL 类型 数据类型
控制结构 PL/SQL 支持的流程控制结构: 条件控制 IF 语句 CASE 语句 循环控制 LOOP 循环 WHILE 循环 FOR 循环 顺序控制 GOTO 语句 NULL 语句
157.
条件控制 2-1IF 语句根据条件执行一系列语句,有三种形式: IF-THEN 、 IF-THEN-ELSE 和 IF-THEN-ELSIF DECLARE icode VARCHAR2(4); irate NUMBER; BEGIN icode := 'i203'; SELECT itemrate INTO irate FROM itemfile WHERE itemcode = icode; IF irate > 200 THEN UPDATE itemfile SET itemrate = itemrate - 200 WHERE itemcode = icode; ELSE UPDATE itemfile SET itemrate = itemrate - 50 WHERE itemcode = icode; END IF; DBMS_OUTPUT.PUT_LINE('itemrate='|| irate); END;
158.
条件控制 2-2BEGIN CASE ‘&grade’ WHEN ’A’ THEN DBMS_OUTPUT.PUT_LINE(’ 优异’ ); WHEN ’B’ THEN DBMS_OUTPUT.PUT_LINE ( 优秀’ ); WHEN ’C’ THEN DBMS_OUTPUT.PUT_LINE (’ 良好’ ); WHEN ’D’ THEN DBMS_OUTPUT.PUT_LINE (’ 一般’ ); WHEN ’F’ THEN DBMS_OUTPUT.PUT_LINE (’ 较差’ ); ELSE DBMS_OUTPUT.PUT_LINE (’ 没有此成绩’ ); END CASE; END; CASE 语句用于根据单个变量或表达式与多个值进行比较 执行 CASE 语句前,先计算选择器的值
159.
循环控制 循环控制用于重复执行一系列语句 循环控制语句包括:LOOP 、 EXIT 和 EXIT WHEN 循环控制的三种类型: LOOP - 无条件循环 WHILE - 根据条件循环 FOR - 循环固定的次数 LOOP sequence_of_statements END LOOP; WHILE condition LOOP sequence_of_statements END LOOP; FOR counter IN [REVERSE] value1..value2 LOOP sequence_of_statements END LOOP;
160.
顺序控制 顺序控制用于按顺序执行语句 顺序控制语句包括:GOTO 语句 - 无条件地转到标签指定的语句 NULL 语句 - 什么也不做的空语句 DECLARE qtyhand itemfile.qty_hand%type; relevel itemfile.re_level%type; BEGIN SELECT qty_hand,re_level INTO qtyhand,relevel FROM itemfile WHERE itemcode = 'i201'; IF qtyhand < relevel THEN GOTO updation; ELSE GOTO quit; END IF; <<updation>> UPDATE itemfile SET qty_hand = qty_hand + re_level WHERE itemcode = 'i201'; <<quit>> NULL; END;
161.
动态 SQL动态 SQL 是指在 PL/SQL 程序执行时生成的 SQL 语句 编译程序对动态 SQL 不做处理,而是在程序运行时动态构造语句、对语句进行语法分析并执行 DDL 语句命令和会话控制语句不能在 PL/SQL 中直接使用,但是可以通过动态 SQL 来执行 执行动态 SQL 的语法: EXECUTE IMMEDIATE dynamic_sql_string [INTO define_variable_list] [USING bind_argument_list]; DECLARE sql_stmt VARCHAR2(200); emp_id NUMBER(4) := 7566; emp_rec emp%ROWTYPE; BEGIN EXECUTE IMMEDIATE 'CREATE TABLE bonus1 (id NUMBER, amt NUMBER)'; sql_stmt := 'SELECT * FROM emp WHERE empno = :id'; EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING emp_id; END;
错误处理 2-2处理预定义异常 处理用户定义异常 DECLARE ordernum VARCHAR2(5); BEGIN SELECT orderno INTO ordernum FROM order_master; EXCEPTION WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE (' 返回多行 '); END; DECLARE invalidCATEGORY EXCEPTION; category VARCHAR2(10); BEGIN category := '&Category'; IF category NOT IN (' 附件 ',' 顶盖 ',' 备件 ') THEN RAISE invalidCATEGORY; ELSE DBMS_OUTPUT.PUT_LINE(' 您输入的类别是 '|| category); END IF; EXCEPTION WHEN invalidCATEGORY THEN DBMS_OUTPUT.PUT_LINE(' 无法识别该类别 '); END;
164.
RAISE_APPLICATION_ERROR 过程用于创建用户定义的错误信息 可以在可执行部分和异常处理部分使用 错误编号必须介于 – 20000 和 – 20999 之间 错误消息的长度可长达 2048 个字节 引发应用程序错误的语法: RAISE_APPLICATION_ERROR(error_number, error_message); 引发应用程序错误 DECLARE rate itemfile.itemrate%TYPE; rate_exception EXCEPTION; BEGIN SELECT NVL(itemrate,0) INTO rate FROM itemfile WHERE itemcode = 'i207'; IF rate = 0 THEN RAISE rate_exception; ELSE DBMS_OUTPUT.PUT_LINE(' 项费率为: ' || rate); END IF; EXCEPTION WHEN rate_exception THEN RAISE_APPLICATION_ERROR(-20001, ' 未指定项费率 '); END;
隐式游标 4-2SQL> SET SERVEROUTPUT ON SQL> BEGIN UPDATE toys SET toyprice=270 WHERE toyid= 'P005'; IF SQL%FOUND THEN DBMS_OUTPUT.PUT_LINE(‘ 表已更新 '); END IF; END; / 只有在 DML 语句影响一行 或多行时,才返回 True
173.
隐式游标 4-3SQL> SET SERVEROUTPUT ON SQL> DECLARE v_TOYID TOYS.ID%type := '&TOYID'; v_TOYNAME TOYS.NAME%Type := '&TOYNAME'; BEGIN UPDATE TOYS SET NAME = v_TOYNAME WHERE toyid=v_TOYID; IF SQL%NOTFOUND THEN DBMS_OUTPUT.PUT_LINE(' 编号未找到。 '); ELSE DBMS_OUTPUT.PUT_LINE(‘ 表已更新 '); END IF; END; / 如果 DML 语句不影响任何行,则返回 True
174.
隐式游标 4-4SQL> SET SERVEROUTPUT ON SQL> BEGIN UPDATE vendor_master SET venname= 'Rob Mathew' WHERE vencode='V004'; DBMS_OUTPUT.PUT_LINE (SQL%ROWCOUNT); END; / 返回 DML 语句影响的行数
175.
SELECT INTO 语句 2-1 SQL> SET SERVEROUTPUT ON SQL> DECLARE empid VARCHAR2(10); desig VARCHAR2(10); BEGIN empid:= '&Employeeid'; SELECT designation INTO desig FROM employee WHERE empno=empid; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE(' 职员未找到 '); END; / 如果没有与 SELECT INTO 语句中的条件匹配的行,将引发 NO_DATA_FOUND 异常
176.
SELECT INTO 语句 2-2 SQL> SET SERVEROUTPUT ON SQL> DECLARE empid VARCHAR2(10); BEGIN SELECT empno INTO empid FROM employee; EXCEPTION WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE(' 该查询提取多行 '); END; / 如果 SELECT INTO 语句返回多个值, 将引发 TOO_MANY_ROWS 异常
177.
显式游标 2-1显式游标在 PL/SQL 块的声明部分定义查询,该查询可以返回多行 显式游标的操作过程: 数据库 打开游标 提取行 变量 关闭游标 30 George 3 44 Roger 2 45 James 1 Stud_mrks Stud_name stud_no
178.
显式游标 2-2SQL>SET SERVER OUTPUT ON SQL>DECLARE my_toy_price toys.toyprice%TYPE; CURSOR toy_cur IS SELECT toyprice FROM toys WHERE toyprice<250; BEGIN OPEN toy_cur; LOOP FETCH toy_cur INTO my_toy_price; EXIT WHEN toy_cur%NOTFOUND; DBMS_OUTPUT.PUT_LINE ('TOYPRICE=: 玩具单价 = : '||my_toy_price); END LOOP; CLOSE toy_cur; END; 声明游标 打开游标 提取行 关闭游标
179.
带参数的显式游标 声明显式游标时可以带参数以提高灵活性 声明带参数的显式游标的语法如下:CURSOR <cursor_name>(<param_name> <param_type>) IS select_statement; SQL> SET SERVEROUTPUT ON SQL> DECLARE desig VARCHAR2(20); emp_code VARCHAR2(5); empnm VARCHAR2(20); CURSOR emp_cur(desigparam VARCHAR2) IS SELECT empno, ename FROM employee WHERE designation=desig; BEGIN desig:= '&desig'; OPEN emp_cur(desig); LOOP FETCH emp_cur INTO emp_code,empnm; EXIT WHEN emp_cur%NOTFOUND; DBMS_OUTPUT.PUT_LINE(emp_code||' '||empnm); END LOOP; CLOSE emp_cur; END;
180.
使用显式游标更新行 2-1允许使用游标删除或更新活动集中的行 声明游标时必须使用 SELECT … FOR UPDATE 语句 CURSOR <cursor_name> IS SELECT statement FOR UPDATE; UPDATE <table_name> SET <set_clause> WHERE CURRENT OF <cursor_name> 更新的语法 DELETE FROM <table_name> WHERE CURRENT OF <cursor_name> 删除的语法
181.
使用显式游标更新行 2-2SQL> SET SERVEROUTPUT ON SQL> DECLARE new_price NUMBER; CURSOR cur_toy IS SELECT toyprice FROM toys WHERE toyprice<100 FOR UPDATE OF toyprice; BEGIN OPEN cur_toy; LOOP FETCH cur_toy INTO new_price; EXIT WHEN cur_toy%NOTFOUND; UPDATE toys SET toyprice = 1.1*new_price WHERE CURRENT OF cur_toy; END LOOP; CLOSE cur_toy; COMMIT; END;
182.
循环游标 2-1循环游标用于简化游标处理代码 当用户需要从游标中提取所有记录时使用 循环游标的语法如下: FOR <record_index> IN <cursor_name> LOOP <executable statements> END LOOP;
183.
循环游标 2-2SQL> SET SERVER OUTPUT ON SQL> DECLARE CURSOR mytoy_cur IS SELECT toyid, toyname, toyprice FROM toys; BEGIN FOR toy_rec IN mytoy_cur LOOP DBMS_OUTPUT.PUT_LINE( ‘ 玩具编号: '||' ' ||toy_rec.toyid||' ' ||‘ 玩具名称: '||' '||toy_rec.toyname||' ' ||‘ 玩具单价: '||' '||toy_rec.toyprice); END LOOP; END;
REF 游标和游标变量 3-2 打开游标变量的语法如下: OPEN cursor_name FOR select_statement; TYPE my_curtype IS REF CURSOR RETURN stud_det%ROWTYPE; order_cur my_curtype; 声明强类型的 REF 游标 TYPE my_ctype IS REF CURSOR; stud_cur my_ctype; 声明弱类型的 REF 游标
186.
REF 游标和游标变量 3-3 SQL> DECLARE TYPE toys_curtype IS REF CURSOR RETURN toys%ROWTYPE; toys_curvar toys_curtype; toys_rec toys%ROWTYPE; BEGIN OPEN toys_curvar FOR SELECT * FROM toys; FETCH toys_curvar INTO toys_rec; ... CLOSE toys_curvar; END; 声明 REF 游标类型 声明游标变量
使用游标变量执行动态 SQL可以使用游标变量执行动态构造的 SQL 语句 打开执行动态 SQL 的游标变量的语如下: OPEN cursor_name FOR dynamic_sqlstring [USING bind_argument_list]; DECLARE r_emp emp%ROWTYPE; TYPE c_type IS REF CURSOR; cur c_type; p_salary NUMBER; BEGIN p_salary := 2500; OPEN cur FOR 'select * from emp where sal>:1 order by sal desc' USING p_salary; DBMS_OUTPUT.PUT_LINE(' 薪水大于 '|| p_salary ||' 的员工有: '); LOOP FETCH cur INTO r_emp; EXIT WHEN cur%NOTFOUND; DBMS_OUTPUT.PUT_LINE(' 编号: '|| r_emp.empno || ' 姓名: ' || r_emp.ename|| ' 薪水: ' || r_emp.sal ); END LOOP; CLOSE cur; END;
过程 8-3CREATE OR REPLACE PROCEDURE find_emp(emp_no NUMBER) AS empname VARCHAR2(20); BEGIN SELECT ename INTO empname FROM EMP WHERE empno = emp_no; DBMS_OUTPUT.PUT_LINE(' 雇员姓名是 '|| empname); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE (' 雇员编号未找到 '); END find_emp; /
198.
过程 8-4过程参数的三种模式: IN 用于接受调用程序的值 默认的参数模式 OUT 用于向调用程序返回值 IN OUT 用于接受调用程序的值,并向调用程序返回更新的值
199.
过程 8-5执行过程的语法: EXECUTE procedure_name(parameters_list); SQL> CREATE OR REPLACE PROCEDURE itemdesc(item_code IN VARCHAR2) IS v_itemdesc VARCHAR2(5); BEGIN SELECT itemdesc INTO v_itemdesc FROM itemfile WHERE itemcode = item_code; DBMS_OUTPUT.PUT_LINE(item_code|| ' 项目的说明为 '||v_itemdesc); END; / SQL> SET SERVEROUTPUT ON SQL> EXECUTE itemdesc('i201');
200.
过程 8-6SQL> CREATE OR REPLACE PROCEDURE test( value1 IN VARCHAR2, value2 OUT NUMBER ) IS identity NUMBER; BEGIN SELECT ITEMRATE INTO identity FROM itemFile WHERE itemcode = value1; IF identity < 200 THEN value2:=100; END IF; END; DECLARE value1 VARCHAR2(5) := 'i202'; value2 NUMBER; BEGIN test (value1, value2); DBMS_OUTPUT.PUT_LINE('value2 的值为 ' || TO_CHAR(value2)); END; /
201.
过程 8-7CREATE OR REPLACE PROCEDURE swap(p1 IN OUT NUMBER, p2 IN OUT NUMBER) IS v_temp NUMBER; BEGIN v_temp := p1; p1 := p2; p2 := v_temp; END; / SQL> SET SERVEROUT ON SQL> DECLARE num1 NUMBER := 100; num2 NUMBER := 200; BEGIN swap(num1, num2); DBMS_OUTPUT.PUT_LINE('num1 = ' || num1); DBMS_OUTPUT.PUT_LINE('num2 = ' || num2); END; /
202.
过程 8-8将过程的执行权限授予其他用户: 删除过程: SQL> GRANT EXECUTE ON find_emp TO MARTIN; SQL> GRANT EXECUTE ON swap TO PUBLIC; SQL> DROP PROCEDURE find_emp;
函数 4-2定义函数的限制: 函数只能接受 IN 参数,而不能接受 IN OUT 或 OUT 参数 形参不能是 PL/SQL 类型 函数的返回类型也必须是数据库类型 访问函数的两种方式: 使用 PL/SQL 块 使用 SQL 语句
205.
函数 4-3创建函数: 从 SQL 语句调用函数: CREATE OR REPLACE FUNCTION fun_hello RETURN VARCHAR2 IS BEGIN RETURN ' 朋友,您好 '; END; / SQL> SELECT fun_hello FROM DUAL;
206.
函数 4-4CREATE OR REPLACE FUNCTION item_price_range (price NUMBER) RETURN VARCHAR2 AS min_price NUMBER; max_price NUMBER; BEGIN SELECT MAX(ITEMRATE), MIN(ITEMRATE) INTO max_price, min_price FROM itemfile; IF price >= min_price AND price <= max_price THEN RETURN ' 输入的单价介于最低价与最高价之间 '; ELSE RETURN ' 超出范围 '; END IF; END; / DECLARE P NUMBER := 300; MSG VARCHAR2(200); BEGIN MSG := item_price_range(300); DBMS_OUTPUT.PUT_LINE(MSG); END; /
创建程序包 2-2CREATE OR REPLACE PACKAGE pack_me IS PROCEDURE order_proc (orno VARCHAR2); FUNCTION order_fun(ornos VARCHAR2) RETURN VARCHAR2; END pack_me; / CREATE OR REPLACE PACKAGE BODY pack_me AS PROCEDURE order_proc (orno VARCHAR2) IS stat CHAR(1); BEGIN SELECT ostatus INTO stat FROM order_master WHERE orderno = orno; …… END order_proc; FUNCTION order_fun(ornos VARCHAR2) RETURN VARCHAR2 IS icode VARCHAR2(5); ocode VARCHAR2(5); BEGIN …… END order_fun; END pack_me; /
程序包中的游标 2-2SQL> CREATE OR REPLACE PACKAGE cur_pack IS CURSOR ord_cur(vcode VARCHAR2) RETURN order_master%ROWTYPE; PROCEDURE ord_pro(vcode VARCHAR2); END cur_pack; / SQL> CREATE OR REPLACE PACKAGE BODY cur_pack AS CURSOR ord_cur(vcode VARCHAR2) RETURN order_master%ROWTYPE IS SELECT * FROM order_master WHERE VENCODE=vcode; PROCEDURE ord_pro(vcode VARCHAR2) IS or_rec order_master%ROWTYPE; BEGIN OPEN ord_cur(vcode); LOOP FETCH ord_cur INTO or_rec; EXIT WHEN ord_cur%NOTFOUND; DBMS_OUTPUT.PUT_LIne(’ 返回的值为 ' || or_rec.orderno); END LOOP; END ord_pro; END cur_pack; /
216.
有关子程序和程序包的信息 USER_OBJECTS 视图包含用户创建的子程序和程序包的信息 USER_SOURCE 视图存储子程序和程序包的源代码 SELECT object_name, object_type FROM USER_OBJECTS WHERE object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY'); SELECT line, text FROM USER_SOURCE WHERE NAME='TEST';
创建触发器的语法 CREATE [ORREPLACE] TRIGGER trigger_name AFTER | BEFORE | INSTEAD OF [INSERT] [[OR] UPDATE [OF column_list]] [[OR] DELETE] ON table_or_view_name [REFERENCING {OLD [AS] old / NEW [AS] new}] [FOR EACH ROW] [WHEN (condition)] pl/sql_block;
触发器的组成部分 3-2 SQL> CREATE OR REPLACE TRIGGER trig_sal AFTER UPDATE OF empsal ON salary_records … 触发器语句 为 salary_records 表创建 trig-sal 触发器 在更新 emp_sal 列之后激活触发器 触发器限制 SQL> … FOR EACH ROW WHEN (NEW.empsal>OLD.empsal) DECLARE Sal_diff NUMBER; … 只有在 WHEN 子句中的条件得到满足时,才激活 trig_sal 触发器 触发器操作 SQL> … BEGIN sal_diff:=:NEW.empsal-:OLD.empsal; DBMS_OUTPUT.PUT_LINE(‘ 工资差额:’ sal_diff); END; 如果 WHEN 子句中的条件得到满足,将执行 BEGIN 块中的代码
225.
触发器的组成部分 3-3Oracle 数据库 更新 表 保存更新 激活 触发器 AFTER 触发器的工作原理 BEFORE 触发器的工作原理 更新 表 激活 触发器 保存更新 Oracle 数据库
226.
创建触发器 CREATE ORREPLACE TRIGGER aiu_itemfile AFTER INSERT ON itemfile FOR EACH ROW BEGIN IF (:NEW.qty_hand = 0) THEN DBMS_OUTPUT.PUT_LINE(' 警告:已插入记录,但数量为零 '); ELSE DBMS_OUTPUT.PUT_LINE(‘ 已插入记录 '); END IF; END; /
触发器类型 6-3行级触发器 SQL> CREATE TABLE TEST_TRG (ID NUMBER, NAME VARCHAR2(20)); SQL> CREATE SEQUENCE SEQ_TEST; SQL> CREATE OR REPLACE TRIGGER BI_TEST_TRG BEFORE INSERT OR UPDATE OF ID ON TEST_TRG FOR EACH ROW BEGIN IF INSERTING THEN SELECT SEQ_TEST.NEXTVAL INTO :NEW.ID FROM DUAL; ELSE RAISE_APPLICATION_ERROR(-20020, ' 不允许更新 ID 值! '); END IF; END; /
230.
触发器类型 6-4语句级触发器 SQL> CREATE OR REPLACE TRIGGER trgdemo AFTER INSERT OR UPDATE OR DELETE ON order_master BEGIN IF UPDATING THEN DBMS_OUTPUT.PUT_LINE(‘ 已更新 ORDER_MASTER 中的数据 '); ELSIF DELETING THEN DBMS_OUTPUT.PUT_LINE(‘ 已删除 ORDER_MASTER 中的数据 '); ELSIF INSERTING THEN DBMS_OUTPUT.PUT_LINE(‘ 已在 ORDER_MASTER 中插入数据 '); END IF; END; /
231.
触发器类型 6-5INSTEAD OF 触发器 SQL> CREATE OR REPLACE TRIGGER upd_ord_view INSTEAD OF UPDATE ON ord_view FOR EACH ROW BEGIN UPDATE order_master SET vencode=:NEW.vencode WHERE orderno = :NEW.orderno; DBMS_OUTPUT.PUT_LINE(‘ 已激活触发器 '); END; /
232.
触发器类型 6-6模式触发器 SQL> CREATE TABLE dropped_obj ( obj_name VARCHAR2(30), obj_type VARCHAR2(20), drop_date DATE); SQL> CREATE OR REPLACE TRIGGER log_drop_obj AFTER DROP ON SCHEMA BEGIN INSERT INTO dropped_obj VALUES( ORA_DICT_OBJ_NAME, ORA_DICT_OBJ_TYPE, SYSDATE); END; /
233.
启用和禁用触发器 删除触发器 启用、禁用和删除触发器SQL> ALTER TRIGGER aiu_itemfile DISABLE; SQL> ALTER TRIGGER aiu_itemfile ENABLE; SQL> DROP TRIGGER aiu_itemfile;
234.
查看有关触发器的信息 USER_TRIGGERS 数据字典视图包含有关触发器的信息 SQL> SELECT TRIGGER_NAME FROM USER_TRIGGERS WHERE TABLE_NAME='EMP'; SQL> SELECT TRIGGER_TYPE, TRIGGERING_EVENT, WHEN_CLAUSE FROM USER_TRIGGERS WHERE TRIGGER_NAME = 'BIU_EMP_DEPTNO';
内置程序包 8-2一些内置程序包: 用 PL/SQL 程序来读写操作系统文本文件 UTL_FILE 提供 XSLT 功能,转换 XML 文档 DBMS_XSLPROCESSOR 提供将数据转换为 XML 类型的功能 DBMS_XMLQUERY XML 解析,处理 XML 文档内容和结构 DBMS_XMLPARSER 用 DOM 模型读写 XML 类型的数据 DBMS_XMLDOM 允许用户使用动态 SQL DBMS_SQL 提供随机数生成器 DBMS_RANDOM 处理 PL/SQL 块和子程序输出调试信息 DBMS_OUTPUT 提供对 LOB 数据类型进行操作的功能 DBMS_LOB 定义和扩展 PL/SQL 语言环境 STANDARD 和 DBMS_STANDARD 说明 程序包名称
237.
内置程序包 8-3DBMS_OUTPUT 包显示 PL/SQL 块和子程序的调试信息。 SQL> SET SERVEROUTPUT ON SQL> BEGIN DBMS_OUTPUT.PUT_LINE(' 打印三角形 '); FOR i IN 1..9 LOOP FOR j IN 1..i LOOP DBMS_OUTPUT.PUT('*'); END LOOP for_j; DBMS_OUTPUT.NEW_LINE; END LOOP for_i; END; /
238.
内置程序包 8-4DBMS_LOB 包提供用于处理大型对象的过程和函数 DBMS_XMLQUERY 包用于将查询结果转换为 XML 格式
239.
内置程序包 8-5SQL> DECLARE result CLOB; xmlstr VARCHAR2(32767); line VARCHAR2(2000); line_no INTEGER := 1; BEGIN result := DBMS_XMLQuery.getXml('SELECT empno, ename FROM employee'); xmlstr := DBMS_LOB.SUBSTR(result,32767); LOOP EXIT WHEN xmlstr IS NULL; line := SUBSTR(xmlstr,1,INSTR(xmlstr,CHR(10))-1); DBMS_OUTPUT.PUT_LINE(line_no || ':' || line); xmlstr := SUBSTR(xmlstr,INSTR(xmlstr,CHR(10))+1); line_no := line_no + 1; END LOOP; END; /
240.
内置程序包 8-6DBMS_RANDOM 包可用来生成随机整数 SQL> SET SERVEROUTPUT ON SQL> DECLARE l_num NUMBER; counter NUMBER; BEGIN counter:=1; WHILE counter <= 10 LOOP l_num := DBMS_RANDOM.RANDOM; DBMS_OUTPUT.PUT_LINE(l_num); counter:=counter+1; END LOOP; END; /
241.
内置程序包 8-7UTL_FILE 包用于读写操作系统文本文件 操作文件的一般过程是打开、读或写、关闭 UTL_FILE 包指定文件路径依赖于 DIRECTORY 对象 SQL> CREATE DIRECTORY TEST_DIR AS 'C:\DEVELOP'; SQL> GRANT READ, WRITE ON DIRECTORY TEST_DIR TO SCOTT;
242.
内置程序包 8-8SQL> SET SERVEROUTPUT ON SQL> DECLARE input_file UTL_FILE.FILE_TYPE; input_buffer VARCHAR2(4000); BEGIN input_file := UTL_FILE.FOPEN( 'TEST_DIR', 'employees.xml', 'r'); LOOP UTL_FILE.GET_LINE(input_file,input_buffer); DBMS_OUTPUT.PUT_LINE(input_buffer); END LOOP; UTL_FILE.FCLOSE(input_file); EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('------------------'); END; /