24 比普通员工最高薪水还要高的经理人 select ename from emp where empno in (select distinct mgr from emp where mgr is not null) and sal > ( select max(sal) from emp where empno not in (select distinct mgr from empwhere mgr is not null) ) / 求部门经理人中平均薪水最低的部门名称 求薪水最高的前5名员工 select ename ,sal from ( select ename,sal from emp order by sal desc) where rownum <=5 求薪水最高的第6到第10名员工(重点掌握) select ename,sal from ( select rownum r,ename,sal from ( select ename,sal from emp order by sal desc )) where r >5 and r <= 10 1-- backup scott exp 2-- create user create user jetwu identified by jetwu default tablespace users quota 10M on users grant create session--登录权限, create table, create view to jetwu 3-- import the data imp --备份一张表 create table emp2 as select * from emp; insert into dept2 select * from dept; rownum --取15条记录中后5条记录值 select ename from (select rownum r, ename from emp) where r > 10; --取薪水最高的5个人 select ename, sal from (select ename,sal from emp order by sal desc) where rownum <=5; --取薪水最高的6到10 select ename, sal from ( select ename, sal, rownum r from ( select ename, sal from emp order by sal desc ) ) where r >=6 and r <=10; 3张表S,C,SC S(SNO,SNAME) C(CNO,CNAME,CTEACHER) SC(SNO,CNO,SCGRADE) 1.找出没选过黎明老师的所有学生姓名 2.列出2门以上(含2门)不及格学生姓名及平均成绩 3.即学过1号课又学过2号课所有学生的姓名 1.select ename from s join sc on(s.sno=sc.sno) join c on(c.cno = sc.cno) where c.cteacher <> '黎明'; 2.select s.sname sc.avg(scgrade) from s s,sc sc where s.sno = sc.sno and sc.scgrade < 60 group by sc.sno having count(*) >=2 3. select sname from s join sc on (s.sno=( select sno from sc where cno = 1 and sno in (select distinct sno from sc where cno = 2))); 28 字段约束,是将约束加在字段后面 非空约束 constraint xxx not null 唯一约束 unique 两个空值不认为是重复的 表级约束, constraint xxxx(名字随便起) unique(email[字段名],name[字段名]) {表示这两个字段的组合不能为空} 29 主键约束 primary key (唯一的不可重复的不可为空的) 外键约束 references 表名(字段) 写成表级约束 constraint xxx foreign key (字段名) references 外表名(外表字段) 如:create table stu( id int, name varchar(50) constraint aaa not null, class1 number(6) , email varchar(30) , constraint stu_class_id foreign key (class1) references class(id), constraint xxx unique(name,email) ); create table class( id number(6) primary key, name varchar2(10) ) 31 修改表结构 alter 增加字段 alter table 表名 add(字段名,参数) 如:alter table stu add(school,varchar2(20)); 删除字段 alter table 表名 drop(字段名) 如:alter table stu drop(school); 修改字段 alter table 表名 modify(字段名,参数) 如:alter table stu modify(email,varchar(50)) 33 索引 一个表如果加了 “主键限制”,“唯一限制”,“组合限制” oracle会自动生成索引 索引创建格式 create index xxx(索引名随便起,最好见名知义) on 表名(字段名) 如:create index index_stu_email on stu(email); 删除索引 drop index xxx; 显示数据库中有什么索引 select index_name from user_indexes; 第一范式-要有主键,列不可分, 第二范式-不能存在部分依赖,不是主键的字段不能部分依赖主键 第三范式-除了主键外的字段不能存在传递依赖 PL SQL显示 pl/sql 面向过程的sql 带有分支和循环的sql 匿名块 :没有名字的程序 PL/SQL分为四块 declare 定义变量(可有可无) begin 程序从这里开始(必须) exception 有异常时执行 end;(必须) 如: set serveroutput on;(必须先执行这一命令,因为默认是OFF,如果是OFF的话,就不会输出) begin dbms_output.put_line('helloworld'); end; set serveroutput on; declare v_name varchar2(20); begin v_name := 'myname'; dbms_output.put_line(v_name); end; declare v_num number :=0; begin v_num := 2/v_num; dbms_output.put_line(v_num); exception when others then dbms_output.put_line('error'); end; --变量声明的规则 1. 变量名不能够使用保留字,如from,select等 2. 第一个字符必须是字母 3. 变量名最多包含30个字符 4. 不要与数据库的表或者列同名 5. 每一行只能声明一个变量 --常用变量类型 1. binary_interger:整数,主要用来计数而不是用来表示字段类型 2. number:数字类型 3. char:定长字符串 4. varchar2:变长字符串 5. date:日期 6. long:长字符串,最长2GB 7. boolean:布尔类型,可以取值为true,false和null值 --变量声明 declare v_temp number(1); v_count binary_integer := 0; v_sal number(7,2) := 4000.00; v_date date := sysdate; v_pi constant number(3,2) := 3.14; v_valid boolean := false; v_name varchar(20) not null := 'MyName'; begin dbms_output.put_line('v_temp value:' || v_count); end; 当变量声明为boolean类型时,该变量能不直接打印 如上面变量不能写成 dbms_output.put_line(v_valid); --变量声明,使用%type属性 declare v_empno number(4); v_empno2 emp.empno%type; v_empno3 v_empno2%type; begin dbms_output.put_line('Test'); end; 当使用“%type” 声明变量时,该变量变得灵活,会随着表的字段的修改而自动修改 --Table变量类型 Table复合变量(相当于java中的数组) declare type(关键字,说明是定义的新类型) type_table_emp_empno is table of emp.empno%type index by binary_integer; v_empnos type_table_emp_empno; begin v_empnos(0) := 7369; v_empnos(2) := 7839; v_empnos(-1) := 9999; dbms_output.put_line(v_empnos(-1)); end; --Record变量类型 (record变量相当于java中的类) declare type type_record_dept is record ( deptno dept.deptno%type, dname dept.dname%type, loc dept.loc%type ); v_temp type_record_dept; begin v_temp.deptno := 50; v_temp.dname := 'aaaa'; v_temp.loc := 'bj'; dbms_output.put_line(v_temp.deptno || ' ' || v_temp.dname); end; --使用%rowtype声明record变量 (record变量相当于java中的类)可以随着表的改动自动更新变量 declare v_temp dept%rowtype; begin v_temp.deptno := 50; v_temp.dname := 'aaaa'; v_temp.loc := 'bj'; dbms_output.put_line(v_temp.deptno || ' ' || v_temp.dname); end; --SQL语句的运用 在PL/SQL里面用select 必须加 “into”,且在select语句里面必须有且只能返回一条语句 declare v_ename emp.ename%type; v_sal emp.sal%type; begin select ename,sal into v_ename,v_sal from emp where empno = 789; dbms_output.put_line(v_ename || ' ' || v_sal); end; declare v_ename emp.ename%type; v_sal emp.sal%type; begin select ename,sal into v_ename,v_sal from emp where deptno = 10 dbms_output.put_line(v_ename || ' ' || v_sal); end; --ddl在PL/SQL中的运用 创建表 在PL/SQL中创建表时,前面必须加“execute immediate” ,然后后面的建表语句用单引号引上 如果在单引号中,又出现单引号,则内部单引号用 (‘’)代表(‘); begin execute immediate 'create table t (nnn varchar2(20) default ''aaa'')'; end; --游标 cursor declare cursor c is select * from emp; v_emp c%rowtype; begin open c; fetch c into v_emp; dbms_output.put_line(v_emp.ename); close c; end; declare cursor c is select * from emp; v_emp c%rowtype; begin open c; loop fetch c into v_emp; exit when (c%notfound); dbms_output.put_line(v_emp.ename); end loop; close c; end; --循环遍历 declare cursor c is select * from emp; v_emp c%rowtype; begin open c; loop fetch c into v_emp; dbms_output.put_line(v_emp.ename); exit when (c%notfound); end loop; close c; end; --IF语句 取出7369的薪水,如果 <1200 ,则输出‘low’,如果 <2000则输出‘middle’,否则'hign' declare v_sal emp.sal%type; begin select sal into v_sal from emp where empno = 7369; if(v_sal < 1200) then dbms_output.put_line('low'); elsif(v_sal <2000) then //elsif这里中间的E是没有的 dbms_output.put_line('middle'); else dbms_output.put_line('hign'); end if; end; 循环 PL/SQL里面的循环一定是以LOOP 开始,以END LOOP结束 下面这个相当于 DO WHILE declare i binary_integer := 1; begin loop dbms_output.put_line(i); i := i + 1; exit when( i >= 11); end loop; end; 下面相当于while循环 declare j binary_integer := 1; begin while j < 11 loop dbms_output.put_line(i); j := j + 1; end loop; end --for循环 declare cursor c is select * from emp; begin for v_emp in c loop dbms_output.put_line(v_emp.ename); end loop; end; --带参数的游标 declare cursor c(v_deptno emp.deptno%type, v_job emp.job%type) is select ename,sal from emp where deptno = v_deptno and job = v_job; begin for v_temp in c(30,'CLERK') loop dbms_output.put_line(v_temp.ename); end loop; end; --可更新的游标 declare cursor c is select * from emp2 for update; begin for v_temp in c loop if(v_temp.sal < 2000) then update emp2 set sal = sal*2 where current of c; elsif (v_temp.sal = 5000) then delete form emp2 where current of c; end if; end loop; commit; end; --存储过程 create or replace procedure p is --上面的替代declare,其他都一样 cursor c is select * from emp2 for update; begin for v_emp in c loop if (v_emp.deptno = 10) then update emp2 set sal = sal + 10 where current of c; elsif (v_emp.deptno = 20) update emp2 set sal = sal + 20 where current of c; else update emp2 set sal = sal + 50 where current of c; end if; end loop; commit; end; --执行存储过程 exec p; 另外一种执行方式 begin p; end; --带参数的存储过程 create or replace procedure p (v_a in number, v_b number, v_ret out number,v_temp in out number ) is begin if(v_a > v_b) then v_ret := v_a; else v_ret := v_b; end if; v_temp := v_temp + 1; end; declare v_a number := 3; v_b number := 4; v_ret number; v_temp number := 5; begin p(v_a,v_b,v_ret,v_temp); dbms_output.put_line(v_ret); dbms_output.put_line(v_temp); end; --函数 create or replace function sax_tax (v_sal number) return number is begin if(v_sal < 2000) then return 0.10; elsif(v_sal < 2750) then return 0.15; else return 0.20; end if; end; --执行函数 select lower(ename), sal_tax(sal) from emp; --触发器 当做一个件事的时候,一触动就会触发另一事件 create table emp2_log ( uname varchar2(20), action varchar2(10), atime date ); create or replace trigger trig after insert or delete or update on emp2 for each row begin if inserting then insert into emp2_log values (USER, 'insert',sysdate); elsif updateing then insert into emp2_log values (USER, 'update',sysdate); elsif deleting then insert into emp2_log values (USER, 'delete',sysdate); end if; end; --触发器用于更新关联 create or replace trigger trig after update on dept for each row begin update emp set deptno = :NEW.deptno where deptno = :OLD.deptno; end; 应用 update dept set deptno = 99 where deptno = 10;--NEW.deptno:99 OLD.deptno:10 --树状结构的存储与展示 drop talbe article; create table article ( id number primary key, cont varchar2(4000), pid number, isleaf number(1), --0 代表非叶子节点,1代表叶子节点 alevel number(2) ); insert into article values (1,'蚂蚁大战大象',0,0,0); insert into article values (2,'大象被打趴下了',1,0,1); insert into article values (3,'蚂蚁也不好过',2,1,2); insert into article values (4,'瞎说',2,0,2); insert into article values (5,'没有瞎说',4,1,3); insert into article values (6,'怎么可能',1,0,1); insert into article values (7,'怎么没有可能',6,1,2); insert into article values (8,'可能性是很大的',6,1,2); insert into article values (9,'大象进医院了',2,0,2); insert into article values (10,'护士是蚂蚁',9,1,3); 蚂蚁大战大象 大象被打趴下了 蚂蚁也不好过 瞎说 没有瞎说 大象进医院了 护士是蚂蚁 怎么可能 怎么没有可能 可能性是很大的 create or replace procedure p(v_pid article.pid%type, v_level binary_integer) is cursor c is select * from article where pid = v_pid; v_preStr varchar2(1024) := ''; begin for i in 1..v_level loop v_preStr := v_preStr || ' |'; end loop; for v_article in c loop dbms_output.put_line(v_preStr || v_article.cont); if(v_article.isleaf=0) then p(v_article.id,v_level + 1); end if; end loop; end;