oracle基础知识(二)

来源:互联网 发布:js加载速度慢 编辑:程序博客网 时间:2024/04/28 15:57
第五章 分组函数 -- 分组函数会对结果集中的一组记录计算一次,每一组只返回一个结果1. MAX(列|表达式) MIN(列|表达式)练习:查询emp中员工工资的最大值SELECT MAX(sal), MIN(sal)FROM emp;2. SUM -- 求和    AVG -- 取平均值练习:查询emp表中20部门员工的工资总和SELECT SUM(sal)FROM empWHERE deptno = 20;-- 所有的分组函数都是忽略空值练习:查询emp表中员工平均补助(comm)SELECT AVG(nvl(comm, 0))FROM emp;SELECT 550 *14 FROM dual;3. COUNT -- 计数练习:查询emp表中30部门的员工数SELECT COUNT(*)FROM empWHERE deptno = 30;练习:查询emp表中员工所在的部门有几个SELECT COUNT(DISTINCT deptno)FROM emp;练习:查询emp表中各个部门的工资的最大值SELECT deptno, MAX(sal)FROM empGROUP BY deptnoORDER BY deptno;练习:查询emp表中各个职位员工工资的平均值SELECT job, AVG(sal)FROM empGROUP BY job;-- 必须要使用子查询练习:查询emp表中各个部门的工资最高的员工的姓名以及工资SELECT ename, deptno, MAX(sal)FROM empGROUP BY ename, deptnoORDER BY deptno;-- 两个原则 -- 1. group by 子句中出现的列,可以不在select子句中出现; -- 2. select 子句出现的非分组函数列,一定要在group by子句中出现; 练习:查询emp表中平均工资在2000以上的部门编号和平均工资SELECT deptno, AVG(sal)FROM emp--WHERE AVG(sal) > 2000GROUP BY deptnoHAVING AVG(sal) > 2000;-- 在where子句中不能出现对分组函数结果的判断-- 对分组函数结果的筛选需要在having子句中-- 是SQL语句的执行顺序决定的练习:查询emp表中员工数多于5人的部门编号以及员工数SELECT deptno, COUNT(*)FROM empGROUP BY deptnoHAVING COUNT(*) > 5;-- 分组函数的嵌套(最多嵌套两层)练习:查询emp表中各部门的平均人数SELECT AVG(COUNT(*))FROM empGROUP BY deptno;  

第六章 多表查询-- 笛卡尔积-- A = {a, b}-- B = {1,2,3}-- A × B = {(a, 1), (a, 2),(a, 3),(b, 1),(b, 2),(b, 3)}-- 1. 笛卡尔积元素数量非常庞大,非常耗费系统资源-- 2. 有意义的数据只占一小部分-- 结论:在多表查询中一定要避免产生笛卡尔积-- 方法:一定要为连接的表设定连接条件,两个表连接,至少需要1个连接条件。-- 连接条件:一般是两个表的公共字段。-- 公共字段:(狭义)两个表中列名和列的数据类型都相同的那些列;--                 (广义)两个表中意义相同的那些列1. 等值连接(连接条件用=来判断的称之为等值连接)练习:查询emp表中员工姓名,部门编号以及部门名称SELECT emp.ename, emp.deptno, dept.deptno, dept.dnameFROM emp, deptWHERE emp.deptno = dept.deptnoORDER BY emp.ename; -- 表别名 -- 表名 表别名 -- 表别名中不能包含特殊字符 -- 如果在SQL中给表起了别名了,那么在当前的SQL的任何地方都不能再使用表名,只能 -- 引用表别名SELECT e.ename, e.deptno, d.deptno, d.dnameFROM emp e, dept dWHERE e.deptno = d.deptnoORDER BY e.ename;2. 不等值连接(连接条件不是用=进行判断)练习:查询emp表中员工姓名,工资以及工资等级SELECT e.ename, e.sal, s.gradeFROM emp e, salgrade sWHERE e.sal BETWEEN s.losal AND s.hisalORDER BY e.ename;练习:查询emp表中20部门员工的姓名,工资,部门名称以及工资等级SELECT E.ENAME, E.SAL, D.DNAME, S.GRADE  FROM EMP E, DEPT D, SALGRADE S WHERE E.DEPTNO = D.DEPTNO   AND E.SAL BETWEEN S.LOSAL AND S.HISAL   AND E.DEPTNO = 20;3. 外连接-- 外连接的符号(+)永远是在连接条件的缺乏表的一端,要查询哪个表的全部记录,另一张表就是缺乏表练习:列出所有部门名称和员工的姓名,即使这个部门没有员工SELECT d.dname, e.enameFROM emp e, dept dWHERE e.deptno(+) = d.deptnoORDER BY d.dname;练习:查询emp表中员工的姓名和部门编号,即使这个员工没有部门SELECT d.dname, e.enameFROM emp e, dept dWHERE e.deptno = d.deptno(+)ORDER BY d.dname;练习:查询没有员工部门的名称SELECT D.DNAME  FROM EMP E, DEPT D WHERE E.DEPTNO(+) = D.DEPTNO   AND ENAME IS NULL ORDER BY D.DNAME; 作业:查询没有部门员工的姓名4. 自连接-- 查询结果和条件都需要从同一张表中查询的问题-- 用自连接-- 语法晦涩,不常用。-- 日常工作中我们通常用子查询来代替自连接练习:查询emp表中和SMITH同部门的员工信息,不包括SMITHSELECT A.*  FROM EMP A, EMP B WHERE A.DEPTNO = B.DEPTNO   AND B.ENAME = 'SMITH'   AND A.ENAME <> 'SMITH';

第七章 子查询-- 查询结果和条件都需要从同一个表中查出来的问题练习:查询emp表中和SMITH同部门的员工信息,不包括SMITHSELECT *  FROM EMP WHERE ENAME <> 'SMITH'   AND DEPTNO = (SELECT DEPTNO FROM EMP WHERE ENAME = 'SMITH');1. 子查询的分类  a. 单行子查询 - 子查询的结果集是一行一列,可以使用单行比较运算符进行比较练习:查询emp表中和SCOTT部门相同,且同领导的员工信息,不包括SMITH;SELECT *FROM empWHERE ename <> 'SCOTT'AND deptno = (SELECT deptno FROM emp WHERE ename = 'SCOTT')AND mgr = (SELECT mgr FROM emp WHERE ename = 'SCOTT');练习:查询emp表中部门人数多于平均部门人数的部门编号和人数SELECT DEPTNO, COUNT(*)  FROM EMP GROUP BY DEPTNOHAVING COUNT(*) > (SELECT AVG(COUNT(*))                                     FROM EMP                                     GROUP BY DEPTNO);  b. 多行子查询 - 子查询的结果集是多行一列的,不能使用单行比较运算符,要使用in练习:查询emp表中哪些员工是领导,列出他们的信息SELECT *FROM empWHERE empno IN (SELECT mgr FROM emp);练习:查询emp表中哪些员工不是领导,列出他们的信息SELECT *FROM empWHERE empno NOT IN (SELECT mgr FROM emp WHERE mgr IS NOT NULL);-- 1. 子查询结果集中出现了null-- 2. not in不忽略空值,在子查询中不能出现空值 a IN (1, 2, NULL) ==> a = 1 OR a = 2 OR a = NULL  a NOT IN (1, 2, NULL) ==> a <> 1 AND a <>2 AND a <> NULL    c. 多列子查询 - 查询结果集是多行多列形式练习:查询emp表中各个部门的工资最高的员工的姓名以及工资SELECT deptno, ename, salFROM empWHERE (deptno, sal) IN (SELECT deptno, MAX(sal) FROM emp GROUP BY deptno)ORDER BY deptno;(a,b) IN ((1,1), (2,2),(3,3));==> a = 1 AND b = 1 OR a = 2 AND b = 2 OR a = 3 AND b = 3; 2. FROM 子句中的子查询 -- 内联视图  - 视图:是一个虚表。视图也是表,所以和表的操作一样。但是视图没有实体数据,只是表的另一种表现方式  -- From子句中的子查询一定要给它起一个别名,作为视图名  -- 如果内联视图中出现了函数列或表达式列,一定要给这样的列起一个别名,就作为对应列的列名SELECT e.deptno, e.ename, e.salFROM emp e, (SELECT deptno, MAX(sal) maxsal FROM emp GROUP BY deptno) aWHERE e.deptno = a.deptno AND e.sal  = a.maxsalORDER BY e.deptno;练习:查询emp表中各个部门的工资最高的员工的姓名,工资以及部门名称SELECT e.deptno, e.ename, e.sal, d.dnameFROM emp e, (SELECT deptno, MAX(sal) maxsal FROM emp GROUP BY deptno) a, dept dWHERE e.deptno = a.deptno AND e.sal  = a.maxsal AND e.deptno = d.deptnoORDER BY e.deptno;SELECT B.ENAME, B.SAL, B.DNAME  FROM (SELECT E.ENAME, E.SAL, D.DNAME, E.DEPTNO          FROM EMP E, DEPT D         WHERE E.DEPTNO = D.DEPTNO) B,       (SELECT DEPTNO, MAX(SAL) MAXSAL FROM EMP GROUP BY DEPTNO) A WHERE A.DEPTNO = B.DEPTNO   AND A.MAXSAL = B.SAL; -- Top-N问题-- 伪列 rownum -- 所有的查询结果集中都有这样一个伪列 -- 作用是给结果集的记录进行编号  SELECT ROWNUM, dname FROM dept;  -- 1. rownum编号是在排序之前已经编好的。 练习:查询emp表中工资由高到低排在前三位的员工的信息SELECT rownum, a.ename, a.salFROM (SELECT ename, sal FROM emp ORDER BY sal DESC) aWHERE ROWNUM <= 3; -- 2. rownum 只能用 < 或<=来判断,不能用>或>=来判断,如果用=判断,只能=1 -- rownum 会动态重新编号 练习:查询emp表中工资由高到低排在4~6位的员工的信息 SELECT b.* FROM (SELECT ROWNUM r,a.ename bname,a.sal bsal FROM  (SELECT ename,sal FROM emp ORDER BY sal DESC  ) a WHERE ROWNUM <=6 ) b WHERE b.r>=4 SELECT B.*  FROM (SELECT ROWNUM R, A.ENAME, A.SAL          FROM (SELECT ENAME, SAL FROM EMP ORDER BY SAL DESC) A         WHERE ROWNUM <= 6) B WHERE B.R >= 4; -- 分页问题  --   CREATE TABLE TEST(N NUMBER); 表中的数据都是正整数,而且不重复  SELECT * FROM TEST ORDER BY N;  写一个SQL语句查询所有连续号码段的起始和结束号码   minnum        maxnum     3                    5     7                   10     12                 13  1. 方法1      SELECT AA.N MINNUM, BB.N MAXNUM       FROM (SELECT ROWNUM R, A.N               FROM (SELECT N                       FROM TEST                      WHERE (N - 1) NOT IN (SELECT N FROM TEST)                      ORDER BY N) A) AA,            (SELECT ROWNUM R, B.N               FROM (SELECT N                       FROM TEST                      WHERE (N + 1) NOT IN (SELECT N FROM TEST)                      ORDER BY N) B) BB      WHERE AA.R = BB.R;  2. 方法2  数据    -       数列       =      结果      n                  m                   n-m  n+1              m+1               n-m  n+2              m+2               n-m    n+4              m+3               n-m+1  n+5              m+4               n-m+1  n+6              m+5               n-m+1    n+9              m+6              n-m+3  n+10            m+7              n-m+3    SELECT MIN(B.N) MINNUM, MAX(B.N) MAXNUM    FROM (SELECT A.N - ROWNUM R, A.N FROM (SELECT N FROM TEST ORDER BY N) A) B   GROUP BY B.R   ORDER BY MINNUM;      SELECT MIN(A.N) MINNUM, MAX(A.N) MAXNUM    FROM (SELECT N FROM TEST ORDER BY N) A   GROUP BY A.N - ROWNUM   ORDER BY MINNUM;

第八章 数据操作与事务控制一. 数据插入 练习:向DEPT表中插入记录,编号 50, 部门名称 '实训', 部门所在地 '沈阳' INSERT INTO dept (dname, deptno, loc) VALUES ('实训', 50, '沈阳');  INSERT INTO dept VALUES (51, '实训', '沈阳');  练习:向DEPT表中插入记录,编号 60, 部门名称 '商用', 部门所在地待定 -- 1. 直接用null关键字   INSERT INTO dept VALUES (60, '商用', NULL); -- 2. 可以用两个连续的单引号来代表空值      INSERT INTO dept VALUES (61, '商用', ''); -- 3. 可以在指定列表的时候忽略空值列,被忽略的列如果没有设定默认值的话,就会插入空值   INSERT INTO dept (deptno, dname) VALUES (62, '商用');   练习:将自己的信息插入到emp表中(2012-3-5)。INSERT INTO emp VALUES (9999, 'Liu', 'CLERK', 7788, to_date('2012-3-5', 'YYYY-MM-DD'), 5001, NULL, 10);- 插入多条数据INSERT INTO emp1 SELECT * FROM emp WHERE deptno = 30;二. 更新数据练习:把emp表中scott的工资更新成3100UPDATE emp SET sal = 3100 WHERE ename = 'SCOTT';练习:给emp表中SMITH涨工资100UPDATE emp SET sal = sal + 100 WHERE ename = 'SMITH';练习:将SMITH的领导,部门更新跟SCOTT一样UPDATE emp SET mgr = (SELECT mgr FROM emp WHERE ename = 'SCOTT')                           , deptno = (SELECT deptno FROM emp WHERE ename = 'SCOTT')WHERE ename = 'SMITH';练习:给30部门工资最低的员工涨100UPDATE emp SET sal =sal + 100WHERE deptno = 30 AND sal = (SELECT MIN(sal) FROM emp WHERE deptno = 30);SELECT * FROM emp;练习:将自己的部门调到20部门,工资更新成20部门的平均工资 + 100,并四舍五入到个位三. 删除数据DELETE [FROM] 表名[WHERE 条件];DELETE FROM emp1; -- 删除emp1所有数据练习:将本部门工资比自己高的员工记录删除DELETE FROM EMP WHERE EMPNO IN       (SELECT EMPNO          FROM EMP E, (SELECT DEPTNO, SAL FROM EMP WHERE EMPNO = 9999) A         WHERE E.DEPTNO = A.DEPTNO           AND E.SAL > A.SAL);

第九章 表和约束(DDL)一. CREATE-- 作用:创建数据库对象-- create  DDL语句,隐式提交,不能回滚CREATE TABLE [SCHEMA.]表名 -- schema方案名(用户名)(       列名1 数据类型1 [DEFAULT 表达式],       列名2 数据类型2 [DEFAULT 表达式],        ...       列名N 数据类型N [DEFAULT 表达式]); - 数据类型  -1. 数字型   - NUMBER[(p[, s])]   -  - p 定义了数字的总长度   -  - s 定义了小数位的长度   - 例子  NUMBER(7,2)   -          NUMBER(4)   -          NUMBER    - 2. 字符型   - a. VARCHAR2(n)  - 可变长度的字符类型   -                            - n代表字符串的长度,n一定要设定,不能省略   -                            - n <= 4000      - b. CHAR[(n)]        - 固定长度的字符型   -                            - n可以省略,n默认是1   -                            - n <= 2000    - 3. LOB 型 -- 容纳4GB的数据   - a. 内部lob     - CLOB  -- 4GB字符型数据     - BLOB  -- 4GB二进制数据   - b. 外部lob      - BFILE  -- 4GB的外部文件      - 4. DATE - 日期型 练习:创建一个 dossier表 dID 数字型 dname 可变长度字符型 30 dheight 数字型 3 dbirthday 日期型 dcountrycode 固定长度字符型,默认值是‘01’ CREATE TABLE dossier(       did NUMBER,       dname VARCHAR2(30),       dheight NUMBER(3),       dbirthday DATE,       dcountrycode CHAR(2) DEFAULT '01');DROP TABLE dossier INSERT INTO dossier VALUES (1, '姚明', 226, to_date('1980-10-6', 'YYYY-MM-DD'), DEFAULT);COMMIT;INSERT INTO dossier (did, dname, dheight, dbirthday) VALUES (1, '姚明', 226, to_date('1980-10-6', 'YYYY-MM-DD'));SELECT * FROM dossier;  - 子查询建表  CREATE TABLE 表名 AS 子查询;    CREATE TABLE emp2 AS SELECT * FROM emp WHERE deptno =10;    SELECT * FROM emp2;  练习:用20部门员工的姓名和年薪 创建一个新表 annemp20CREATE TABLE annemp20ASSELECT ename, (sal + NVL(comm, 0)) * 12 annsalFROM empWHERE deptno = 20;SELECT * FROM User_Tables;SELECT ROWID, dnameFROM dossier;二. ALTER -- 属于DDL语句,自动提交,不能回滚 -- 修改对象的属性 1. 添加列 ALTER TABLE 表名 ADD (列名 数据类型[,...]);  练习:在dossier表中添加一列 sex 列,1位长度固定长度字符型ALTER TABLE dossier ADD (sex CHAR); 2. 修改列 ALTER TABLE 表名 MODIFY (列名 属性值); -- 1. 列名一定是在表中存在的列 -- 2. 修改那些属性,就把哪些属性放在列名后面就可以了 练习:为sex列添加默认值,默认为‘1’ALTER TABLE dossier MODIFY (sex DEFAULT '1'); -- 默认值的修改对表中现有列数据没有任何影响 -- 只会影响以后插入的数据。  -- 将某列更新成其默认值 UPDATE dossier  SET sex = DEFAULT WHERE did = 1;  3. 删除列   1> ALTER TABLE 表名 DROP COLUMN 列名;   2> ALTER TABLE 表名 DROP (列名列表);   练习:删除表中sex列ALTER TABLE dossier DROP (sex);  -- 注意:删除列会将列的定义和数据一并删除,不能回滚,在使用之前一定要慎重  -- 必要的时候要现将表中数据备份后再删除。  -- 表中必须至少要含有一列。   三. DROP  -- DDL语句,隐式提交不能回滚 -- 删除数据库对象 DROP TABLE 表名; DROP TABLE emp1; 四. 重命名表RENAME oldname TO NEWname;RENAME dossier TO ouxiang;     SELECT *FROM dossier;五. TRUNCATETRUNCATE TABLE 表名;-- 截断:删除表中所有的数据;TRUNCATE TABLE emp2;DELETE FROM emp2;-- 两种语句的区别-- 1. truncate是DDL语句,自动提交,不能回滚,而Delete是DML语句,能回滚;-- 2. truncate在删除数据的同时,会释放存储空间,delete不会做这样的事;-- 3. truncate只能删除所有数据,delete是可以有选择的删除;-- 4. truncate的效率要远远的高于delete,表越大越明显。回滚段五. 约束   定义在表中某列上的规则,防止错误数据进入表中;   1. 五种约束  1> NOT NULL :非空约束,插入到该列的数据不能为null;  2> UNIQUE     : 唯一键 约束,  该列数据在表中是唯一的,即不能重复;  3> PRIMARY KEY: 主键约束。表中的列或列的组合,其值在表中 可以唯一的确定一条记录;                                一个表只能有一个主键。                                主键的值必须是非空且唯一的。                                在表设计的时候,所有的表必须有主键。                                  4> FOREIGN KEY : 外键约束。表A和表B的公共字段如果是表A的主键或唯一键的话,那么                                 就是表B的外键。表A通常成为父表,表B称为子表。 外键是定义在子表上的。                                       i. 子表的公共字段中不能出现父表中没有的值      UPDATE emp SET deptno = 90 WHERE empno = 7788;      ii. 如果父表中的某一个值被子表所引用的话,这条数据不能被删除;      DELETE FROM dept WHERE deptno = 10;       5> CHECK :检查约束。在某列上定义的一个boolean表达式,要求插入到该列的值必须要保证                     boolean表达式为真,否则无法插入。  2. 约束定义   1> 列级约束定义      CREATE TABLE dossier(       did NUMBER PRIMARY KEY,       dname VARCHAR2(30) NOT NULL,       dheight NUMBER(3) UNIQUE,       dbirthday DATE,       dcountrycode CHAR(2) DEFAULT '01' REFERENCES country(countrycode));  2> 表级约束定义    CONSTRAINT 约束名 约束类型(列名)          CREATE TABLE dossier(       did NUMBER,       dname VARCHAR2(30),       dheight NUMBER(3),       dbirthday DATE NOT NULL,       dcountrycode CHAR(2) DEFAULT '01',       CONSTRAINT dossier_did_pk PRIMARY KEY(did),       CONSTRAINT dossier_dname_uk UNIQUE(dname),       CONSTRAINT dossier_dheight_ck CHECK(dheight > 0),       CONSTRAINT dossier_countycode_fk FOREIGN KEY(dcountrycode)                                                                REFERENCES county(countrycode) );-- not null只能做列级的约束定义,不能做表级的约束定义练习:创建一个country表  countrycode 两个字符长度固定字符类型 主键  countryname 非空    CREATE TABLE country  (         countrycode CHAR(2),         countryname VARCHAR2(30) NOT NULL,         CONSTRAINT county_code_pk PRIMARY KEY(countrycode)  );   INSERT INTO country VALUES('01', '中国');   SELECT * FROM country;  3> 给现有的表添加约束  ALTER TABLE 表名 ADD [CONSTRAINT 约束名] 约束类型(列名);练习:给dossier表添加主键约束ALTER TABLE dossier ADD CONSTRAINT dossier_did_pk PRIMARY KEY(did);     练习:给dossier表的dname列,添加唯一键约束ALTER TABLE dossier ADD CONSTRAINT dossier_dname_uk UNIQUE(dname);  练习:给dossier表添加check约束,身高不能小于0ALTER TABLE dossier ADD CONSTRAINT dossier_dheight_ck CHECK(dheight > 0);练习:给dossier表的生日列添加非空约束-- ALTER TABLE dossier ADD CONSTRAINT dossier_dbirthday_nn NOT NULL(dbirthday);ALTER TABLE dossier MODIFY (dbirthday NOT NULL); ALTER TABLE dossier ADD CONSTRAINT dossier_dbirthday_ck CHECK (dbirthday IS NO NULL);练习:给dossier表添加外键约束ALTER TABLE dossier ADD CONSTRAINT dossier_dcountrycode_fk FOREIGN KEY(dcountrycode) REFERENCES country(countrycode); 4> 删除约束 ALTER TABLE 表名 DROP CONSTRAINT 约束名; 练习:删除dossier表的唯一键约束ALTER TABLE dossier DROP CONSTRAINT dossier_dname_uk;练习:删除country表的主键约束ALTER TABLE country DROP CONSTRAINT county_code_pk CASCADE; 

原创粉丝点击