碎点篇—— oracle 语法和练习

返回主目录

 

--select from where having group by order by 的正确执行顺序为:
--from-->where-->group by-->having-->select-->order by
--------------------------------------------------------
--1、去重:distinct 必须放在开头,多字段,每个字段不一样才去重
--2、条件比较:
-- =,!=,<>,<,>,<=,>=,any,some,all
-- is null, is not null
-- between x and y
-- in(list) , not in (list)
-- like _,%,escape '\' _\%escape '\'
-- not, (and,or) and优先级高

-- 按照单个列排序
-- order by col
-- 降序排列:order by col desc
-- 升序排列:order by col asc
-- 按多个列排序:(优先级)
-- order by col1 desc(asc) , col2 desc(asc)

--1.全集:union all
--2.并集:union (去重)
--3.交集:intersect
--4.差集:minus
--5.不懂怎么用,就选择 (*)
-----------------------------------------------------------
--基本查询语句
select * from emp;
select e.ename , e.sal from emp e where e.sal>1500;
select distinct e.deptno , d.dname from emp e , dept d;
---------------------------------------------------------
--组函数又被称作集合函数,用于对多行数据进行操作,并返回一个单一的结果
--组函数仅用于选择列表或查询的having子句单行函数对单个数值进行操作,并
--返回一个值。
--concat(string2,string3)连接两个字符串
--initcap(string) string中每个单词首字母大写
--lower(string) string 中每个单词首字母小写
--lpad , rpad 填充字符型数据
--ltrim/rtrim (string2,string3)
trim(A from B)
--substr() 提取字符串的一部分substr(string,1,2)
--upper(string)以大写形式返回string
--instr() 字符串出现的位置,instr(string,'A')
--length() 字符串长度

-------------------------------------------------------
--round(number,n):返回四舍五入的值
select round(23.434) from dual;
select round(23.434,2) from dual;
select round(23.436,2) from dual;
select round(23.434,-1) from dual;
--trunc(number,n): 返回截取的值
select trunc(23.434) from dual;
select trunc(23.434,2) from dual;
select trunc(23.436,2) from dual;
select trunc(23.434,-1) from dual;
--mod(x,y):求余数
select mod(13,5) from dual;
--ceil(number):向上取整
select ceil (19.2) from dual;
--floor(number):向下取整
select floor(19.2) from dual;

--avg(): 返回某列的平均值
--min(): 返回某列的最小值
--max(): 返回某列的最大值
--sum(): 返回某列值的和
--count(): 返回某列的行数
--组函数仅在选择列表和having子句中有效

--group by 子句
--group by 子句可以包含任意数目的列
--除组函数语句外,select 语句中的每个列都必须在 group by 子句中给出。
--如果分组列中具有null值,则null将作为一个分组返回。如果列中有多行null
--值,他们将分为一组。
--group by 子句必须出现在where 子句之后,order by 子句之前。
--过滤分组(having子句)
--where 过滤行,
--having 过滤分组
--having 支持所有的where操作
--分组和排序
--一般在使用group by 子句时,应该给出 order by 子句

--数据来自于多张表,92表连接
--注意:明确引用同名的列,必须使用表名,或者别名区分
--1.笛卡尔积:
--   select 字段列表 from 表1,表2,表3....
--2.等值连接:取关系列相同的记录
--   select 字段列表 from 表1,表2,表3....
--          where 表1.列 = 表2.列 and 表1.列 =表3.列
--3.非等值连接:取关系列不同的记录 != > < >= <= between and
--   select 字段列表 from 表1,表2,表3....
--          where 表1.列 != 表2.列 and 表1.列 != 表3.列
--4.自连接:(特殊的等值连接) 列来自于同一张表,不同角度看待表
--   select 字段列表 from 表1 e, 表2 d 
--          where e.列1 = d.列3
--5.外连接:在等值基础上,确保一张表(主表) 的记录都存在,从
--          表满足则匹配,不满足补充null
--右外:主表在右边
--左外:主表在左边

--sql1992:的语法规则暴露了这样额缺点:语句过滤条件和表连接的条件
--          都放到了where子句中。当条件过多时,联结条件多,过滤条件
--          多时,就容易造成混淆
--sql1999:修正了这个缺点,把联结条件,过滤条件分开来,包括以下新的table
--          join 的句法结构:
--cross join
--natural join 
--using 子句
--on 子句
--left outer join
--right outer join
--full outer join
-------------------------------------------------------
--创建视图
--with read only 表示只读
create or replace view v_emp_dept_a as 
       select e.deptno , e.ename , d.dname from
       emp e join dept d on e.deptno= d.deptno
       with read only ;

select * from v_emp_dept_a;
--当不再需要视图的时候,用"drop view"撤销。删掉视图不会导致数据的丢失
--因为视图是基于数据库的表之上的一个查询定义
drop view v_emp_dept_a;

--创建视图必须要有主键,不然无法插入数据。
create or replace view v_emp_dept_b as
       select e.empno , e.ename , e.sal , e.deptno from emp e;

select * from v_emp_dept_b;

--DML
insert into v_emp_dept_b (empno , ename , sal) values(2000,'zhiyi',3554);
update v_emp_dept_b set ename='weiwo', deptno=20 where ename='zhiyi';
delete from v_emp_dept_b where ename like 'weiwo'
-----------------------------------------------------------------------
--我们要求平均薪水的等级最低的部门,它的部门名称是什么?
--我们完全使用子查询
--求部门的平均薪水
select e.deptno dt , avg(e.sal) avg_sal from emp e group by deptno;
--创建子类视图
create or replace view  deptno_avg_sal_a as
       select e.deptno dt , avg(e.sal) avg_sal from emp e group by deptno;
select *  from deptno_avg_sal_a;
--求部门薪水的等级
select t.dt dl , s.grade gr from deptno_avg_sal_a t join salgrade s on
       t.avg_sal between losal and hisal;
--创建子类视图
create or replace view dept_grade_a as
       select t.dt dl , s.grade gr from deptno_avg_sal_a t join salgrade s on
              t.avg_sal between losal and hisal;
select * from dept_grade_a;
--求出最低等级
select  min(gr) from dept_grade_a;
--求出部门名字
select d.dname from dept_grade_a de join dept d on de.dl = d.deptno
       where de.gr = (select min(gr) from dept_grade_a);
select * from dept;
--删除视图
drop view dept_grade_a;
drop view deptno_avg_sal_a;
drop view v_emp_dept_b;
----------------------------------------------------------------------
--创建表
create table temp as 
       select *from emp where 1=2;
----where 1=2 创建的是空表单
select * from temp;
create table temp2 as 
       select *from emp where 1=1;
select * from temp2;
----where 1=1 创建的是全部数据的表单
--插入数据
insert into temp select * from emp;
--删除表单
drop table temp;
drop table temp2;

---------------------------------------------------------------------
--number(x,y) : 数字类型,最长x x位,y y位小数
--varchar2(maxlength) : 变长字符串,这个参数的上限是32767字节。
--                     声明方式如下 varchar2(L L),L L 为字符串长度,
--                     没有缺省值,作为变量最大32767个字节
--char(max_length) : 定长字符串 ,最大2000个字节
--date : 日期类型(只能精确到秒)
--timestamp : 时间戳(精确到微秒)
--long : 长字符串,最大 2GB

--了解类型
--clob : 最大长度4G -->大对象很少使用:如果存在大对象,一般的解决方案
--                     存入文件地址(地址为程序所在应用服务器的相对路径)
--blob : 存二进制文件

--主键约束是数据库中最重要的一种约束。在关系中,主键值不可为空,也不
--允许出现重复,即关系要满足实体完整性规则。
--主键从功能上看相当于非空且唯一
--一个表中只允许一个主键
--主键是表中能够唯一确定一个行数据的字段
--主键字段可以是单字段或者多字段的组合
--oracle为主键创建对应的唯一性索引。

-------------------------------------------------------------------
--procedural language和sql的结合体。通过增加变量、控制语句,使我们可以写
--           一些逻辑更复杂的数据库操作。

--匿名块由一下四部分组成:
--declare    (可选)
--声明各种变量或游标的地方
--begin      (必要)
--开始执行语句
--       单行注释用两个连在一起的‘-’表示。
         /*多行注释语句,可以换行*/
--exception     (可选)
--出错后的处理
--end;          (必要)(请注意end后面的分号)


--1.变量必须在 declare 语句块中声明
--   变量声明的语法规则
--identifier [constant] datatype [not null] [:=| default expr];
--如:
--变量名  类型 := 初始值;
-- v_str varchar2(10) := 'abc';

--2.变量的命名规则
--变量名不能够使用保留字,如from、select等
--变量名最多包含30个字符
--不要与数据库的表或者列同名
--每一行只能声明一个变量
--建议:
--a).普通变量 v_
--b).常量 c_
--3.赋值语句:
--a).PL/SQL中的赋值使用  :=
--b)."=" 被用作比较操作符
--c).赋值语句中有一些规则需要遵守
--     字符类型必须使用单引号
--     不可以使用group by
--     可以使用数学操作符或字符串连接操作符

--常用变量类型:
--普通变量
--  %type
--  %rowtype
--  varray
--  table
--  record
--变量声明规则
--  变量名不能够使用保留字,如from、select等
--  第一个字符必须是字母
--  变量名最多包含30个字符
--  不要与数据库的表或者列同名
--  每行只能声明一个变量
--  普通变量的类型主要有:
--    binary_integer : 整数,主要用来计数而不是用来表示字段类型
--    number(x,y) : 数字类型,最长x位,y位小数
--    varchar2(maxlength)  : 变长字符串,这个参数的上限是32767字节
--                         声明方式如下 varchar2(L) , L为字符串长度,
--                         没有缺省值,作为变量最大32767个字节
--char(max_length) : 定长字符串
--date : 日期
--boolean  : 布尔类型,可以取值为 true、false和null值


--table 义记录表(或索引表) 数据类型
--先声明table类型(声明具体的table类型)
--type table 类型的名称 is table of data_type [index by binary_integer];


--1.单选择语句:
--   if 条件  then
--   end if;
--2.双重选择:
--   if 条件 then
--   else
--   end if;
--3.多选择:
--   if 条件 then
--   elsif 条件 then
--   elsif 条件 then
--   else
--   end if;


--1.do-while 循环,先执行后判断:
--   loop
--   exit when 条件
--   end loop;
--2.while 循环,先判断后执行:
--   while 条件 loop
--   end loop;
--3.for 循环,能够确定次数,不用声明变量,增长变量
--   for index in[reverse] min..max loop
--   end loop;
--  index 不能手动改变值,内部自动维护 +1 或 -1

------------------------------------------------------------------
--cursor 分类:
--                           |--显式 cursor
--           --静态 cursor --|
--          |                |--隐式 cursor
--cursor  --|
--          |                             |-- 强类型(限制),规定返回类型
--          |--动态 cursor --ref cursor --|
--                                        |-- 弱类型(非限制),不规定返回类型
--                                                 --可以获取任何结果集

--隐式游标:
--  可以使用名字sql来访问,但要注意,通过sql游标总是只能访问前一个处理
--  操作或单行select操作的游标属性。所以通常在刚刚执行完操作之后,立即
--  使用sql游标来操作属性。游标的属性有4种。分别是:
--  sql %isopen , sql %found , sql %notfound , sql %rowcount

--sql%isopen 返回的类型是布尔型,判断游标是否被打开,如果打开 %ispen 等于
--           true,否则等于false,即执行过程中为真,结束后为假。

--sql%notfound 返回值为布尔型,判断游标所在的行是否有效,如果有效,则
--             %found 等于true,否则等于false,即与%found 属性返回值相反。

--sql%found 返回值的类型为布尔值,值为true代表插入、删除、更新或单行查询
--          操作成功。

--sql%rowcount 返回值类型为整形,返回当前位置为止游标读取的记录行数,即成功
--             执行的数据行数。


------------------------------------------------------------------------
--显式游标:
--    主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下;
--隐式游标:
--    而对于非查询语句,如修改、删除操作,则由oracle系统自动地为这些操作设置
--    操作设置游标并创建其工作区,这些由系统隐含创建的游标称为:隐式游标。
--    隐式游标的名字为sql,这是由 oracle 系统定义的。对于隐式游标的操作,如
--    定义、打开、取值及关闭操作,都由 oracle 系统自动地完成,无需用户进行
--    处理。用户只要通过隐式游标的相关属性,来完成相应的操作。在隐式游标的
--    工作区中,所存放的数据是与用户自定义的游标无关的、最新处理的一条sql
--    语句所包含的数据。
--    格式调用为:sql%
--    注: insert , update , delete , select 语句中不必明确定义游标。

--1.游标:cursor
--   游标就是指在某个结果集上的指针,通过这个指针的移动,我们得以遍历整个结果集
--2.游标的使用步骤(标准)
--   1).声明游标
--   2).打开游标
--   3).处理游标中的数据
--   4).关闭游标

--ref 游标:动态游标
--   1).在运行时使不同的语句与之关联
--   2).ref游标可以使用游标变量
--属性引用类型的一种 ,在运行时动态 的改变游标的指向。for循环中不能使用
--ref游标,因为for自动打开游标
--   1).弱类型游标:
--       没有返回类型的游标变量,有动态关联sql字符串
--       type refempcur is ref cursor;
--   2).强类型游标
--       有返回类型的游标变量,不能关联sql字符串,只能关联sql命令
--       type refempcur is ref cursor return emp%rowtype; 
---      游标仅能打开emp表的数据。
--       open 游标名: for select_statement

------------------------------------------------------------------
--创建存储过程
create [or replace] procedure procedure_name
([arg1 [in | out | in out]] type1 [default value1] ,
[arg2 [in | out | in out]] type2 [default value2] ,
--.....
[argn [in | out | in out]] typen [default valuen])
[authid definer | current_user]
{is | as}
--<声明部分>
begin
--<执行部分>
exception
--<可选的异常错误处理程序>
end;

----------------------------------------------------------------------
--触发器
--  触发器是数据库发生某个操作时自动运行的一类的程序
--  用于保持数据的完整性或记录数据库操作信息方面
--  触发器不能够被直接调用,只能够在某些事件发生时触发,也就是系统自动调用
--触发器的构建语法:
--  create [or replace] trigger trigger_name
--  before | after
--  event1 [or event2 or event3 ....]
--  on table_name [for each row]
--  begin
--  statement;
--  ...
--  end;

--event通常是 insert 、delete 或 update 等DML操作

--触发器分为语句级触发器和行级触发器
--语句级触发器是指每执行一条DML语句,该触发器就执行一次
--行级触发器是指每个DML操作影响几条记录,就会触发几次 (for each row)
--行级触发器中由于涉及到了每条记录的数据变动,所以对于每条记录的数据来说
--就有新值和旧值之分。
--用关键字 :new 和 :old 来代表新的记录和旧的记录。

--jdbc 调用 存储过程:
public class Test{
     public  static void main(String[] args){
          try{
              Class.forName("oracle.jdbc.driver.OracleDriver");
              String url = "jdbc:oracle:thin:@localhost:1521:orcl";
              Connection conn = DriverManager.getConnection(url,"scott","tiger");
              System.out.println(conn.isClosed());
              CallableStatement cs = conn.prepareCall("{call delRepeat(?,?,?)}");
              cs.setString(1,"emp");
              cs.setString(2,"ename");
              cs.registerOutParameter(3,OracleTypes.NUMBER);
              cs.executeQuery();
              System.out.println(cs.getObject(3));
              conn.close();
          } catch (Exception e) {
              e.printStackTrace();
          }
     }
}

-----------------------------------------------------------------------------
--外传:

--case when 方法
--decode 方法

--为所有人涨工资,标准是:10部门涨10%;20%部门涨15%;30部门涨20%;
--其他部门涨18%。
select * from emp;
select ename, (case deptno when 10 then sal*1.1
       when 20 then sal*1.15 
         when 30 then sal*1.2 
           else sal*1.18 end) v_sal
             from emp e;
--等价于下面的:
select ename, decode(deptno ,10 , sal*1.1,20 , 
       sal*1.15 , 30, sal*1.2 ,sal*1.18) v_sal
       from emp e;

------------------------------------------------------------------
------------------------------------------------------------------
select * from emp e where sal in (800,2000,3000,5000);
select * from emp e where ename in ('KING','JONES','FORD','MARTIN');
select *from emp e where sal between 1200 and 4000;
select * from emp e where e.deptno not in (20);
select * from emp e where e.deptno != 20;
select *  from emp e where (e.deptno = 10 or e.deptno = 30)
       and e.sal > 1500;
select * from emp e where e.deptno in (10 , 30) and e.sal >1500;
select * from emp e where e.hiredate > to_date('1981-02-05' , 'yyyy-mm-dd');

-----------------------------------------------------------------------
--1、查询部门编号为10的员工信息
select * from emp  where deptno = 10;
--2、查询年薪大于3万的人员的姓名与部门编号
select * from emp e where (e.sal+nvl(comm , 0))*12 > 30000;
--3、查询佣金为null的人员姓名与工资
select * from emp e where comm is null;
--4、查询工资大于1500 且 and 含有佣金的人员姓名
select * from emp e where e.sal > 1500 and  comm is not null;
--5、查询工资大于1500 或 or含有佣金的人员姓名
select * from emp e where e.sal > 1500 or comm is not null;
--6、查询姓名里面含有 S 员工信息 工资、名称
select * from emp e where e.ename like '%S%';
--7、求姓名以J开头第二个字符O的员工姓名的与工资
select * from emp e where e.ename like 'JO%';
--8、求包含%的雇员姓名
select * from emp e where e.ename like '%A%%' escape 'A';
--9、使用in查询部门名称为 SALES 和 RESEARCH 的雇员姓名、工资、部门编号
--   用 distinct去重
select * from emp;
select distinct e.ename , e.sal , e.deptno from emp e , dept d
       where d.dname in ('SALES' , 'RESEARCH') and e.deptno = d.deptno;
--10、使用exists查询部门名称为SALES和RESEARCH 的雇员姓名、工资、部门编号。
--    exists是判断exits后面的sql语句是否为真,若为真则整个sql句子成立,
--    否则没有任何记录。语法如下:
--  ** select * from a where exists (select g from b where a.id = b.id);
select distinct e.ename , e.sal , e.deptno from  emp e 
       where exists (select * from emp e ,dept d  
             where d.dname in ('SALES' , 'RESEARCH') and d.deptno = e.deptno);
---------------------------------------------------------------------
select * from emp e order by e.sal desc , e.ename asc;
select e.ename || ' is a ' || e.job from emp e; 
---------------------------------------------------------------------
--1、使用基本查询语句.
--(1)查询DEPT表显示所有部门名称.
select d.dname from dept d;
--(2)查询EMP表显示所有雇员名及其全年收入(月收入=工资+补助),
--处理NULL行,并指定列别名
--为"年收入"。(NVL(comm,0) comm取空值时用0替代)
select e.ename , (e.sal+nvl(comm,0))*12 sal_all from emp e;
--(3)查询显示不存在雇员的所有部门号。
select d.deptno from dept d 
       where d.deptno not in (select distinct e.deptno from emp e 
             where d.deptno = e.deptno);

--2、限制查询数据
--(1)查询EMP表显示工资超过2850的雇员姓名和工资。
select e.ename , e.sal from emp e where e.sal >2850;
--(2)查询EMP表显示工资不在1500~2850之间的所有雇员及工资。
select e.ename , e.sal from emp e where e.sal not in (1500 , 2850);
--(3)查询EMP表显示代码为7566的雇员姓名及所在部门代码。
select e.ename , e.deptno from emp e where e.empno = 7566;
--(4)查询EMP表显示部门10和30中工资超过1500的雇员名及工资。
select e.ename , e.sal from  emp e where e.deptno in (10,30) and e.sal >1500;
--(5)查询EMP表显示第2个字符为"A"的所有雇员名其工资。
select e.ename , e.sal from emp e where e.ename like '_A%';
--(6)查询EMP表显示补助非空的所有雇员名及其补助。
select e.ename , e.comm from emp e where comm is not null;
--3、排序数据
--(1)查询EMP表显示所有雇员名、工资、雇佣日期,并以雇员名的升序进行排序。
select e.ename , e.sal , e.hiredate from emp e order by e.ename asc;
--(2)查询EMP表显示在1981年2月1日到1981年5月1日之间雇佣的雇员名、
--     岗位及雇佣日期,并以雇佣日期进行排序。
select e.ename , e.job , e.hiredate from emp e 
       where e.hiredate >= to_date('1981-02-01' ,'yyyy-mm-dd') and
             e.hiredate <= to_date('1981-05-01' , 'yyyy-mm-dd') 
             order by e.hiredate desc;
--或
select e.ename , e.job , e.hiredate from emp e 
       where e.hiredate >= to_date('1981-02-01' ,'yyyy-mm-dd') and
             e.hiredate <= to_date('1981-05-01' , 'yyyy-mm-dd') 
             order by e.hiredate asc;
--(3)查询EMP表显示获得补助的所有雇员名、工资及补助,并以工资升序和
--补助降序排序。
select e.ename , e.sal , e.comm from emp e 
       where (e.comm is not null and e.comm != 0) order by e.sal , e.comm desc;

-----------------------------------------------------------------------------
select lower(ename) from emp e ;
select upper(lower(ename)) from emp
select substrb('流aa川abc',1,4) from dual;
select ename , substr(ename , 2) from emp e;
select ename , length(ename) from emp 
select ename , lpad(ename , '6' , '*') from emp;
select ename , rpad(ename , '6' ,'*') from emp;
select ename , instr(ename , 'A') from emp;
select ename , instr(ename , ename) from emp;
select ename , replace(ename , 'A' , '-') from emp;
select rtrim('xxgao lao shixxx' , 'x') text from dual;
select trim(both 'x' from 'xxxgao lao shixxx') from dual;


select ceil(19.2) from dual;
select floor(19.2) from dual;
select mod(19,2) from dual;
select trunc(23.653) from dual;
select trunc(23.653,2) from dual;
select trunc(23.653,-1) from  dual;
select round(23.653) from dual;
select round(23.653,2) from dual;
select round(23.653,-1) from dual;


select sysdate from dual;
select current_date from dual;
select add_months(sysdate , 3) from dual;
select months_between(sysdate,add_months(sysdate,3)) from dual;
select sysdate-2 from dual;
select sysdate+2 from dual;
select ename , round((sysdate-hiredate)/7) weeks from emp e where e.deptno = 10;
select * from emp where empno = to_number('7369');
select * from emp e where hiredate = '20-2月-1981';
select * from emp e where hiredate = to_date('1981-02-20' , 'yyyy-mm-dd');
select '199'-90 from dual;

select to_char(sysdate,'yyyy-mm-dd hh24 : mi : ss') from dual;
select ename , hiredate , to_char(hiredate , 'yyyy-mm-dd hh24:mi:ss') from emp;

select to_char(sal , '$99,999.9999') salary from emp where ename = 'ALLEN';
select to_char(sal , '$00,000.0000') salary from emp where ename = 'ALLEN';
select to_char(sal , 'L00,000.0000') salary from emp where ename = 'ALLEN';

select to_date('04,05,19,23,40' ,'yy,mm,dd,hh24,mi,ss') from dual;
select to_date('2004-09-19' , 'yyyy-mm-dd') from dual;

select to_number('$39343.783' , '$99990.000') from dual;
select to_number('11.231','999.999') from dual;

select e.*, nvl(to_char(mgr) , 'boss') mgr from emp e where mgr is null;

select to_char(next_day(add_months(hiredate , 6) , '星期五'),'yyyy-mm-dd') dat
       from emp e order by hiredate;

---------------------------------------------------------------------
--1、查询82年员工
select * from emp e where to_char(e.hiredate ,'yy') like '82';
--2、查询36年工龄的人员
select * from emp e where (sysdate - to_date(hiredate))/365 > 36;
--3、显示员工雇佣期 6 个月后下一个星期一的日期
select e.ename , to_char(next_day(add_months(hiredate , 6),'星期一'),
       'yyyy-mm-dd') from emp e order by hiredate asc;
--4、找没有上级的员工,把mgr的字段信息输出为 "boss"
select ename , nvl(to_char(mgr) , 'boss') from emp e where mgr is null;
--5、为所有人长工资,标准是:10部门长10%;20部门长15%;30
--部门长20%其他部门长18%
--case when 方法:
select e.ename , (case deptno when 10 then e.sal*1.1 when 20 then e.sal*1.15 
       when 30 then e.sal*1.2 else e.sal*1.18  end) v_sal 
         from emp e;
--decode 方法: 
select e.ename , decode(deptno , 10,e.sal*1.1, 20,e.sal*1.15, 30,e.sal*1.2,
       e.sal*1.18) v_sal from emp e;

----------------------------------------------------------------
select sum(e.sal) , avg(e.sal) , min(sal) , max(e.sal) from emp e;
select min(hiredate) , max(hiredate) from emp e;
select count(1) from emp e ;
select count(*) from emp e ;
select count(comm) from emp ;
select count(mgr) from emp;
select count(distinct deptno) from emp;

select avg(nvl(comm,0)) from emp e ;

select deptno , avg(sal) from emp group by deptno;
select deptno , avg(sal) from emp group by deptno having avg(sal) > 2000;

--• 求部门下雇员的平均工资>2000 人数
select deptno , count(1) from emp group by deptno 
       having deptno in (select deptno from emp e 
       group by deptno having avg(sal) > 2000);
--部门薪水最高
select deptno , max(sal) max_sal from emp e group by deptno;

select max(e.max_sal) from (select max(sal) max_sal from 
       emp e group by deptno) e

select max(sal) , deptno , job from emp group by deptno , job;

select avg(sal) from emp where sal > 1200
       group by deptno having avg(sal) > 1500
       order by avg(sal) asc;
-- 部门里面 工龄最小和最大的人找出来       
--找出部门里面最大和最小工龄 
select deptno ,  max(hiredate) min_date , min(hiredate) max_date
       from emp e group by deptno;
--找出工龄对应的名字 
select e.deptno , e.ename eename , e.hiredate from emp e join
       (select deptno dt , max(hiredate) min_date , min(hiredate) max_date 
       from emp e group by deptno) t on (e.hiredate = t.min_date or 
       e.hiredate = t.max_date) and e.deptno = t.dt order by e.deptno;

---------------------------------------------------------------------
--1、查询10号部门中编号最新入职的员工,工龄最长的员工的个人信息。
select e.* from emp e join 
       (select deptno dt , max(hiredate) min_date ,min(hiredate) max_date 
        from emp e group by deptno) t on (e.hiredate = t.min_date or
        e.hiredate = t.max_date) and e.deptno = 10;
--2、从“software”找到‘f’的位置,用‘*’左或右填充到15位,去除其中的‘a’。
--–Instr()字符串出现的位置, instr( string ,’A‘)
--–lpad,rpad 填充字符型数据
--–ltrim/rtrim (string1,string2)
select instr('software','f') , lpad('software' , 15 , '*'),
       rpad('software' , 15 ,'*'),
       replace('software','a','') from dual;
--3、查询员工的奖金,如果奖金不为NULL显示‘有奖金’,为null则显示无奖金
select e.ename , nvl2(comm,'有奖金','无奖金') from emp e;
select e.ename , decode(comm,null,'无奖金','有奖金') from emp e;
--4、写一个查询显示当前日期,列标题显示为Date。再显示六个月后的日期,
--下一个星期日的日期,该月最后一天的日期。
select sysdate dat , add_months(sysdate , 6) , next_day(sysdate,'星期日'),
       last_day(sysdate) from dual;
--5、查询EMP表按管理者编号升序排列,如果管理者编号为空则把为空的在最前显
--示
select * from emp order by mgr nulls first;
--6、求部门平均薪水
select deptno , avg(sal) from emp e group by deptno;
--7、按部门求出工资大于1300人员的 部门编号、平均工资、最小佣金、
--最大佣金,并且最大佣金大于100
select deptno ,avg(sal) , min(comm),max(comm) from emp e 
       where sal > 1500 group by deptno having max(comm)>100;
--8、找出每个部门的平均、最小、最大薪水
select deptno , avg(sal) , min(sal) , max(sal) from emp e group by deptno;
--9、查询出雇员名,雇员所在部门名称, 工资等级
select e.ename, d.deptno , s.grade from emp e ,dept d , salgrade s
       where sal between losal and hisal and e.deptno = d.deptno;

select * from emp , salgrade where sal between losal and hisal;

select e.empno , e.ename , d.deptno , d.loc from emp e , dept d 
       where e.deptno = d.deptno and e.ename like 'JAMES';

select e.empno , e.ename ,d.dname , d.loc , d.deptno from emp e, dept d
       where e.deptno = d.deptno and e.deptno = 10;

select * from emp e ,salgrade s where sal between losal and hisal;

select e.ename , e.deptno , d.dname from emp e , dept d 
       where e.deptno = d.deptno(+);

select e.ename , e.deptno , d.dname from emp e , dept d
       where e.deptno(+) = d.deptno;

-----------------------------------------------------------------
--99语法
select e.empno , e.ename , e.deptno , d.loc from emp e , dept d
       where e.deptno = d.deptno;

select e.empno , e.ename , e.deptno , d.loc from emp e
       cross join dept d where e.deptno = d.deptno;

select * from emp e natural join dept d where deptno = 10;

select e.empno , e.ename , e.sal , deptno , d.loc from emp e join dept d
       using(deptno) where deptno = 10;

select e.ename , d.dname , s.grade from emp e join dept d on 
       e.deptno = d.deptno
       join salgrade s on e.sal between losal and hisal;

select * from emp e right outer join dept d on e.deptno = d.deptno;

select * from emp e left outer join dept d on e.deptno = d.deptno;

select * from emp e right join dept d on e.deptno = d.deptno;

select * from emp e inner join dept d on e.deptno = d.deptno;

select * from emp e join dept d on e.deptno = d.deptno;

select * from emp e join dept d using(deptno);

--查找那些薪水在整个雇员平均薪水之上的人
select * from emp e where (e.sal+nvl(comm , 0)) > (select 
       avg(sal+nvl(comm , 0)) from emp);
--找出所有的经理人
select distinct e.ename from emp e , emp em where e.empno = em.mgr;
select *from emp e where empno in (select distinct mgr from emp);
--找出部门20最高收入的职员
select e.ename , e.sal , e.comm from emp e join (select deptno , 
       max(sal+nvl(comm,0)) max_sal from emp group by deptno) em 
       on e.deptno = 20 and e.sal = em.max_sal;
select e.ename , e.sal , e.comm from emp e 
       where (e.sal+nvl(comm , 0)) >= all(select (sal+nvl(comm , 0))
       from emp where deptno =20) and deptno = 20;
--求每个部门平均薪水的平均水平
--求部门平均薪水
select deptno dt , avg(sal) avg_sal from emp e group by e.deptno;
--求等级
select t.dt , t.avg_sal , s.grade from (select deptno dt , avg(sal) avg_sal
       from emp e group by e.deptno) t join salgrade s on t.avg_sal between 
       losal and hisal;
       
---------------------------------------------------------------------
--1、求平均薪水最高的部门的部门编号
--求部门的平均薪水
select deptno , avg(sal+nvl(comm , 0)) from emp group by deptno ;
--求出最大值
select  max(max_avg) from (select deptno dt ,avg(sal+nvl(comm , 0)) max_avg
       from emp group by deptno) t 
--求出部门编号
select k.dt , k.sal_avg from 
       (select e.deptno dt , avg(sal+nvl(comm , 0)) sal_avg from emp e 
          group by deptno) k where k.sal_avg = (select  max(max_avg) from 
          (select deptno dt ,avg(sal+nvl(comm , 0)) max_avg
                  from emp group by deptno) t )
--2、求部门平均薪水的等级
select k.dt , k.avg_sal , s.grade from (select e.deptno dt , avg(sal) avg_sal 
       from emp e group by deptno) k join salgrade s on k.avg_sal 
       between losal and hisal;
--3、求部门平均的薪水等级
--求部门的薪水等级
select e.deptno dt , e.sal sl, s.grade gd from emp e join salgrade s on e.sal 
       between losal and hisal;
--求平均值
select k.dt , avg(k.sl) , avg(k.gd) from (select e.deptno dt , e.sal sl, 
       s.grade gd from emp e join salgrade s on e.sal 
       between losal and hisal) k group by k.dt;
--4、求薪水最高的前5名雇员
--先排列薪水
select * from emp e order by e.sal desc;
--截取前五名 
select t.* ,rownum rm from (select * from emp e order by e.sal desc) t
       where rownum <= 5;
--5、求薪水最高的第6到10名雇员
select k.* from (select t.* ,rownum rm from (select * from emp e order by 
       e.sal desc) t where rownum <= 10) k where k.rm >= 6;

---------------------------------------------------------------------
---------------------------------------------------------------------
declare
    type tb_mytable is table of dept.deptno%type index by
         binary_integer;
    v_tb_mytable tb_mytable;
begin
    dbms_output.put_line('hello world');
end;

--do while 循环:
declare
    v_num number(3,0) := 0;
begin
    loop
      dbms_output.put_line(v_num);
      v_num := v_num + 2;
      exit when v_num = 100;
    end loop;
end;

--while 循环
declare
    v_num number(3,0) := 0;
begin
    while v_num != 100 loop
      dbms_output.put_line(v_num);
      v_num := v_num + 2;
    end loop;
end;

--while循环:
declare
    type t is table of number(3) index by varchar2(3);
    hash_t t;
    l_row varchar2(3);
begin
    hash_t('a') := 10;
    hash_t('b') := 20;
    l_row := hash_t.first;
    while(l_row is not null) loop
    dbms_output.put_line(hash_t(l_row));
    l_row := hash_t.next(l_row);
    end loop;
end;

--for循环:
declare
    type t is table of number(3) index by pls_integer;
    hash_t t;
    l_row varchar2(3);
begin
    hash_t(1) := 10;
    hash_t(2) := 20;
    for i in hash_t.first..hash_t.last loop
      dbms_output.put_line(hash_t(i));
      end loop;
end;

--if条件句:
declare
    i integer;
    b01 boolean := true;
begin
    if b01 then
      dbms_output.put_line('test');
      end if;
end;


declare
    v_name varchar2(20);
begin
    select ename into v_name from emp e where
           e.deptno = 20 and e.empno = &empno;
     dbms_output.put_line(v_name);
exception
     when others then
       dbms_output.put_line('数据未找到');
       rollback;
end;

select * from emp;

declare
    v_empno emp.empno%type := &empno;
    v_comm emp.comm%type;    
begin
    select comm into v_comm from emp e where e.empno = v_empno;
    if(v_comm is null) then
        dbms_output.put_line('无奖金');
    else
        dbms_output.put_line('有奖金');
    end if;
exception
    when others then
      dbms_output.put_line(sqlcode||'-----'||sqlerrm);
    rollback;
end;

declare
    v_empno emp.empno%type := &empno;
    v_comm emp.comm%type;
begin
    select comm into v_comm from emp e where e.empno = v_empno;
    if(v_comm is null) then
        dbms_output.put_line('无奖金');
    elsif(v_comm > 0 and v_comm < 800) then
        dbms_output.put_line('奖金少的可怜');
    else
        dbms_output.put_line('奖金可观');
    end if;
exception
    when others then
      dbms_output.put_line(sqlcode||'----'||sqlerrm);
    rollback;
end;

-----------------------------------------------------------
-------------------------------------------------------------
--创建表
create  table v_temp02(
    vno number(2),
    vname varchar2(20),
    vage number(3)
);
--增
insert into v_temp02 values(10 , '王哥' , 18);
insert into v_temp02 values(11 , '杨哥' , 19);
insert into v_temp02 values(12 , '张哥' , 17);
insert into v_temp02 values(13 , '黄哥' , 20);
insert into v_temp02 values(14 , '文哥' , 21);
--commit提交事务,可加可不加,加了之后,就直接提交,而没机会回滚了
commit;
--查
select * from v_temp02;
--修改数据
begin
   update v_temp02 set vname = '忠哥' , vage = 18 where vno = 12;
   if sql%found then
      dbms_output.put_line('更新了'||sql%rowcount||'记录');
   end if;
   commit;
   if not sql%isopen then
     dbms_output.put_line('自动关闭游标');
   end if;
end;
--删除数据
delete from v_temp02 where vno = 11;
commit;
--删除表
drop table v_temp02;

-----------------------------------------------------------------
--游标
--如抓取一条数据
declare
   cursor my_cursor is select * from dept; --声明游标(定义的游标不能有into句子)
   v_dept dept%rowtype;       --定义变量
begin
   open my_cursor;            --打开游标
   fetch my_cursor into v_dept;      --使用游标
   dbms_output.put_line(v_dept.deptno||'----'||v_dept.dname||
         '---'||v_dept.loc);
   close my_cursor;                  --关闭游标
end;

--loop循环(do-while)遍历游标,利用loop循环和%notfound属性实现游标遍历
declare
   cursor my_cursor is select * from dept;   --声明游标
   v_dept dept%rowtype;       --定义变量
begin
   open my_cursor;            --打开游标
   loop                       --打开loop(do-while)循环
      fetch my_cursor into v_dept;   --使用游标
      exit when my_cursor%notfound;  --定义游标停止条件
      dbms_output.put_line(v_dept.deptno||'---'||
           v_dept.dname||'---'||v_dept.loc);
   end loop;                  --关闭loop循环
   close my_cursor;           --关闭游标
exception                     --一次
   when others then
     dbms_output.put_line(sqlcode||'---'||sqlerrm);
   rollback;
end;

--while循环遍历游标,利用while循环配合%found属性实现游标遍历。
declare
   cursor my_cursor is select * from dept;   --声明游标
   v_dept my_cursor%rowtype;         --定义变量
begin
   open my_cursor;                   --打开游标
   fetch my_cursor into v_dept;      --使用游标
   while my_cursor%found loop        --打开while循环
      dbms_output.put_line(v_dept.deptno||'---'||
             v_dept.dname||'---'||v_dept.loc);
      fetch my_cursor into v_dept;   --使用游标
   end loop;                         --关闭循环
   close my_cursor;                  --关闭游标
exception                            --异常
   when others then
     dbms_output.put_line(sqlcode||'---'||sqlerrm);
   rollback;                         --回滚
end;

--for循环遍历游标,利用for循环遍历游标,不需要打开游标,也不需要关闭游标
--甚至不用声明循环变量,不用抓取,最简单。推荐使用
declare
    cursor my_cursor is select * from dept;
    v_dept dept%rowtype;
begin
    for v_dept in my_cursor loop
       dbms_output.put_line(v_dept.deptno||'---'||v_dept.dname||
               '---'||v_dept.loc);
    end loop;
exception
    when others then
       dbms_output.put_line(sqlcode||'---'||sqlerrm);
    rollback;
end;

-------------------------------------------------------------------
--使用游标,更新状态数据,如果年薪 < 5000 低 [5000,8000] 中 >= 8000 高
--复制表
create table copy_emp02 as select * from emp where 1=1;

select * from copy_emp02;

--加入状态列
alter table copy_emp02 add status varchar2(20);

--带参数的游标
declare
    cursor my_cursor(v_no dept.deptno%type) is 
           select * from dept d where deptno = v_no;
    v_dept dept%rowtype;
begin
    for v_dept in my_cursor(&v_no) loop
      dbms_output.put_line('第'||my_cursor%rowcount||'行,数据为:'||
               v_dept.deptno||'---'||v_dept.dname||'---'||v_dept.loc);
    end loop;
end;

--参数01
declare
    cursor my_cursor(v_sal number) is select * from emp e 
           where e.sal > v_sal;
    v_emp emp%rowtype;
begin
    for v_emp in my_cursor(1500) loop        --sal大于1500的雇员
      dbms_output.put_line(v_emp.ename||'---'||v_emp.sal);
    end loop;
end;

--参数02
declare
    cursor my_cursor(v_sal number default 2000) is select * from emp e
           where e.sal > v_sal;   --默认值为2000,即sal > 2000的雇员
    v_emp emp%rowtype;
begin
    for v_emp in my_cursor(v_sal => 1500) loop
      dbms_output.put_line(v_emp.ename||'---'||v_emp.sal);
    end loop;
exception
    when others then
      dbms_output.put_line(sqlcode||'---'||sqlerrm);
    rollback;
end;

--参数03
declare
    cursor my_cursor(v_sal number default 2000) is select * from emp e
           where e.sal > v_sal;         --默认值为2000,即sal > 2000的雇员
    v_emp emp%rowtype;      
begin
    for v_emp in my_cursor loop         --带默认值的参数 ,可不加括号和参数
      dbms_output.put_line(v_emp.ename||'---'||v_emp.sal);
    end loop;
end;

-------------------------------------------------------------------
--声明游标,有参数有返回值
select * from emp where deptno = 10;
declare
   type emp_record is record(
      v_ename emp.ename%type,
      v_hiredate emp.hiredate%type
   );
   v_record emp_record;
   cursor my_cursor(v_deptno number , v_job varchar2) return emp_record
          is select ename , hiredate from emp where deptno = v_deptno 
          and job = v_job;
   v_emp emp%rowtype;
begin
   open my_cursor(10 , 'CLERK');
   loop
      fetch my_cursor into v_record;
      if my_cursor%found then
         dbms_output.put_line(v_record.v_ename||'的雇佣日期是'||v_record.v_hiredate);
      else
         dbms_output.put_line('已经处理结束了');
      exit;
      end if;
    end loop;
    close my_cursor;
exception
    when others then
    dbms_output.put_line(sqlcode||'---'||sqlerrm);
    rollback;
end;

--基于游标定义记录变量,比声明记录类型变量要方便
declare
    cursor my_cursor(v_deptno number , v_job varchar2) is select ename ,
           hiredate from emp e where e.deptno = v_deptno and e.job = v_job;
    v_cursor my_cursor%rowtype;
    v_emp emp%rowtype;
begin
    open my_cursor(10 , 'CLERK');
    loop
       fetch my_cursor into v_cursor;
       if my_cursor%found then
          dbms_output.put_line(v_cursor.ename||'的雇佣日期是'||v_cursor.hiredate);
       else
          dbms_output.put_line('已经处理完毕');
          exit;
       end if;
    end loop;
    close my_cursor;
end;

--更新或删除
create table emp2 as select * from emp ;      --创建新版,不影响旧表
select * from emp2;

--在这个例子中,我们同个select语句后面添加 for update
--来提示oracle锁定记录以便进行更新,然后用 where current of
--来指明操作时添加在当前游标所指向的记录上

declare
    cursor my_cursor is select * from emp2 for update;
    v_temp my_cursor%rowtype;
begin
    for v_emp in my_cursor loop
       if (v_emp.sal < 2000) then
          update emp2 set sal = sal * 2 where current of my_cursor;
       elsif(v_emp.sal = 1500) then
          delete from emp2 where current of my_cursor;
       end if;
    end loop;
    commit;
end;

--删除表emp2
drop table emp2;

-------------------------------------------------------------------
--动态游标:弱类型游标
declare
    type RefEmpCur is ref cursor;
    mycur RefEmpCur;
    v_emp emp%rowtype;
begin
    open mycur for select * from emp;
    loop
       fetch mycur into v_emp;
       exit when mycur%notfound;
       dbms_output.put_line(v_emp.deptno||'---'||v_emp.ename||'---'||
                 v_emp.sal);
    end loop;
    close mycur;
end;

--多语句
declare
    type RefEmpCur is ref cursor;
    mycur RefEmpCur;
    v_emp emp%rowtype;
    v_dept dept%rowtype;
begin
    open mycur for select * from emp;
    loop
       fetch mycur into v_emp;
       exit when mycur%notfound;
       dbms_output.put_line(v_emp.deptno||'---'||v_emp.ename||'---'||
                 v_emp.sal);
    end loop;
    close mycur;
    open mycur for select * from dept;
    loop
        fetch mycur into v_dept;
        exit when mycur%notfound;
        dbms_output.put_line(v_dept.deptno||'---'||v_dept.dname||'---'||
                  v_dept.loc);
    end loop;
    close mycur;
end;

--sys_refcursor
declare
    --type ref_cursor is ref cursor;
    --cur01 ref_cursor;
    cur01 sys_refcursor;
    v_emp emp%rowtype;
    v_sql  varchar2(100);
begin
    v_sql := 'select * from emp';
    open cur01 for v_sql;
    loop
       fetch cur01 into v_emp;
       exit when (cur01%notfound);
       dbms_output.put_line(v_emp.ename);
    end loop;
    close cur01;
end;

-------------------------------------------------------------------
select * from student_score;
--创建存储过程

-------------------------------------------------------------------
--实现一个函数判断数据是时间格式类型
create or replace function isDate(in_date in varchar2) return number 
       is v_result number(2);
       v_date date;
begin
    v_date := to_date(in_date , 'yyyy-mm-dd');
    v_result := case when v_date is not null then 1 else 0 end;
    return v_result;
exception
    when others then
       dbms_output.put_line(sqlcode||'---'||sqlerrm);
    rollback;
end;

select isDate('1982-02-10') from dual;

--trigger 触发器例子
create
    or replace trigger trig_temp after update on dept for each row
begin
    update emp set deptno =: new.deptno where deptno =: old.deptno;
end;

--如果没有触发器,是不能直接更新的
update dept set deptno = 90 where deptno = 30

select * from dept;




 

 

 

 

                碎点篇—— oracle 语法和练习

 

 

 

返回主目录

碎点篇—— oracle 语法和练习碎点篇—— oracle 语法和练习 万道一 发布了30 篇原创文章 · 获赞 13 · 访问量 1791 私信 关注
上一篇:硬盘安装Archlinux「2013-12-26」


下一篇:Oracle数据库-多表联合查询&子查询