本文主要为参考文献[1]的学习笔记。
Oracle SQL和PL/SQL笔记
第1章 开始使用Oracle Server
1.Oracle Database的安装
Ø 指定Oracle主目录位置。
Ø 不创建启动数据库。
Ø 选择企业版。
2. 建立数据库
Ø 开始->菜单->Oracle->OraDb10g_home1->Configuration and Migration Tools->Database Configuration Assistant.
Ø 输入全局数据库名和数据库例程SID。
Ø 设置账号和口令,其它选项接收默认即可。
3. 使用Net Manager配置监听程序和网络服务名
Ø 开始->菜单->Oracle->OraDb10g_home1->Configuration and Migration Tools->Net Manager
Ø 在默认监听程序Listener中添加数据库。输入主机IP地址或主机名,监听端口1521。数据库服务中输入全局数据库名,Oracle主目录和SID。
Ø 重启监听程序。在Windows操作系统的服务中重启OracleOraDb10g_home1TNSListener服务。
Ø 在Net Manager的“服务命名”中点击加号形状的按钮。输入Net服务名,主机名,1521端口及SID。
4 sql*plus工具
Ø 命令行语法:sqlplus [username]/[passwd] [@server] [AS SYSDBA] [AS SYSOPER]
Ø 连接数据库:d:/> sqlplus scott/tiger@demo
Ø 窗口环境的sql*plus:开始->菜单->Oracle->OraDb10g_home1->Application Development->SQL Plus.
Ø 浏览器环境的isql*plus:需启动isqlplus*plus服务器:isqlplusctl start;访问URL http://hostname:port/isqlplus即可。
5 PL/SQL Developer
为PL/SQL集成开发环境。其中命令窗口实现了sql*plus的全部功能。
第2章 SQL和PL/SQL综述
1 数据库基本概念
数据库管理系统:支持三级结构两级映射的数据管理软件。
数据库:由数据库管理系统管理,具有较少冗余,较高独立性、支持多用户共享、并且有相互联系的文件的集合。
三级数据视图:数据抽象的三个层次,外部视图、全局视图、存储视图。
两级映射:外部视图与全局视图间的逻辑映射;全局视图与存储视图之间的物理映射。
模式:使用DDL精确定义数据视图的程序。
三级模式:子模式(外模式);模式(逻辑模式);内模式(物理模式)。
数据模型:抽象描述现实世界的方法,表示实体和实体之间的联系。
关系模型:用二维表格数据表示实体和实体之间联系的模型。
关系:关系模型中的一张二维表。元组,属性,属性名,域。
关系模式:关系的表头,即关系中属性名的集合,为关系的型。
DBMS组成:DDL;DML;数据库管理例行程序。
数据字典:数据库系统中涉及到的对象的描述信息,以数据文件的形式组织起来。
数据库系统:数据库、DBMS、DBA和应用系统组成的集合。
2 SQL标准
SQl-89, SQL-92, SQL-99。SQL99标准是ANSI,ISO, IEC标准,分5个部分(Part1:SQL/Framework, Part2: Foundation/SQL Foundation, Part4: Persistent Stored Modules(SQL/PSM), Part5: Host Language Binding(SQL/Bindings)。一般一百页左右,最厚的第二部分超过一千页。描述貌似使用的是BNF范式。
3 SQl语言分类
Ø 数据查询语言(SELECT)
Ø 数据操纵语言(DML):INSERT, UPDATE, DELETE
Ø 数据定义语言(DDL): CREATE, ALTER, DROP
Ø 数据控制语言(DCL): GRANT, REVOKE
Ø 事务控制语句(TCS):COMMIT, ROLLBAK, SAVEPOINT
Ø 会话控制语句(SCL): ALTER SESSION, SET ROLE
Ø 系统控制语句(SCS): ALTER SYSTEM
4 Oracle数据库对象
表、索引、约束、视图、序列、同义词、过程、函数、触发器、对象类型。
1 查询所有列
SELECT * FROM table_name;
2 查询指定列
SELECT column1,..., columnN FROM table_name;
3 使用列别名与表别名
SELECT alias.column1 [AS] aliasOfCol1, ... , alias.columnN aliasOfColN FROM table_name alias;
列别名含特殊字符时使用双引号。
4 排除重复行
SELECT DISTINCT column1,... ,column2 FROM table_name;
5 处理NULL
Ø 当插入数据时未提供值,且该列没有默认值时,该列结果为NULL.
Ø 使用NVL函数提供默认值;NVL(X,Y)表示列X为NULL时返回Y。
Ø NVL2; NVL2(X, Y, Z)表示X非NULL时返回Y,为NULL时返回Z。
6查询日期列
Ø 设置会话的日期的语言显示格式:
ALTER SESSION SET nls_date_language = 'SIMPLIFIED CHINESE';
ALTER SESSION SET nls_date_language = 'AMERICAN';
Ø 设置会话的日期的显示格式:
ALTER SESSION SET nls_date_format = 'YYYY''-''MM''-''DD';
Ø 使用TO_CHAR定制日期的显示格式:
SELECT t.crtime, TO_CHAR(t.crtime, 'YYYY-MM-DD') FROM table_name t;
7 连接字符串
Ø ||: SELECT col1 || col2 FROM table_name;
Ø CONCAT: SELECT CONCAT(col1, col2) FROM table_name;
第4章 限制数据
1 WHERE子句中使用常规比较符:>, <, >=, <=, !=, <>, =
Ø 注意这里的等于(=)不是C语言里的等于(==),另外不等于有两个:<> 和!=。
Ø 常规比较符可用于数字,字符串,日期。字符串必须使用单引号。
Ø SELECT * FROM emp WHERE hiredate > to_date('2009-11-07', 'YYYY-MM-DD');
Ø SELECT * FROM emp WHERE UPPER(job) = 'CLEARK';
2 其它比较操作符
Ø BETWEEN AND操作符指定范围
Ø LIKE操作符模糊匹配字符串
%表示0个或多个字符;
_表示单个字符;
ESCAPE 'char' 用于指定转义符,转义符后跟%或_用于取消它们的特殊含义。
例如:
SELECT * FROM emp WHERE ename LIKE '%a_%' ESCAPE 'a';
用来查询ename中包含下划线的记录。
Ø IN操作符,匹配列表中的项。
SELECT * FROM protocol t WHERE t.type IN ('HTTP', 'DNS', 'FTP');
Ø IS NULL操作符:检测结果是否为NULL。
Ø 逻辑操作符AND, OR, NOT.. 优先级NOT>AND>OR。可使用括号改变计算的优先级。NOT用于对特定条件取反,IS NOT NULL是最常见的。一个不恰当的例子如下:
WHERE X AND (NOT (Y<Z))等价于WHERE X AND Y>=Z.
3 示例
Rownum是一个伪列,表示符合条件的记录的序号。
Ø SELECT * FROM table_name WHERE rownum < n; --可用<=, n>1时正确。
Ø SELECT * FROM table_name WHERE rownum < n; --只有n = 1时正确。
Ø SELECT * FROM table_name WHERE rownum > n; -- n>0时为空集,n = 0时为全集。
Ø 查询符合条件的第XX条到第YY条记录:
SELECT XX, YY FROM
(SELECT XX, YY, rownum AS XYZ FROM table_name WHERE ZZ >20)
WHERE XYZ BETWEEN 10 AND 20;
另一种方式,使用集合间的差,可能比上面的使用子查询更耗资源:
SELECT XX, YY FROM table_name WHERE ZZ>20 AND rownum < 20
MINUS
SELECT XX, YY FROM table_name WHERE ZZ>20 AND rownum < 10;
Ø 查询某个时间段的数据
SELECT * FROM tablename t
WHERE t.crtime BETWEEN
TO_DATE('2009-11-10 11:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND
TO_DATE('2009-11-10 12:00:00', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY t.crtime DESC;
1 ORDER BY子句
Ø ORDER BY col1 [ASC|DESC], ... , colN [ASC|DESC]
Ø Order by子句必须为SELECT的最后一个子句。
Ø ORDER BY可跟一列或多列排序;默认为升序(ASC), DESC表示降序。
Ø 若排序列有NULL,升序排列时,NULL行在最后面,降序排列时,NULL行在最前面。
Ø 使用多列排序:SELECT * FROM emp ORDER BY deptno ASC, sal DESC;
Ø 使用列位置排序,列位置从1开始:SELECT * FROM emp ORDER BY 1 DESC;
第6章 SQL单行函数
1 单行函数指输入一行,输出一行的函数,多行函数指输入多行输出一行的函数。单独调用单行函数时可使用数据字典dual。
Ø 函数很多,最好下一个函数手册可供参考。PL/SQL Developer中键入函数时,会有参数说明。不知道有没有像类似man这样的官方手册。这里只做简单的列举。
2 数字函数
Ø 很多语言的数字函数名称都差不多。
Ø ROUND:四舍五入,例如ROUND(AVG(t.salary),6)保留6位小数。
Ø TRUNC:截断
Ø SIG: 符号函数,负数-1,整数1,0返回0.
3 字符函数
Ø 若SQL函数返回的CHAR或者VARCHAR2值超出长度限制,则会被截断并返回。如果返回的CBLOB值超出长度限制则显示错误消息。
Ø UPPER、LOWER用于大小写转换
Ø INSTR用于字串查找,类似与C中的strstr和C++中的find.
SELECT instr('Great Wall In China', 'China') FROM dual;
Ø SUBSTR用于得到字串。
Ø LPAD,RPAD用于左右填充。
Ø TREAM用于截断指定字符,例如
SELECT * FROM fault_type d WHERE TRIM(trailing ' ' from d.type_desc) = 'INVALID_PARM';
为截取尾部空格的例子。默认时为截取头部和尾部。可分别指定leading, trailing, both。
4 日期函数
Ø SYSDATE: 返回当前系统时间。
5 转换函数
Ø TO_CHAR: 将其它类型转换为字符串
Ø TO_DATE:将字符串转换为日期
Ø TO_NUMBER: 转换为NUMBER。
6正则式函数
Ø Oracle基于POSIX和Unicode标准实现了正则表达式。如果已经熟悉了grep,应该可以找到熟悉的感觉。
Ø 各种字符样式:
.: 匹配单个字符
+:匹配该符号前出现一次或多次的子表达式。
?匹配该符号前出现一次或0次的子表达式。
*:匹配该符号前出现0次或多次的子表达式。
{m, n}:匹配该符号前出现至少m次,不超过n次的子表达式。
[]:用于匹配列表中的任意字符。列表中以^开头表示取反。
|:用于匹配二选一。
():括号内表达式作为一个单元。
/n;匹配该符号前第n次重复出现的子表达式。
/:取消元字符的特殊含义。
^与$匹配字符串的开始和结束。
[:class:]:用于匹配POSIX类别,例如upper,digit, alnum, space等。
/d与/D:用于匹配数字字符和非数字字符。
/w与/W:用于匹配单词和非单词。
/s与/S:用于匹配空格和非空格。
/A用于匹配字符串的开始
/Z和/z用于匹配字符串的结束。
Ø 正则式函数:REGXP_LIKE, REGXP_INSTR, REGXP_SUBSTR, REGXP_REPLACE。
第7章 操纵数据
本章主要为数据控制语言DML和事务控制语句TCS。
使用中字符串需用单引号括起来。
1 INSERT语句
(1)语法:
INSERT INTO table_name [column1,...,columnN] VALUES(value1,...valueN);
(2)不指定列列表时,需按顺序为所有列提供数据。
INSERT INTO dept VALUES(50, 'TRAIN', 'BOSTON');
(3)使用列列表时,只需为相应列增加数据即可。必须为主键列和非空列提供数据。
INSERT INTO emp(empno, empname, hiredate)
VALUES(1355, 'MARK', TO_DATE('2008-07-01', 'YYYY-MM-DD'));
可使用DEFAULT代替VALUES中的值,若有默认值则为默认值,否则为NULL。
(4)Oracle中使用替代变量插入数据:
编写脚本C:/loademp.sql,内容如下:
ACCEPT no PROMPT '请输入雇员号:';
ACCEPT no PROMPT '请输入雇员名:';
INSERT INTO emp(empno, empname) VALUES(&no, '&name');
说明:
ACCEPT 语句用于读取输入的数据,PROMPT后跟的是提示语句;
VALUES中的&类似与C语言中scanf的读取输入,字符串不要忘了加单引号。
加载此脚本时,在PL/SQL Developer的命令窗口中键入命令:@c:/loademp即可。或者直接将脚本内容复制到命令窗口也可以。
2 子查询复制数据
(1)常规装载方式,可使用目标表的HWM(High Water Mark)以下空间。可提高表段空间利用率,但速度较慢。
INSERT INTO employee(empno, ename, sal, deptno)
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 20;
(2)直接装载方式,不能使用目标表HWM,但速度很快。
INSERT /*+APPEND*/ INTO employee(empno, ename, sal, deptno)
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 20;
3 INTO子句中使用子查询
INSERT的INTO子句中可以指定表,视图和子查询。使用WITH CHECK OPTION选项,表示限制被插入的数据满足子查询的条件。
INSERT INTO (SELECT empno, ename, sal, deptno FROM emp
WHERE deptno = 30 WITH CHECK OPTION)
VALUES(1112, 'MARY', 2000, 30);
此时数据被插入到子查询的基本表中。
4 多表插入
多表插入表示用子查询将一张表的数据根据条件插入到多张表中。
(1)无条件INSERT ALL
将子查询的所有结果无条件的复制到多个表中。
INSERT ALL
INTO sal_history VALUES(ename, hiredate, sal)
INTO mgr_history VALUES(ename, mgr, sal)
SELECT ename hiredate, mgr, sal FROM emp;
(2)有条件INSERT ALL
将子查询的结果根据不同的条件插入到不同的表中
INSERT ALL
WHEN sal > 1000 THEN
INTO sal_history VALUES(ename, hiredate,sal)
WHEN mgr > 7000 THEN
INTO mgr_history VALUES(ename, mgr, sal)
SELECT ename, hiredate, mgr, sal FROM emp;
这里的WHEN相当与C语言中的多个独立的if条件。
(3)有条件INSERT FIRST
INSERT ALL
WHEN sal > 3000 THEN
INTO sal_history VALUES(ename, hiredate,sal)
WHEN mgr > 1000 THEN
INTO mgr_history VALUES(ename, mgr, sal)
ELSE
INTO low_history VALUES(ename, hiredate, sal)
SELECT ename, hiredate, mgr, sal FROM emp;
这里的WHEN相当C语言中的if..else if...else if...else.
5 UPDATE更新数据
(1)表达式更新数据
UPDATE emp SET sal = sal*1.1, comm. = sal*0.1 WHERE deptno = 20;
(2)子查询更新
UPDATE emp SET (job, sal, comm.) = (
SELECT job, sal, comm. FROM emp WHERE ename = 'SMITH')
WHERE ename = 'SCOTT';
--复制表数据
UPDATE employee SET deptno = (
SELECT deptno FROM emp WHERE empno = 7799)
WHERE job = (SELECT job FROM emp WHERE empno = 7799);
6 使用MERGE语句
若行存在,则执行UPDATE,否则执行INSERT, ON用于指定连接条件.
MERGEI NTO new n USING emp e
ON (n.empno = e.empno)
WHEN MATCHED THEN
UPDATE SET n.sal = e.sal
WHEN NOT MATCHED THEN
INSERT(n.empno, n.ename, n.sal, n.comm)
VALUES(n.empno, e.ename, e.sal, e.comm);
7 删除数据
DELETE删除不会释放表空间,TRUNCATE会释放表空间,DROP会删除表结构。
(1)条件删除
DELETE FROM emp WHERE ename = 'SCOTT';
(2)删除所有数据
DELETE FROM emp;
(3)截断表
TRUNCATE TABLE emp;
(4)使用子查询删除数据
DELETE FROM emp WHERE deptno = (SELECT deptno FROM dept WHERE dname = 'SALES');
DELET删除主表数据时,需确保从表不存在相关记录。
8 事务控制
(1)执行事务操作DML时,Oracle会在表上加锁,防止表结构被更改;同时被作用的行上加锁,防止其它事务在相应行执行DML。COMMIT后会结束事务,删除保存点,释放锁。
(2)提交事务:COMMIT;
回退事务:ROLLBACK;
设置保存点:
SAVEPOINT point_name;
或exec dbms_transaction.savepoint('point_name');
取消部分事务
ROLLBACK TO point_name;
或exec dbms_transaction.rollback;
(3)只读事务
只读事务不会取得新的数据变化,用于取得具体时间点的数据。
SET TRANSACTION READ ONLY;
或exec dbms_transaction.read_only;
(4)顺序事务
只读事务,使得会话不能执行DML操作。为了允许DML操作,可使用顺序事务。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
设置只读事务和顺序事务时,SET语句必须为事务开始的第一条语句。即之前的DML语句必须COMMIT后才能继续SET语句。
第8章 连接查询
1 等值连接
SELECT dept.dname, emp.ename, emp.sal FROM emp, dept
WHERE emp.deptno = dept.deptno AND dept.deptno = 10;
2 不等连接
使用等值比较符号之外的其它比较操作符。如BETWEEN...AND。
3 自连接
主要用于显示上下级或层次关系。
SELECT worker.ename, manager.ename
FROM emp worker, emp manager
WHERE worker.mgr = manager.deptno;
4 外连接
Ø 不仅返回满足条件的记录,而且返回不满足条件的部分记录。
Ø 使用+号,如WHERE table1.col1(+) = table2.clo2表示返回等值连接记录和table2中不满足条件的记录。
Ø +号位于显示较少行的一端。只适用与列,不能和OR和IN操作符一起使用。
Ø 示例:表s中的字段sf取值是表t中字段tf的一个子集。现在需要查看表s中是否有记录不满足该条件。
SELECT * FROM(
SELECT s.sf s_sf, t.tf t_sf
FROM s, t
WHERE s.sf = t.tf(+)
)
WHERE t_sf IS NULL;
5 SQL:1999连接
(1)笛卡尔积—CROSS JOIN
SELECT d.dname, e.ename FROM dept d CROSS JOIN emp e;
(2)自然连接—Natural JOIN
自然连接基于两张表的同名列执行相等连接。
SELECT d.dname, e.ename FROM dept d NATURAL JOIN emp e;
(3)USING—选择某相同列进行连接
SELECT d.dname, e.ename FROM dept d, emp e USING(deptno);
(4)ON子句—连接列名不同时可使用
SELECT d.dname, e.ename FROM dept d JOIN emp e
ON e.deptno = d.deptno AND e.deptno = 10;
(5)LEFTER [OUTER] JOIN--左连接
SELECT d.dname, e.ename FROM dept d LEFT JOIN emp e
ON e.deptno = d.deptno AND e.deptno = 10;
(6)RIGHT [OUTER] JOIN –右连接
SELECT d.dname, e.ename FROM dept d RIGHT JOIN emp e
ON e.deptno = d.deptno AND e.deptno = 10;
(7)FULL [OUTER] JOIN—完全外连接
SELECT d.dname, e.ename FROM dept d FULL JOIN emp e
ON e.deptno = d.deptno AND e.deptno = 10;
第9章 数据分组
1 分组函数
MAX, MIN, AVG, SUM, COUNT
VARIANCE 方差STDDEV 标准偏差
2 GROUP BY 与 HAVING
(1)GROUP BY用于指定分组列,HAVING用于限制分组显示结果。
(2)GROUP可用于单列和多列分组
SELECT deptno, job, avg(sal) FROM emp GROUP BY deptno, job;
(3)HAVING限制分组
SELECT deptno, job, avg(sal) FROM emp GROUP BY deptno, job
HAVING avg(sal) < 2500;
(4)数据分组需注意
Ø 分组函数只能出现在选择列表、ORDER BY子句、HAVING子句中
Ø 分组函数会忽略NULL行
Ø 使用分组函数时,可在函数中指定ALL或DISTINCT,默认为ALL。
Ø ORDER BY子句必须在最后面。
Ø 选择列表中的列、表达式必须出现在GROUP BY子句中。
3 ROLLUP与CUBE
(1)GROUP BY中使用ROLLUP和CUBE可以生成小计和总计。
Ø ROLLUP(A, B)先按A,B分组统计,再按A分组统计,最后计算总的统计;
Ø CUBE操作符会生成A,B统计,A统计,B统计,总统计;
Ø GROUP BY ROLLUP(a, b, c)等价于GROUP BY(a, b, c) 、GROUP BY(a,b)、GROUP(a)、GROUP()的并集;
Ø GROUP BY CUBE(a, b, c)等于所有组合情况的并集;
Ø 示例:
SELECT deptno, job, avg(sal) FROM emp GROUP BY ROLLUP(deptno, job);
SELECT deptno, job, avg(sal) FROM emp GROUP BY ROLLUP(deptno, job);
(2)GROUPING函数
Ø ROLLUP和CUBE中确定统计结果是否使用了某列,返回0 表示使用了,返回1表示没有使用该列。
Ø SELECT deptno, job, avg(sal), GROUPING(deptno), GROUPING(job)
FROM emp GROUP BY ROLLUP(deptno, job);
(3)ROLLUP和CUBE中使用复合列
Ø ROLLUP(a, (b,c))等价于GROUP BY(a,b,c)、GROUP BY a, GROUP BY ()的并集;
Ø CUBE((a,b),c)等价于GROUP BY(a, b, c)、GROUP BY(a, b)、GROUP BY c、GROUP BY()的并集。
4 GROUPING SETS操作符
Ø GROUPING SETS用于显示多个分组的统计结果
Ø GROUP BY GROUPING SETS(a, b)等价于GROUP BY a与GROUP BY b的并集。
Ø SELECT deptno, job, avg(sal) FROM emp
GROUP BY GROUPING SETS(deptno, job);
5 连接分组
Ø 连接分组用于组合不同分组的统计结果。
Ø 在GROUP BY子句中指定多个GROUPING SETS、CUBE、ROLLUP可以实现连接分组。
Ø 连接多个GROUPING SETS: GROUPING SETS(a, b), GROUPING SETS(c,d)会定义分组(a,b), (a,d), (b,c), (b,d);
SELECT deptno, job, mgr, sum(sal) FROM emp
GROUP BY GROUPING SETS(deptno), GROUPING SETS(job, mgr);
Ø 连接ROLLUP, GROUP BY后接a, ROLLUP(b,c)时,会定义分组(a,b,c)、(a,b)与(a)
SELECT deptno, job, mgr, sum(sal) FROM emp
GROUP BY deptno, ROLLUP(job, mgr);
Ø 连接CUBE: 连接CUBE, GROUP BY后接a, CUBE(b,c)时,会定义分组(a,b,c)、(a,b), (a,c)与(a)
SELECT deptno, job, mgr, sum(sal) FROM emp
GROUP BY deptno, CUBE(job, mgr);
第10章 子查询
1 单行子查询
Ø 返回一行数据的子查询语句。可使用单行比较符(=,>=, <=, <, >, <>)。
Ø SELECT * FROM emp WHERE deptno =
(SELECT deptno FROM dept WHERE deptname = 'Tech');
2 多行子查询
Ø 多行子查询指返回多行数据的子查询语句。多行子查询可使用IN, ALL, ANY.
3 多列子查询
Ø 多列子查询指返回多列数据的子查询语句。与单列的差不多。
Ø SELECT * FROM emp WHERE (sal, nvl(comm., -1)) IN
(SELECT sal, nvl(comm, -1) FROM emp WHERE deptno = 30);
4 相关子查询
Ø 子查询引用到主SQL语句的表列时,执行相关子查询;主SQL语句可以是SELECT,UPDATE, DELETE语句;普通子查询只执行一次子查询,相关子查询,每处理一行主SQL语句,都会执行一次相关子查询。
Ø UPDATE示例,表table_test有month_id, num两列,表示月份id和数据,现有增加一列sum,表示该月及以前的月份的数据总和。
ALTER TABLE tab_test add sum NUMBER;
UPDATE table_test t
SET t.sum = (SELECT sum(d.num) FROM table_test d WHERE
d.month_id <= t.month_id);
也可以使用分析函数over直接用查询得到结果:
SELECT t.month_id, t.num, SUM(t.num) OVER(order by t.month_id)
FROM table_test t;
--得到季度数据
SELECT t.month_id, t.num, SUM(t.num) OVER(PARTITION by TRUNC((t.month_id – 1)/3)) FROM table_test t;
SELECT t.month_id, t.num, SUM(t.num) OVER(PARTITION by TRUNC((t.month_id – 1)/3) ORDER BY t.month_di)
FROM table_test t;
Ø EXISTS操作符用于检测子查询是否存在返回行,有返回行时,条件值为true,否则为false;NOT EXISTS 与EXISTS相反。
SELECT ename, sal, deptno FROM emp e WHERE EXISTS
(SELECT 1 FROMdept WHERE deptno = e.deptno AND loc = 'NEW YORK');
5 DDL中使用子查询
Ø SELECT与DML中使用子查询时,WHERE子句和SET子句不能包含ORDER BY子句,DDL中使用时可以包含。DDL使用子查询如CREATE [TABLE | VIEW | MATERIALIZED VIEW].
CREATE TABLE new_emp(id, name, sal, job, deptno) AS
SELECT empno, enmae, sal, job, deptno FROM emp;
--只复制表结构
CREATE TABLE new AS SELECT * FROM emp WHERE 1 = 0;
6 FROM中使用子查询
Ø FROM中子查询被当作视图看待,必须指定别名。
SELECT ename, job, sal FROM emp,
(SELECT deptno, avg(sal) avgsal FROM emp GROUP BY deptno) dept
WHERE emp.deptno = dept.deptno AND sal > dept.avgsal;
7 WITH子句重用子查询
多次引用相同的查询块,可以使用WITH子句为子查询取名,多次引用。
WITH
Dept_sum AS(
SELECT d.dname, sum(e.sal) total FROM dept d, emp e
WHERE d.deptno = e.deptno GROUP BY d.dname),
Dept_avg_sum AS(
SELECT sum(total)/COUNT(*) avg_num FROM dept_sum)
SELECT dname, total FROM dept_sum
WHERE total > (SELECT avg_sum FROM dept_avg_sum);
第11章 PL/SQL基础
1 PL/SQL块:PL/SQL的基本程序单元
Ø PL/SQL块结构
DELCARE
--定义常量、变量、数据类型、游标
BEGIN
--PL/SQL语句和SQL语句
EXCEPTION
--异常处理
END;
Ø PL/SQL块分类
匿名块、命名块、子程序(过程、函数、包)、触发器
² 命名块在块前加<<block_name>>即可
2 数据类型
Ø 标量类型、符合类型、参照类型、LOB类型
Ø %TYPE可根据表列或其它变量的类型定义新变量
Ø 复合变量包括PL/SQL记录、PL/SQL表、嵌套表、VARRAY。
Ø REF CURSOR用于定义游标变量;REF obj_type用于定义对象指针。
Ø 子类型:已存在数据类型的子集:
SUBTYPE subtype_name IS base_type [(constraint)] [NOT NULL];
3 代码编写规则
变量:前缀v_
常量:前缀c_
游标:后缀_cursor
例外:前缀e_
PL/SQL表类型:后缀_table_type
PL/SQL记录类型:后缀_record_type
第12章 SQL*Plus
1 连接命令
Ø [CONNECT | CONN] user/passwd@SID
Ø [DISCONNECT | DISC] user/passwd@SID
Ø PASSWORD | PASSW
Ø EXIT | QUIT --退出SQL*Plus
2 编辑命令
SQL*Plus会缓存SQL语句,编辑命令可以显示、编辑修改SQL缓冲区内容。此处编辑命令大多数不用于PL/SQL Developer。
Ø LIST | L --列出缓冲区内容
Ø DEL --删除当前行内容,可指定起始与结束行号。
Ø EDIT | ED --编辑
Ø RUN | / --运行缓存区中的SQL.
3 文件操作
Ø SAVE file [CREATE | APPEND | REPLACE] --保存缓冲区SQL
Ø GET file --加载文件至缓冲区
Ø START | @ file --执行sql脚本
Ø @@ --执行可嵌套脚本的sql脚本。
Ø EDIT --编辑缓冲区内容
Ø SPOOL --保存SQL*Plus屏幕内容至文件
SPOOL file
Execute SQL
SPOOL OFF
4 交互式命令
Ø &var --引用替代变量,字符类型需用单引号,只在当前语句有效
Ø &&var --同&var, 在SQL*Plus环境中有效
Ø DEFINE --定义类型为CHAR的替代变量
DEFINE title = BOB
Ø UNDEFINE --清除替代变量的定义
Ø ACCEPT –定义CHAR, NUMBER, DATE的替代变量。
ACCEPT title PROMPT ‘请输入标题:'
ACCEPT pwd hide --隐藏用户输入
Ø PROMPT --提示信息
Ø PAUSE --暂停
Ø VARIABLE | VAR --定义绑定变量
VAR no NUMBER
Ø PRINT –输出绑定变量结果
5 环境变量
Ø Showall --显示环境变量
Show variable --显示指定环境变量
Set variable on|off --设置或进制环境变量
Ø 一些环境变量
AUTOCOMMIT --是否自动提交DML
SERVEROUTPUT --控制服务器输出,dbms_output包需设置此变量为ON
TERMOUT --控制SQL脚本的输出,OFF则不会显示结果
TIME --SQL提示符是否显示时间
TIMING --是否显示SQL语句的执行时间。
后记
负责向Oracle数据库写数据的家伙竟然从来没有接触过Oracle,这可能是个笑话,然而却是真实存在的。于是就有了这篇笔记。在校期间的数据库课程[2]提供了一个理论上的入门,打下了一定的基础。不得不承认,高等教育的课程设置比较完备,如果真的都学精了,那绝对是人才。可惜我一向都学得半生不熟的。不过这不是问题,用到的时候再学就可以了。文献[1]只能算是Oracle学习之路上的一个开端。看第一遍的时候觉得有些东西没理解,当时明白了,之后又觉得比较模糊。于是决定写一下笔记,整理一下思路。写到一部分的时候,发现自己并不擅长于做笔记,特别是需要耗费比较多的时间。书籍是借过来看的,也许是担心以后参考的时候没有资料查阅,这也是做笔记的一个原因。不过现在没有这个必要了。入门之后直接查阅资料就可以了。OTN(Oracle Technology Network)上的资料非常的丰富。下载之后就可以离线查阅了。
如果可能,本文将不断的更新。
[1] 王海亮,张立民,王海风等。精通Oracle 10g SQL和PL/SQL[M]. 北京:中国水利水电出版社,2007.
[2] 杨开英。数据库系统概论[M]. 武汉:武汉理工大学出版社,2003.