数据库知识(Oracle为例)

数据库(DB)

1、数据库(DB)-----按照数据结构存储、管理数据的仓库。
   数据库管理系统(DBMS)---管理数据库的软件
2、数据库的分类:
      1》:关系数据库---------描述两元素间的关系的DB,二维数据表(table)
	oracle:oracle公司,关系数据库管理系统、支持多平台、
	DB2:IBM公司、关系数据库系统
	Sybase:Sybase公司、关系数据库系统、SAP收购
	SQL Server:微软
	MySQL、oracle公司(Sun(MySQL))绿色开源,小型关系数据库管理系统,中小型网站应用广泛、成本低
	
	表-----一个关系数据库由多个数据表组成
	   行----横排数据-----记录(Record)--------类
	   列----纵排数据-----字段(Field)---------类的属性
	   表--表=====关联关系 一对一、一对多、多对多
      2》:图形数据库
      3》:
===================================================================================
===================================================================================
3、SQL------》结构化查询语言-------不区分大小写(原则关键字大写其它小写)
					没有;排版使用;、方便
	1》应用在关系数据库上,
	  所有数据库都是用相同或相似的语言
	2》分为:DDL<数据定义语言>----建立、修改、删除数据库对象
			create:创建表或其他对象的结构
			alter :修改表或其他对象的结构
			drop  :删除表或其他对象的结构
			truncate:删除表数据,保存表结构
		 DML<数据操纵语言>----改变数据表中的数据-要经过事物控制语句提交才能真正修改
			insert:向数据表插入数据
			update:更新数据表已经存在的数据
			delete:删除数据表中的数据
		 TCL<事物控制语言>---维护数据一致性
			commit:提交,确认已经进行的数据改变
			rollback:回滚,取消已经进行的数据改变
			savepoint:保存点,使当前的事物可以回退到指定的保存点,便于取消部分改变
		 DQL<数据查询语言>--查询数据
			select:查询数据
		 DCL<数据控制语言>---执行权限的授予和收回操作
			grant:授予,用于给用户或角色授予权限
			revoke:用于收回用户或角色已有的权限
			create user :创建用户
==================================================================================
==================================================================================
Oracle数据库:
1、oracle数据库的安装(Windows、Linux):地址:www.Oracle.com
2、如何访问oracle数据库:命令行工具:SQL*PLUS   
			  图形界面工具:SQL Developer
3、Oracle数据库一般安装在服务器上,在客户端使用telnet命令登陆数据库服务器,再启动服务器的SQL*PLUS工具,使用SQL语句操作数据库
   访问操作数据库:
	 SQL*PLUS :oracle提供的数据交互工具、默认与oracle一起安装,基于C/S的SQL开发工具
		命令行输入sqlplus,进入oracle,输入用户名和密码进入,在SQL后输入相应操作命令操作
		exit---退出
	 SQL Developer:oracle提供的免费的图形化开发工具,方便美观--java开发的工具需要指定JDK的位置
		 先建立指定数据库的连接,再在界面中执行SQL语句	
============================================================================
============================================================================
============================================================================
Oracle DBMS数据类型
	number:  数字类型,number(总位数,小数点后的位数即精度) 例:number(6,2),整数位最大是4位 小数点后位数最大是2位,最大值9999.99
	char:	  固定长度的字符串类型,char(占用的字节数,最大长度2000字节),
			例:char(20) 最多存储20个字节的字符串,并且占用固定空间20个字节
			占用空间大,查询快
	varchar2:变长的字符串类型,Oracle特有,varchar2(最多占用的字节数,最大长度4000) 
			例:varchar(100) 最多存储100个字节的字符串,具体根据存储的字符串长度而定
			varchar: 变长的字符类型,与varchar2一样,用多少占多少。其他数据库也有
			查询慢,占用空间小
	date:	  时间日期类型,长度7个字节,默认格式:DD-MON-RR
1、字符串:
	char:定长字符串:存不满补空格,
		可以指定长度,不指定默认为1,最大取值是2000字节
		默认单位是字节byte,可以指定字符char
	varchar2:变长字符串,存多少占多少
		必须指定长度,最大长度4000字节
		默认单位是字节byte ,可以指定字符char
	long:varchar2的加长版,存储变长字符串,最多存储2GB的字符串数据
		限制:每个表只能有一个long类型、不能作为主键
			不能建立索引、不能出现在查询条件中
			
	clob:存储定长或变长字符串,最多存4GB字符串数据。例:name clob);
2、字符串函数:
	字符串函数 
	1、concat(p1,p2):拼接字符串,将p1,p2拼接成一个字符串
		    select concat(ename,sal) from emp_young;
		    select concat(concat(ename,':'),sal) from emp_young;
	2、SQL语句中可以使用 || 连接字符串
		select ename||':'||sal from emp_young;
	3、length(p): 获取字符串(p)的长度
		    select ename,length(ename) from emp_young;
	4、lower upper initcap:小写 大写 每个单词首字母大写
	   伪表dual 当查询的内容与任何一张表无关时,为满足from子句要求,可以使用为表,伪表智慧查询出一条记录
		    select lower('HELLOWORLD') from dual;
		    select upper('helloworld'),initcap('HELLO WORLD') from dual;
		    select ename,sal,job from emp_young where ename=lower('SCOTT');       
	5、trim ltrim rtrim :去除字符串两边 左边 右边的内容
		    select trim('e' from 'eeeeliteeee') from emp_young;--只能去除一个字符
		    select ltrim('eeeeliteee','e' ) from emp_young;
		    select ltrim('esseeseseliteee','es' ) from emp_young;--当做两个字符去除
		    select rtrim('eeeeliteeee','e') from emp_young;
	6、lpad rpad 补位函数(左补,右补),字符>位数则从左边截取保留
	   可以将指定内容显示指定位数,不足时则补充若干个指定的单一字符以达到位数
		    select lpad(sal,6,'$') from emp_young;
	7、substr(str,m[,n])函数,截取字符串
	   截取str字符串从m开始,连续截取n个,若不指定n,则是连续截取到字符串的末尾,
	   n若超过实际可截取长度,也是到字符串的末尾。***注意:数据库中下标从1开始的
		    select  substr('thrinking in java',10,2) from dual;
	8、instr(str1,str2[,n[,m]]) 查找位置  查找str2在str1中的位置,
	   若指定了位置n:从n处开始查找第一次出现的位置,若指定了m则是查找第m次出现的位置
		    select instr('thinking in java','in',4,2) from dual;
3、数值类型:
	数值类你:number(p,s)
	数值函数:
		1、round(n[,m])对n进行四舍五入,m时保留到小数点后多少位,
		  m为0或不指定,则保留到整数,m为负数,则是保留小数点前的位数
			select round(45.672,2),round(46.678),round(55.678,-2) from dual;
		2、trunc(n[,m]) 截取数字,m为0或不指定,截取整数,m>0 截取小数为  m<0 截取整数
			select trunc(45.672,2),trunc(46.678),trunc(55.678,-1) from dual;
		3、mod(n.m):求余数,若m为0,则直接返回n
			select mod(13,4) from dual;
		4、ceil  floor  入、舍(向上取整,向下取整)
			select ceil(45.678),floor(45.678) from dual;
4、日期类型:
	date 与 timestamp
	时间戳的前7个字节与date一致,多出的4个字节保存一个整数(int),可以存秒以下的精度,所以可以精确到纳秒

	日期相关的关键字
		1、sysdate:表示一个内部函数,返回一个表示当前系统时间的date类型的值
			select sysdate from dual;
			insert into emp_young(empno,hiredate)values(1001,sysdate);
			select * from emp_young;
			rollback;
		2、systimestamp:返回时间戳类型的当前系统时间
			select systimestamp from dual;
	日期类型可以比大小,越晚的越大,日期可以进行加减运算,加上一个数字等同与加上指定的天数,减法同理
		两个日期间也可以相减,差为相差的天数
		select sysdate+1 from dual;  
		查看每个员工的入职时间
		select ename,trunc(sysdate-hiredate) from emp_young;
		查看自己活了多少天
		select trunc(sysdate-to_date('1992-1-12','yyyy-MM-DD')) from dual;
	日期转换函数:
		1、to_date()函数  将一个字符串按照指定的日期格式转换为date
		    RR:两位数字表示年,会自动判定世纪  to_date('05-05-81','DD-MON-RR');
		    查看1982年以后入职的员工
			select ename,hiredate from emp_young where hiredate>to_date('1982-01-01','yyyy-MM-DD');
		2、to_char()函数  将日期按照指定日期格式转换为字符串,
		  日期格式字符串中,出现字符凡不是英文和符号,其他字符都要使用双引号括起来
			select to_char(sysdate,'yyyy-MM-DD HH24:MI:SS') from dual;
			select to_char(sysdate,'YYYY"年"MM"月"DD"日"') from dual;
			select to_char(to_date('50-02-04','RR-MM_DD'),'YYYY-MM-DD') from dual;
	日期常用函数:
		1、last_day(date) 返回给定日期所在月的月底日期
			当月的月底是哪天?
			select last_day(sysdate) from dual;
		2、add_months(date,i) 对指定日期date加上指定的月i
			查看每个员工入职20周年的纪念日
			select ename,add_months(hiredate,12*20) from emp_young;
			查看73个月以前是哪天
			select add_months(sysdate,-73) from dual;
		3、months_between(date1,date2)返回两个日期之间相差的月,计算是根据date1-date2计算结果的
			查看每个员工距今入职多少个月了
			select ename,months_between(sysdate,hiredate) from emp_young;
		4、next_day(data,i) 返回给定日期之后的最近的周几对应的日期,i表示周几,1为周日,2为周一,以此类推
			select next_day(sysdate,4) from dual;
		5、least()、greatest()函数,返回列表中的最小值与最大值
			select least(sysdate,to_date('2008-10-10','YYYY-MM-DD')) from dual;
			查看每个员工的入职时间,
			若是82年以后入职的,则显示其入职时间,若是82年以前入职的则显示为1982-01-01
			select ename,greatest(hiredate,to_date('1982-01-01','YYYY_MM_DD')) from emp_young;
		6、extract()函数  提取一个日期中指定的日期分量对应的值
			select extract(year from sysdate) from dual;
			查看1982年入职的员工
			select ename from emp_young where extract(year from hiredate)=1981;
5、空值:
	1、数据库中,任何字段的默认值都为null
	2、显示插入null:隐式插入null:
		create table student_young(id number(4),
				  name char(20),
				  gender char);
		显示插入:insert into student_young values(1000,'李莫愁',null);
		隐式插入:insert into student_young(name,gender) values('张无忌','M');
	3、更新null值
	      update student_young set gender=null where id=1000;
	4、null 作为条件进行过滤,不能使用=
	      select * from student_young where gender is null;
	      select * from student_young where gender is not null;
	5、null 的运算:null 与字符串连接等于什么也没干,null与数字连接或运算结果是null。
	      select ename,sal,comm,sal+comm from emp_young;--comm为null时相加结果null
	6、空置函数:
		nvl(p1,p2)当p1为null时,函数返回p2,若p1不是null,返回p1自身,所以是将null替换为一个非null值    
		      select ename,sal,comm,sal+nvl(comm,0) from emp_young;
		nvl2(p1,p2,p3) 当p1不是null返回p2,是null返回p3。p2,p3要类型一致,与p1类型不要求  
		      查看每个员工的奖金状态,有显示"有奖金" 无显示"没有奖金"
		      select ename,comm,nvl2(comm,'有奖金','没有奖金') from emp_young;
		      select ename,sal,comm,nvl2(comm,sal+comm,sal) from emp_young;
==========================================================================
==========================================================================
=======================================================================
DDL----对表进行操作
5、创建表:		create table 表名(
					列名1 数据类型1,
					列名2 数据类型2,
					....
					列名n 数据类型n
					);------------冒号可以没有,使用方便操作
   查看表结构:		desc 表名    查询结果:属性名称 是否为空 数据类型	   
   给列指定默认值:	default '..' 在数据库中,所有数据类型的默认值都是null,使用default设置后默认值就是设置的
					例如:gender char(1) default 'M' 如果没有指定性别默认是男
					
   非空:		not Null 默认字段值可以为空,设置之后必须是有效值,任何情况下都不能为null
   删除表:		drop table 表名;
6、修改表名:rename 旧表名 to 新表名;
   增加列:  alter table 表名 add(
				  列名1 数据类型1,
				  ...
				  列名n 数据类型n
				  ) ;
   删除列:  alter table 表名 drop(
				   列名1,
				   ...
				   列名n
				    );
   修改列:  alter table 表名 modify(
				   列名1 数据类型1 默认值(修改需要修改的数据),
				   ...
				   列名1 数据类型1 默认值(修改需要修改的数据)
				    );
	     可以修改列的数据类型、长度、以及默认值或非空,当表中存在数据后,尽量不修改字段内容,若修改长度尽量不要减小,否则可能会修改失败		
=========================================================================================
DML-------提交才生效,DML可以对数据表中的数据进行操作,分为 insert update delete DML是伴随事物(TCL)使用的
7、增加记录:insert into 表名(列名1,列名2,...,列名n)values(值1,值2,...值n);前后对应就行,不一定所有字段都要有值,建议使用
	      insert into 表名values(值1,值2,...值n);全列插入,顺序必须一样
	      插入日期值:通过to_date(日期,格式)函数
	      insert into myemp_young(id,name,birth)values(1,'rose',to_date('2008-08-02','yyyy-MM-DD'));
   更新表数据: update 表名 set 列名=值,(列名n=值n...) where 列名=值;不加where就会整张表修改,where约束条件
   删除数据:	 delete from 表名 where 列名=值;删除表中列名=值的行记录,**没有where会整张表数据删除
		 DDL删除  truncate table 表名; 删除表全部数据,保留表结构
   delete和truncate区别:
	   delete:		 truncate
	   有条件删除		全部删除
	   DML语句,可以回滚	DDL语句,立即生效,无法回滚
	   删除全表数据效率低	删除全表数据效率高
	   
====================================================================
DQL  (Date Query Language)数据查询语句:用于查询数据
查询表中所有字段
        select * from emp_young;
查询表中指定字段
        select ename,job,sal,deptno from emp_young;
select 子句可以查看:字段、函数、表达式
        查看员工的年薪
        select ename,sal*12 from emp_young;
 select 子句可以使用 where子句约束条件
        查看20号部门的员工信息
        select ename,sal,job,deptno from emp_young where deptno=20;
        查询职位是CLERK的员工
        select ename from emp_young where job='CLERK';
1、别名:当select子句中查询的内容是一个函数或表达式,那么结果集对应的该字段名就是这个函数名或表达式,可读性差
  为此应为该列添加别名。
      select ename,sal*12 as sals from emp_young;
      select ename,sal*12 sals from emp_young;--as可以省略
      select ename,sal*12 "s als" from emp_young;--区分大小写或空格用双引号括起来
2、判断条件:>,<,=,>=,<=,<>(!=oracle特有)
      select ename,sal from emp_young where sal=2000;
      select ename,sal,job from emp_young where deptno<>10;
      select ename,sal,hiredate from emp_young where hiredate>to_date('1982-1-1','YYYY-MM-DD');
3、关键字:and,or
      select ename,sal,job from emp_young where sal>1000 and job='CLERK';--且
      select ename,sal,job from emp_young where sal>1000 or job='CLERK';--或
      查看工资高于1000的CLERK与SALESMAN。and的优先级高于or,添加()提高优先级 
      select ename,sal from emp_young where sal>1000 and (job='CLERK' or job='SALESMAN');
4、like(模糊查询) 支持两个通配符: % 0或多个字符,_一个字符
      查看名字第二个字符是A的员工
      select ename,job from emp_young where ename like '_A%';
5、in 、not in 查询出在列表里和不再列表里条件的数据,常用于子查询
      查询出工作是MANAGER或CLERK的员工信息
      select ename,job,sal from emp_young where job in ('MANAGER','CLERK');
      查询出工作不是MANAGER或CLERK的员工信息
      select ename,job,sal from emp_young where job not in  ('MANAGER','CLERK');
6、between...and...在什么之间 数字、字符、日期同样适用
      select  ename,sal from emp_young where sal between 1500 and 3000;
7、null 的用法     
      select ename,comm from emp_young where comm is null;
      select ename,comm from emp_young where comm is not null;
8、any、all 任何一个项,所有项,用与判断>,<,>=,<=一个列表中的内容,
    any,all列表中通常不是确定值,是子查询的结果
    >any(list) 大于列表中最小的   >all(大于列表中最大的) 其他判断同理
      select ename,empno,job from emp_young where sal>any(2000,4000,5000);
      select ename,empno,job from emp_young where sal>all(3000,4000,4500);
9、可以使用函数或表达式的IE过作为过滤条件
      select ename,sal from emp_young where ename=upper('scott');
      select ename,sal from emp_young where sal*12>50000;
10、distinct 去除查询结果后的重复数据,必须紧跟select后,
      查看公司共有多少种职位
      select distinct job from emp_young;  
      distinct 后可跟多个字段,字段值的组合没有重复
      select distinct job,deptno from emp_young;

11、排序:order by... 子句可以根据后面指定的字段对结果集进行升序或降序排序,
    asc 升序 desc 降序,不写默认是 asc 升序。该句只能写在select最后一个子句上
      查看公司工资的排名
      select ename,sal from emp_young order by sal;--升序
      select ename,sal from emp_young order by sal asc;--升序
      select ename,sal from emp_young order by sal desc;--降序
      *order by...可以按照多个字段排序,当一个字段有重复值时,才按照第二个字段排序。
      select ename,deptno,sal from emp_young order by deptno asc,sal desc;
12、聚合函数:聚合函数又称为多行函数,分组函数,聚合函数可已将多条记录进行统计,
    然后得出一个结果,所以聚合函数使用来龙及使用的。聚合函数忽略null值
    12.1、max()、min()、统计最大值和最小值。
      查看公司的最高工资和最小工资
      select max(sal),min(sal) from emp_young;
    12.2、avg()、sum()、求平均值,总和,聚合函数忽略null值(平均值时忽略null选项)
      查看公司员工工资的平均值和工资总和
      select avg(sal),sum(sal) from emp_young;
    12.3、count(),统计有多少条记录,聚合函数忽略null值
      统计公司有多少人
      select count(ename) from emp_young; 
      select count(comm) from emp_young;--4条记录,忽略null值
    12.4、聚合函数忽略null值
      select avg(comm),sum(comm) from emp_young;
      select avg(nvl(comm,0)) from emp_young;
      统计表中总数据量,建议使用*或唯一标示即主键
      select count(*) from emp_young;
13、分组:
    13.1、group by...子句  可以将结果集按照指定的字段值相同的记录看做一组,
          配合聚合函数使用可以对不同分组的记录分别进行统计然后得到结果
            查看每个部门最高工资和最低工资
            select max(sal),min(sal),deptno from emp_young group by deptno;
            *在select语句中若使用了聚合函数,那么不在聚合函数中的其他单独字段必须出现在
            group by 子句中,反过来不是必须的
            查看每种职位的平均工资和工资总和是多少
            select avg(sal)),sum(sal),job from emp_young group by job;
            *group by 可以按照多个字段分组,分组原则是这些字段值的组合相同的看做一组
            查看每个部门每种职位的平均工资
            select avg(sal) from emp_young group by deptno,job;
            查看部门的平均工资,前提是部门平均工资高于2000
            select avg(sal) from emp_young where avg(sal)>2000 group by deptno;错 
            *where的过滤时机:
            where是在查询表中的每一条数据时进行过滤的,只会将满足where条件的查询出来 
    13.2、having、子句必须紧跟在 group by...之后作用是添加条件来过滤不同的分组
          having可以使用聚合函数作为过滤条件
            查看部门的平均工资,前提是部门平均工资高于2000
            select avg(sal),deptno from emp_young group by deptno having avg(sal)>2000; 
            查看部门平均工资高于2000的这些部门的最高工资和最低工资
            select  max(sal),min(sal),deptno from emp_young group by deptno having avg(sal)>2000;
            查看最高工资>=3000 职位的平均工资是多少
            select avg(sal),job from emp_young group by job having max(sal)>=3000;
14、语句执行顺序:from 从右到左  where/order by 从左到右 
=========================
关联查询:理解为多表查询。关联查询是建立在多张表上进行联合查询,查询的结果集中到每一条记录中的字段
可能来自不同的表。重点是:找到表与表之间的对应关系
1、   查询员工的信息和部门信息,两张表中的信息
      select ename,job,sal,dname,loc from emp_young,dept_young 
      where emp_young.deptno=dept_young.deptno;
      查询时列出项两张表都有,要带上表名
      select ename,job,sal,dname,loc,emp_young.deptno from emp_young,dept_young 
      where emp_young.deptno=dept_young.deptno;
      查询时列出项建议带上表名,表名可以有别名
      select e.ename,e.job,e.sal,d.dname,d.loc
      from emp_young e,dept_young d 
      where e.deptno=d.deptno;--连接条件
***上述SQL语句中:e.deptno=d.deptno条件用来联系emp_young,dept_young的数据关系的
这个样的条件称为:连接条件
***在关联查询中,必须要添加连接条件,N张表关联查询至少要添加N-1个连接条件,
不添加连接条件会产生笛卡尔积。实际开发中要避免笛卡尔积的出现,这是一个无意义的结果集
2、过滤条件和连接条件要同时成立
      查看SALES部门的员工
      select e.ename,e.job,e.sal,e.deptno,d.dname from emp_young e,dept_young d
      where e.deptno=d.deptno and d.dname='SALES';
      查看在NEW YORK工作的员工
      select e.ename,d.loc from emp_young e,dept_young d 
      where e.deptno=d.deptno and d.loc='NEW YORK';
              连接条件              过滤条件
3、内连接:关联查询的另一种写法,可以使连接条件和过滤条件分离,结构更好
      查看员工的姓名和部门
      select e.ename,d.dname 
      from emp_young e join dept_young d on e.deptno=d.deptno;
              表与表                         连接条件
      select e.ename,d.dname from emp_young e join dept_young
      on e.deptno=d.deptno where d.dname='SALES';
          连接条件                过滤条件
      查看每个员工以及所在的部门信息
      select e.ename,e.sal,d.dname,d.loc from emp_young e join dept_young d
      on e.deptno=d.deptno;
      *scott没有被查出来,原因是他的部门号是50,不满足连接条件,
      若想将不满足连接条件的也列出来,需要使用外连接
4、外连接:分为 左外连接、右外连接、全外连接,原理类似
          左外连接:以join左侧的表为驱动表,该表所有记录都要显示出来,
          那么当某条记录不满足连接条件时,那么来自join右侧表中的字段的值全部显示为null。
          左外连接:查询员工的信息和部门信息
          select e.ename,e.sal,d.dname,d.loc 
          from emp_young e left outer join dept_young d 
          on e.deptno=d.deptno;
          **关联查询也可以实现外连接效果,(+)定义在连接条件上,定义在哪边哪边就补null
          但不能实现全外连接效果
          select e.ename,e.sal,d.dname,d.loc from emp_young e,dept_young d
          where e.deptno=d.deptno(+);
          右外连接:
          select e.ename,e.sal,d.dname,d.loc 
          from emp_young e Right outer join dept_young d 
          on e.deptno=d.deptno;
          **
          select e.ename,e.sal,d.dname,d.loc from emp_young e,dept_young d
          where e.deptno(+)=d.deptno;
          全外连接:
          select e.ename,e.sal,d.dname,d.loc 
          from emp_young e full outer join dept_young d 
          on e.deptno=d.deptno;
5、自连接:当前表的一条记录对应当前表自己的多条记录,这种设计就是自连接,
自连接是用来解决数据内容相同,但是数据间又存在上下级关系的树状结构的情况。
          查询员工以及上司的名字:
          select e.ename,m.ename from emp_young e,emp_young m
          where e.mgr=m.empno;
          
          select e.ename,m.ename from emp_young e,emp_young m
          where e.mgr=m.empno(+);
=====================================================================================
=====================================================================================
高级查询:
1、子查询
  1.1、子查询:子查询就是一条查询语句,他是嵌套在其他SQL语句中的,目的是为实际的SQL语句提供数据
   子查询可以应用在DQL,DDL,DML中
      查看比CLERK工资高的员工
      select ename,sal from emp_young 
      where sal>(select sal from emp_young where ename='CLARK');      
      查看和CLARK相同部门的员工
      select ename,deptno from emp_young 
      where deptno=(select deptno from emp_young where ename='CLARK'); 
      查询高于公司平均工资的员工信息
      select ename,sal,deptno,job from emp_young 
      where sal>(select avg(sal) from emp_young);
  1.2、子查询在DDL中的应用,可以根据查询的结果集快速创建一张表
  创建一张表myemployee含有字段:
  empno,ename,sal,job,deptno,dname,loc 数据来自emp_young和dept_young 
      create table myemployee as 
      select e.empno,e.ename,e.sal,e.job,d.dname,d.loc 
      from emp_young e,dept_young d where e.deptno=d.deptno;       
           
      create table myemployeeL as    
      select e.empno,e.ename,e.sal,e.job,d.dname,d.loc 
      from emp_young e join dept_young d on e.deptno=d.deptno;            
      将CLARK所在部门所有员工的工资增加500
      update emp_young set sal=sal+500 where 
      deptno=(select deptno from emp_young where ename='CLARK'); 
  1.3、子查询根据结果不同,分为:
  单行单列子查询:常用作过滤条件
  多行单列子查询:常用作过滤条件
  多行多列子查询:常当做表看待
  理解:单列当做过滤条件,多列当做表
      多行单列子查询:
      select ename,job,deptno from emp_young where 
      deptno in (select deptno from emp_young where job='SALESMAN') and 
      job <>'SALESMAN');--deptno等于列表之一
      查看比所有职位是CLARK和SALEXMAN工资都高的员工信息
      select ename,job,deptno from emp_young where 
      sal>all(select sal from emp_young where job in ('CLeRK' ,'SALESMAN'));
  1.4、在having子句中:
      查看部门的最低薪水,前提是该部门的最低薪水要高于30号部门的最低薪水
      select min(sal),deptno from emp_young group by deptno having 
      min(sal)>(select min(sal) from emp_young where deptno=30); 
  1.5、在from子句中:多行多列当表看待
      查看高于自己所在部门平均工资的员工
      select  e.ename,e.sal,s.deptno from emp_young e,
      (select avg(sal) avg_sal,deptno from emp_young group by deptno) s  --在查询语句中多行多列当表看待
      where e.deptno=s.deptno and e.sal>s.avg_sal;--关联条件、过滤条件
      --------------------------------------
      查看4人以上含4人的部门员工的工资都是多少
      select e.ename,e.sal,e.deptno from emp_young e,
      (select deptno,count(deptno) from emp_young group by deptno 
      having count(deptno)>=4) s 
      where e.deptno=s.deptno and e.deptno=s.deptno;
      ---------------------------------------
      select e.ename,e.sal,e.deptno from emp_young e,
      (select count(*) p_count,deptno from emp_young group by deptno) t
      where e.deptno=t.deptno and t.p_count>=4;
      ---------------------------------------
      select ename,sal,deptno from emp_young 
      where deptno in 
      (select deptno from emp_young group by deptno having count(*)>=4);
  1.6、exists 关键字:该关键字后面跟一个子查询,用于where中作为过滤条件使用,
      是用来判断其后的子查询是否可以查询出数据,若可以则exists返回真,否则返回假
      查看有员工的部门    
      select d.deptno,d.dname,d.loc from dept_young d
      where exists(
       select * from emp_young e
       where e.deptno=d.deptno
      )
      ---------------------------
      select d.deptno,d.dname,d.loc from dept_young d
      where not exists(
       select * from emp_young e
       where e.deptno=d.deptno
      )
  1.7、子查询在select子句中: 
      select e.ename,e.sal,(select d.dname from dept_young d where d.deptno=e.deptno) 
      from emp_young e;
                              查出来只能有一个值,有内容列出来,没有补null
      --------------------------------------------------
      查看有下属的员工的工号、名字、职位、工资
      select distinct e.empno,e.ename,e.job,e.sal from emp_young e,emp_young s
      where e.empno=s.mgr;
2、分页查询(oracle):分页查询就是分段查询数据(分批查询数据),在查询的数据量非常大的时候尤其重要
分也可以减少系统资源消耗,响应速度快,不同数据库分页的语法不一致。
  2.1、oracle中使用 rownum 解决分页。rownum 是一个伪列,不存在于任何一张表中,但是每张表都可以查询
  该字段,在查询某张表时,只要可以查询出一条记录,该字段的值就是这条行号的记录,从1开始,生成的
  过程在查询过程中进行。
     select rownum,ename,sal,deptno from emp_young;
     获取6-10
     select rownum,ename,sal from emp_young where rownum between 6 and 10;--错
      以上查询不出任何数据,因为编号是在查询的过程中进行的,所以不能用rownum在编号的
      过程中进行>1以上的数字判断,否则查询不出数据。
     select * from (select rownum rn,ename,sal,deptno from emp_young) 
     where rn between 6 and 10; --必须给伪列别名
    --------------------------------------------
    查看公司工资排名的6-10名
    select rownum,ename,sal from emp_young 
    where rn between 6 and 10 order by sal desc;--错
    *在分页查询中有排序需求时,一定要先排序,因为排序总是在SQL最后执行 
    select * from(
                  select rownum rn,t.* from( 
                  select ename,sal from emp_young order by sal  desc) t)
    where rn between 6 and 10;
    ----------------------
    select * from
                (select rownum rn,t.* from
                    (select ename,sal from emp_young order by sal desc) t
                    where rownum<=10
                ) --编号小于10的编号,大于10的不编号,效率更高
    where rn>=6;--数据量大时更加快速
    -------------------------------------------------------    
  2.2、计算分页的公式:在编程语言中使用
      page:页号                   第几页
      pageSize:每页的条目数       每页的内容多少
      start:(page-1)*pageSize+1  每页从第几条开始
      end:pageSize*page          每页到第几条结束
3、decode(...[,default])函数,
可以实现分支结构,都不匹配返回default,没有default返回null
    3.1、
      select ename,job,sal,
      decode(job,'MANAGER',sal*1.1,'ANALYST',sal*1.1,'SALESMAN',sal*1.05,sal) bonus
      from emp_young;  
      --有逗号
      -----------------------------------
     3.2、 case..when..then..else..end...函数:
      select ename,job,sal,case job when 'MANAGER' then sal*12 
                                    when 'ANAYST'  then sal*11
                                    when 'SALESMAN'then sal*1.05
                            else sal end   bonus --没有逗号
      from emp_young;            
      ------------------------------------------------         
    3.3、decode(...)在分组查询中应用
      select count(*),decode(job,'MANAGER','VIP','ANALYST','VIP','OTHER') 
      from emp_young 
      group by decode(job,'MANAGER','VIP','ANALYST','VIP','OTHER');
    !排序中:排序的时候null被认为最大值,排在最上面  不常用
      select deptno,dname,loc from dept_young order by
      decode(dname,'OPERATIONS',1,'ACCOUNTING',2,'SALES',3);--类型对应相同即可
==================================
4、排序函数:排序函数允许按照指定字段分组,再按照指定字段排序,然后生成组内编号
  4.1、row_number() over( partition by...order by....):生成组内连续且唯一的编号
        查看每个组工资排名
        select ename,sal,deptno,
        row_number() over(
                       partition by deptno  --分组
                       order by sal desc    --排序
                      ) rank 
        from emp_young;
  4.2、rank() 生成组内不连续也不唯一的组内编号
        查看每个组工资排名
        select ename,sal,deptno,
        rank() over(
                       partition by deptno  --分组
                       order by sal desc    --排序
                      ) rank 
        from emp_young;
    4.3、dense_rank() 生成组内连续但不唯一的组内编号
        select ename,sal,deptno,
        dense_rank() over(
                       partition by deptno  --分组
                       order by sal desc    --排序
                      ) rank 
        from emp_young;
==========================================
5、集合操作:
  5.1、 并集、union:合并后会自动去掉重复元素,对结果排序
             union all:合并后不会去掉重复元素,对结果不排序
             查看职位是MANAGER且工资大于2500的员工信息
          select ename,job,sal from emp_young where job='MANAGER'
          union
          select ename,job,sal from emp_young where sal>2500;
          ------------------
          select ename,job,sal from emp_young where job='MANAGER'
          union all
          select ename,job,sal from emp_young where sal>2500;
  5.2、交集:intersect:显示两个查询结果集的交集,以第一列的数据做升序排列
          查看工资大于2500的职位是MANAGER的员工信息
          select ename,job,sal from emp_young where job='MANAGER'
          intersect
          select ename,job,sal from emp_young where sal>2500;
  5.3、差集:minus:获取两个结果集的差集,即结果集1减去结果集2的结果集
          查看职位是MANAGER但薪水低于2500的员工信息
          select ename,job,sal from emp_young where  job='MANAGER'
          minus
          select ename,job,sal from emp_young where sal>2500;
=======================================================
高级分组函数辅助表 sales_tab

      create table sales_tab(
        year_id number not null,
        month_id number not null,
        day_id number not null,
        sales_value number(10,2) not null
      )
      commit
      desc sales_tab
      insert into sales_tab
      select trunc(DBMS_RANDOM.value(low=>2010,high=>2012))as year_id,
       trunc(DBMS_RANDOM.value(low=>1,high=>13))as month_id,
       trunc(DBMS_RANDOM.value(low=>1,high=>32))as day_id,
       trunc(DBMS_RANDOM.value(low=>1,high=>100),2)as sales_value
       from dual
       connect by level<=1000;
       commit;
6、高级分组函数:
    rollup、cube(a,b,c...)、grouping sets()是group by 子句的扩张
    查看每天的营业额
    select year_id,month_id,day_id,sum(sales_value) from sales_tab
    group by year_id,month_id,day_id
    order by year_id,month_id,day_id;
    查看每月的营业额
    select year_id,month_id,sum(sales_value) from sales_tab
    group by year_id,month_id
    order by year_id,month_id
    查看每年营业额
    select year_id,sum(sales_value) from sales_tab
    group by year_id
    order by year_id
    查看总的营业额
    select sum(sales_value) from sales_tab
    查看每天,每月,每年,以及总额?
          select year_id,month_id,day_id,sum(sales_value) from sales_tab
          group by year_id,month_id,day_id
        union all
          select year_id,month_id,null,sum(sales_value) from sales_tab
          group by year_id,month_id
        union all
          select year_id,null,null, sum(sales_value)from sales_tab
          group by year_id
        union all
          select null,null,null,sum(sales_value)from sales_tab

  6.1、rollup:分组方式递减分组
          group by rollup(a,b,c)
          等同于
          group by a,b,c
           union all
          group by a,b
            union all
          group by a
            union all
          全表
          ------------
        select year_id,month_id,day_id,sum(sales_value) from sales_tab
        group by rollup(year_id,month_id,day_id);
  6.2、cube(a,b,c...): cube分组方式是全方位的,分组方式是2的参数个数次方。
        a,b,c
        a,b
        a,c
        b,c
        a
        b
        c
        全表
        select year_id,month_id,day_id,sum(sales_value) from sales_tab
        group by cube(year_id,month_id,day_id);
  6.3、grouping sets()允许指定不同的分组方式,然后将这些分组的结果并在一个结果集里
        查看同年同月与每年的营业额
        select year_id,month_id,sum(sales_value) from sales_tab
        group by grouping sets(
          (year_id,month_id),year_id
        ) 
        order by year_id,month_id;
       
====================================================================
====================================================================
====================================================================
1、视图:虚拟表,将查询到的数据表中的数据认为是一个表,实际上不存在没有数据,数据随基表是变化的,
是数据库对象之一,数据库对象有:表、视图、索引、序列
视图在SQL中体现的角色和表相同,它只对应一个查询语句的结果集,
所以查询一张视图时,会先执行该视图对应的查询语句,得到结果集,根据这个结果集进行实际的查询
    1.1、视图分为:简单视图:基于单表、不包含表达式或函数.可以DML,操作DML就是操作基表
                 复杂视图:包含表达式或函数,连接视图(基于多表查询结果集),不能进行DML操作
        视图作用:方便查询:复杂查询可以基于视图查询
                 限制数据访问:只能查到视图中的字段
        用户权限:有权限才能创建视图:
                  grant...(授予何种权限)to...(授权给谁)。(DCL授权命令)
                  grant create view to tarena
    1.2、创建简单视图:
        create view v_emp_young_dept10 as
        select empno,ename,sal,deptno from emp_young where deptno=10;
        查询视图内容:
        select * from v_emp_young_dept10;
    1.3、视图可以通过create or replace view 创建或替换,有替换没有创建,
         字段起别名,当视图对应的查询语句中含有函数或表达式时,该字段必须给别名
        create or replace view v_emp_young_dept10 as
        select empno id,ename name,sal salary,deptno from emp_young
        where deptno = 10;
        查询视图内容:
        desc v_emp_young_dept10;
        select * from v_emp_young_dept10;
    1.4、对视图进行DML操作,仅能对简单视图进行DML操作,复杂视图不允许DML操作,
        简单视图:视图数据来自一张表且不含函数或表达式
        复杂视图:查询语句含有表达式、函数、分组等
                连接视图:数据来自多张表,算作复杂的一种
        对简单视图进行DML操作可以,但不能违反基表的约束条件,可能失败。
        基表:视图数据来源表,对视图进行DML操作就是对基表进行DML操作
       例1:给视图插入数据  插入基表->视图显示
        insert into v_emp_young_dept10(id,name,salary,deptno)
        values(1001,'JACK',5000,10);
        select * from v_emp_young_dept10
        select * from emp_young;
      例2:更新数据,更新基表->更新视图
        update v_emp_young_dept10 set salary=9000 where id=1001;
        select * from v_emp_young_dept10
        select * from emp_young;
    1.5、对视图进行某些DML操作时,可能导致视图自身对该记录不可见,但是依然能影响基表记录,
      这种操作是对基表的“污染”。
        *部门是20,视图中不可见
        insert into v_emp_young_dept10(id,name,salary,deptno)
        values(1002,'ROSE',5000,20);
       
        update v_emp_young_dept10 set deptno = 20;
        *delete不会出现该问题,,由于删除不掉数据,所以也不会对基表数据删除
        delete from v_emp_young_dept10 where deptno=20;
    1.6、with check option 对视图添加检查选项,来避免基表污染,添加了检查选项的视图要求对视图进行DML操作后
    试图必须对其可控(insert后视图必须可见,update后视图也必须对其可见,delete没有该问题)
        create or replace view v_emp_young_dept10 as
        select empno id,ename name,sal salary,deptno 
        from emp_young where deptno=10
        with check option;
    1.7、with read only 对视图添加只读选项,添加后,不能对视图进行DML操作
        create or replace view v_emp_young_dept10 as
        select empno id,ename name,sal salary,deptno  
        from  emp_young where deptno=10
        with read only;
    1.8、数据字典:是一系列的表,这些表中的数据由数据库自身维护,用来记录用户创建过的数据库对象
    的清单,当需要时,可以查看这些数据字典
        user_objects:记录了所有数据库对象
            查看所有创建过的视图
            select object_name,object_type from user_objects
            where object_type='VIEW' and object_name like '%_young_dept10';--where object_type='TABLE';
        user_tables:记录用户创建过的所有表的数据字典
            select table_name from user_tables;
        user_views:记录用户创建过的所有视图的数据字典
            select view_name,text from user_views;
    1.9、创建复杂视图:
        创建一个部门工资情况的视图
            create or replace view v_salinto as 
            select avg(e.sal) avg_sal,
                   sum(e.sal) avg_sum,
                   max(e.sal) max_sal,
                   min(e.sal) min_sal,
                   e.deptno,d.dname
            from emp_young e,dept_young d
            where e.deptno=d.deptno
            group by e.deptno,d.dname;
            查看比自己所在部门平局没工资高的员工信息
            select e,ename,e.sal,e.deptno from emp_young,v_salinfo v
            where e.deptno=v.deptno and e.sal>v.avg_sal;
     1.20、删除视图:删除视图并不会对基表有任何影响
           drop view v_emp_young_dept10
==============================================================
2、序列:数据库对象之一,用来生成一系列唯一数字值的数据库对象,值由数据库按递增或递减自动生成
通常序列生成的数字是为某张表的主键字段(id)提供值的。可为多个表提供主键值
     2.1、创建序列:
            create sequence seq_name
            start with 初始值 
            increment by 步长
            MAXVALUE 最大值(默认没有最大值)
            MINVALUE 最小值(默认没有最小值)
            cycle |(nocycle) 提增或递减至最大值或最小值是否重用序列,
            cache p |(nocache) 有缓冲区,默认没有缓冲区,
            用来指定预存p个数据在缓冲区提高序列值的生成效率,默认是20
            ----------------------------
            create sequence seq_emp_empno
            start with 1000 
            increment by 10;
     2.2、序列支持两个伪列:
     nextval:使序列生成下一个数字,新创建的序列第一次生成是start with指定的数字,
             以后就是上次生成的数字加上步长得到的,序列不能后退,
             所以生成新数字后就不能得到以前的数字了
     currval:返回序列最后生成的数字,新创建的序列至少调用一次nextval后才可以使用currval
             select seq_emp_empno.nextval from dual;--生成新数字
             select seq_emp_empno.currval from dual;--沿用最后的数字
    2.3、使用序列:通常用于给主键字段(ID)赋值使用
             insert into emp_young(empno,ename,job,sal,deptno)
             values(seq_emp_empno.nextval,'rose','CLERK',1000,10);
             
             select * from emp_young;
    2.4、删除序列:
             drop sequence seq_emp_empno;
=============================================================
3、索引:提高查询效率机制,一旦建立由数据库维护自动调用
    3.1、创建索引:
           给emp_young表的ename字段添加索引
           create index idx_emp_ename on emp_young(ename);
           select * from emp_young where ename='SCOTT';--当查询时会自动应用索引
           *复合索引:多列索引,基于多个列的索引
           create index idx_emp_job_sal on emp_young(job,sal);
           当查询时会自动应用idx_emp_job_sal复合索引
           select empno,ename,sal,job from emp_young order by job,sal;
           *给函数创建索引
           create index emp_ename_upper_idx on emp_young(upper(ename));
           当做下面查询时,会自动应用刚刚建立的索引
           select * from emp_young where upper(ename)='KING';
    3.2、修改或删除索引
         重建索引(修改索引):alter index index_name rebuild
         alter index idx_emp_ename rebuild;
         删除索引:  drop index index_name;
         drop index idx_emp_ename;
   3.2、使用索引的原则:
         不要在小表上建立索引
         不要在经常进行DML操作的表上建立索引
         ...........
===========================
4、约束:保证字段值符合要求
      4.1、非空约束(NN):该字段值不能为空,默认字段值可以为空
        1:建表时添加非空约束:
          create table employees(
            eid number(6),
            name varchar2(30)not null,
            salary number(7,2),
            hiredate date constraint employees_hiredate_nn not null
          );
        2:修改非空约束:not null 非空约束也是列级约束,只能在修改表中字段的同时修改该约束
          alter table employees modify(eid number(6) not null);--修改字段,增加非空约束
          alter table employees modify(eid number(6) null);--取消非空约束
     4.2、唯一性约束(UK):unique,保证字段或字段的组合不出现重复值,null除外。
        1:建表时添加唯一性约束
          create table employees1(
            eid number(6) unique,
            name varchar2(30),
            email varchar(50),
            salary number(7,2),
            hiredate date,      --这里有冒号
            constraint employees_email_uk unique(email)
          );
          插入记录测试唯一性约束
          insert into employees1(eid,name,email,salary)values(1001,'roes','oo@',1000);
          insert into employees1(eid,name,email,salary)values(null,'roes',null,1000);
          select * from employees1;
        2:添加唯一性约束:
          alter table employees1 add constraint employees1_name_uk unique(name);
          delete from employees1;
    4.3、主键约束(PK):primary key:主键是记录的唯一标识。每张表通常都要有主键(id),该字段值在整张表中
    是非空且惟一的,这样才能用主键的值唯一确定表中的一条数据   
        1:建表时添加主键约束:
          create table employees2(
            eid number(6) primary key,
            name varchar2(30),
            email varchar2(50),
            salary number(7,2),
            hiredate date
          );
        2:添加主键约束:
          alter table employees1 add constraint employees1_name_uk primary key(name);
    4.4、外键约束:定义在两个表的字段或一个表的两个字段用来保证两个字段的关系
    一个表中的一个字段对应另一个表中的主键,这个字段就是外键,
    添加外键约束后,外键中的值只能值null或主键中的值,删除主键所在表的记录时,必须先全部删除
    主键对应的外键所在的表的记录。
      1:先建表,再添加外键约束:
        create table employees3(
            eid number(6),
            name varchar2(30),
            email varchar2(50),
            salary number(7,2),
            deptno number(4)
          );
        alter table employees3 
        add constraint employees3_deptno_fk 
        foreign key(deptno)references dept(deptno);
      3:关联查询一般不考虑外键约束   
    4.5、检查约束:check:强制要求在字段上的值都要满足check中定义的条件。性别约束等
      1:添加检查约束:
          员工薪水必须大于2000
          alter table employees2 add constraint employees2_salary_check
          check(salary>2000);
          用在where中的的条件都可以用在check中。
          正常插入数据:
          insert into employees2(eid,name,salary)values(1236,'doma noble',2500);
          视图修改职员的薪水为1500,更新失败
          update employess2 set salary=1500 where eid=1236;

猜你喜欢

转载自blog.csdn.net/qq_28635317/article/details/106161332
今日推荐