--字符函数upper()和lower()-- selectupper('yes') from dual; --数值函数,四舍五入,保留1位,即26.2,保留-1位,即30 select round(26.18,1) from dual; --截取函数,保留1位即56.1 select trunc(56.16,1) from dual; --求余函数,1 selectmod(10,3) from dual; --日期函数 ---查询emp表中所有员工入职距离现在几天 select sysdate-e.hiredate from emp e; ---明天此刻 select sysdate+1from dual;
--日期转换字符串函数, 0 select to_char(sysdate,'yyyy-mm-ss hh:mi:ss') from dual; select to_char(sysdate,'yyyy-mm-ss hh24:mi:ss') from dual; --字符串转日期函数 select to_date('2020-10-10 21:07:52','yyyy-mm-ss hh:mi:ss') from dual;
--通用函数nvl(),如果e.comm不是null,则使用,否则为0 ---null和任意值做算术运算,结果都是null select e.sal*12+nvl(e.comm, 0) from emp e;
条件表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
--给emp表种员工起中文名 select e.name, case e.name when'hiccup'then'曹操' when'tom'then'大猫' when'sms'then'史密斯' else'无名' end from emp e;
--判断emp表中员工工资,如果高于3000显示高收入,如果在1500和3000之间,显示中等收入,其余显示低收入 select e.sal, case e.name when e.sal>3000then'高收入' when e.sal>1500then'中等收入' else'低收入' end from emp e;
注意:Oracle一般都用单引号
多行函数(聚合函数)
1 2 3 4 5
--注意,一次执行多行要有分号 selectcount(1) from emp; selectsum(sal) from emp; selectmax(sal) from emp; selectavg(sal) from emp;
分组查询
1 2 3 4 5 6
--查询出每个部门的平均工资 ---分组查询中,出现在gruop by后天的原始列,才能出现在select后面 ---没有出现在group by后面的原始列,想在后面出现,必须加上聚合函数 select e.deptno,avg(e.sal) from emp e groupby e.deptno
1 2 3 4 5 6
--查询公司高于2000的部门信息 ---所有条件都不能使用别名判断,因为条件的优先级大于select select e.deptno,avg(e.sal) from emp e groupby e.deptno havingavg(e.sal)>2000
1 2 3 4 5 6
--查询出每个部门工资高于800的员工的平均工资
select e.deptno,avg(e.sal) from emp e where e.sal>800 groupby e.deptno
1 2 3 4 5 6 7
---where过滤分组前的数据,having过滤分组后的数据 ---位置表现为在group by前后 select e.deptno,avg(e.sal) from emp e where e.sal>800 groupby e.deptno havingavg(e.sal)>2000
多表查询
1 2 3 4 5 6 7
--笛卡尔积,14*4=56条 select* from emp e, dept d;
--等值连接,14条 select*from emp e,dept d where e.deptno = f.deptno;
子查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
--返回一个值 select*from emp where sal in (select sal from emp where name ='xiaoming');
--返回一个集合 select*from emp where sal in (selectsqlfrom emp where deptno ='10');
--返回一张表,多行记录 select t.deptno, t.s, e.name, d.dname from ( select deptno,min(sal) s from emp groupby deptno ) t,emp e,dept d where t.deptno = e.deptno and t.s = e.sal and e.deptno = d.deptno;
分页查询
1 2 3 4 5 6 7 8
--只有做select查询的时候,才会有rownum
select*from ( select rownum rn, tt.*from( select*from emp orderbysqldesc--无论这行多少条,根据11和5的值都可以分页显示 ) tt where rownum<11 ) where rn>5
视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14
--视图:提供一个查询的窗口,所有数据来自于原表,所以修改视图的数据,也就是修改对应原表里的数据 ---创建视图必须要有dba权限,查询语句可以跨用户查询 ---利用查询语句创建表 createtable emp asselect*from scott.emp; ---创建视图 createview v_emp asselect ename,job from emp; ---查询视图 select*from v_emp; ---修改视图,所有数据来自于原表,所以修改视图的数据,也就是修改对应原表里的数据 update v_emp set job ='clerk'wherewhere ename ='aline'; commit; ---创建只读视图 createview v_emp asselect ename,job from emp with read only; ---视图的作用:屏蔽敏感字段,保证总部和分部数据及时统一(分部使用总部做的视图)
索引
1 2 3 4 5 6 7 8 9
--索引:在表的列上构建一个二叉树(例如书的目录),可以提高查询效率,降低增删改效率。 ---单列索引,触发规则:条件必须是索引列的原始值,单行函数,模糊查询都会影响索引的触发。 create index idx_ename on emp ename; select*from emp where ename ='scott';--触发单列索引 ---复合索引,触发规则:第一列为优先检索列,若要触发索引,必须包含有优先检索列中的原始值 create index idx_ename_job on emp (ename,job); select*from emp where ename ='scott'and job ='tt';--触发复合索引 select*from emp where ename ='scott'or job ='tt';--不触发索引 select*from emp where ename ='scott';--触发单列索引
pl/sql变量
1 2 3 4 5 6 7 8 9 10 11 12 13
--pl/sql编程语言是对sql语言的扩展,使得sql语言有过程化编程特性,主要用来编写存储过程和存储函数。 ---申明方法,可以使用":="赋值,也可以使用into查询语句赋值, declare i number(2) :=10; s varchar2(10) :='小明'; ena emp.ename%type;---引用型变量 emprow emp%rowtype;---记录型变量 begin dbms_output.put_line(i); select ename into ena from emp where empno ='7878'; select*into emprow from emp where empno ='7878'; dbms_output.put_line(emprow.ename ||'的工作为:'|| emprow.job); end;
pl/sql判断
1 2 3 4 5 6 7 8 9 10 11
declare i number(3) :=ⅈ--输入,变量名任意 begin if i<18then dbms_output.put_line('未成年'); elsif i<40then dbms_output.put_line('中年人'); else dbms_output.put_line('老年人'); end if; end;
--游标:可以存放多个对象,多行记录 ---输出emp表中的所有员工的姓名 declare cursor c1 isselect*from emp; emprow emp%rowtype; begin open c1; loop fetch c1 into emprow;--一行一行的取 exit when c1%notfound; dbms_output.put_line(emprow.ename); end loop; close c1; end;
---给指定部门员工涨工资 declare cursor c2(eno emp.deptno%type) isselect empno from emp where deptno = eno; en emp.empno%type begin open c2(10); loop fetch c2 into en; exit when c2%notfound; update emp set sal = sal +100where empno = en; commit; end loop; close c2;--只赋值一次 end;
存储过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14
--存储过程:提前已经编译好的一段pl/sql语言,放置在数据库端可直接别调用,这一段pl/sql一般都是固定步骤的业务 ---给指定员工涨100元 createor replace procedure p1(eno emp.empno%type)--默认in类型 as--is也可以,这里相当于declare,做申明用 begin update emp set sal=sal+100where empno = eno; commit; end;
---调用 declare begin p1(7788); end;
存储函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
---通过存储函数计算指定员工的年薪 ----存储过程和存储函数的参数都不能带长度,存储函数的返回值类型不能带长度 createor replace function f_yearsal(eno emp.empno%type) return number--number是类型,不能加长度 is s number(10); begin selectsql*12+nvl(comm,0) into s from emp where empno = eno; return s; end;
---调用f_yearsal declare s number(10); begin s := f_yearsal(7788);--需要返回值接收 dbms_output.put_line(s); end;
out类型参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
---使用存储过程计算年薪 createor replace procedure p_yearsal(eno emp.empno%type, yearsal out number) is s number(10); c emp.comm%type; begin select sal*12,nvl(comm,0) into s, c from emp where empno = eno; yearsal := s+c; end;
--调用 declare yearsal number(10); begin p_yearsal(7788, yearsal); dbms_output.put_line(yearsal); end;
--查询出员工姓名,员工所在部门名称 ---传统实现 select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno; ---使用存储函数实现 createor replace function fdna(dno dept.deptno%type) return dept.dname%type is dna dept.dname%type; begin select d.name into dna from dept where deptno = dno; return dna; end; ---调用 select e.ename, fdna(e.deptno)--只有存储函数可以这样做,因为存储过程没有返回值 from emp e;
-- 触发器:指定一个规则,在我们做增删改的时候,只要满足规则,自动触发无需调用 -- 分为两类,语句级和行级,包含 for each row 的是行级触发器,加 for each now 的目的是为了使用:old 或者 :new 对象或者一行记录
-- 插入一条记录,输出一个新员工入职 --- 语句级触发器 createor replace trigger t1 after insert on person declare begin dbms_output.put_line('一个新员工入职'); end; --- 触发 insertinto person values(1,'小马'); commit; --- 不能给员工降薪 -- 行级触发器 createor replace tirgger t2 before update on emp foreachrow declare
begin if :old.sal > :new.sal then raise_application_error(-20001,'不能给员工降薪')--只能-20001到-20999之间,不能重复 end if; end; --- 触发 update emp set sal = sal -1where empno =7788; commit;
--- 使用触发器实现主键自增 -- 行级触发器 createor replace trigger autoid before insert on person foreachrow declare
begin select s_person.nextval into :new.pid from dual; end; --- 使用 insertinto person (pname) values ('嗷嗷嗷'); commit;