Oracle_day01
1. Oracle简介
Oracle公司的一款关系型数据库管理系统,分布式数据库,实现了分布式处理功能。
2. Oracle数据库的体系结构
数据库
Oracle数据库是数据的物理存储,与其它数据库不同,一个操作系统只有一个Oracle数据库,可以看做Oracle就只有一个大数据库。
实例
一个Oracle实例(Oracle instance)有一系列的后台进程(background processes)和内存结构(memory structures)组成。一个数据库可以有n个实例。
数据文件(dbf)
数据文件是数据库的物理存储单位。数据库的数据是存储在表空间中的 ,真正是在某一个或多个数据库文件中。一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间。一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属的表空间才行。
表空间
表空间是Oracle对物理数据库上相关数据文件的逻辑映射。表空间由多个数据文件组成,数据文件只能属于一个表空间。表空间为逻辑单位,数据文件为物理单位。每个数据库至少有一个表空间(称为system表空间)。
用户
用户是在实例下建立的,不同实例中可以建相同名字的用户。表不是由表空间去查的,而是由用户去查的,因为不同用户可以在同一个表空间建同一个名字的表。Oracle是由用户和表空间对数据进行管理和存放的。
数据库 ---> 数据库实例 ---> 表空间(逻辑单位)(用户) ---> 数据文件(物理单位)
地球 ---> 一个国家 ---> 省份(逻辑单位)(公民) ---> 山川河流(物理单位)
3. sql简介
sql: structured query language,简称sql,结构化查询语言。用于存取数据以及查询,更新和管理数据库系统,也是数据库脚本文件的扩展名。
sql分类:
DDL
数据库定义语言。create, alter, drop, truncate。
DML
数据库操作语言。insert, update, delete。
DCL
数据库控制语言。通过grant, revoke获取许可,确定单个用户和用户组对数据库对象的访问。
DQL
数据查询语言。select...from...where。
4. sql语法
4.1 基本查询
--基本查询
select * from tab;--查询所有表
select * from emp;--查询emp表
select 1 from emp;--14*1个1
select empno,ename,job from emp;--查询表中的某些列
--别名查询,as关键字可省略
--别名中不萌有特殊字符或关键字,如果有就加双引号。
select empno as 部门编号,ename as 部门名称,job as 工作 from emp;
select empno 部门编号,ename 部门名称,job 工作 from emp;
select empno "部门 编号",ename 部门名称,job 工作 from emp;
4.2 distinct去重
/*
distinct去重
单列去重:只显示非重复数据
多列去重:整行数据完全相同时才去重
*/
select distinct job from emp;--单列去重
select distinct job,deptno from emp;--多列去重
4.3 四则运算
select 1+1;
/*
在mysql中结果为2;
在oracle中报错:from keyword not found where expected,
需要补上dual表,oracle中的虚表,伪表,主要是用来补齐语法结构
*/
select 1+1 from dual;--在oracle和mysql中都为2
4.3 nvl函数
--查询员工年薪
select sal*12 from emp;
--查询员工年薪+奖金(comm中存在null值)
select sal*12+comm from emp;--错误
/*
comm为空(null)的行查询结果显示该行也为空,因为null值表示不确定,不可预知的内容,
不能做四则运算;需要使用nvl函数,将comm为null值的在进行运算时设置为0
*/
select sal*12+nvl(comm,0) from emp;--正确
4.4 字符串拼接
/*
拼接符拼接:oracle特有字符串拼接符:||
函数拼接:concat(str1,str2),mysql和oracle中都有
*/
--查询员工姓名
--拼接符拼接
select '姓名:'||ename from emp;
--函数拼接
select concat('姓名:',ename) from emp;
/*
oracle中单引号和双引号区别:
双引号:关键字,对象名,字段名,别名
单引号:指定字符串文本时,转义符
*/
4.5 条件查询
/*
关系运算符:> >= = < <= != <>(不等号)
逻辑运算符:and or not
其它运算符:
like 模糊查询
in(set) 在某个集合中
between..and..在某个区间内
is null 判断为空
is not null 判断不为空
*/
--模糊查询
--查询员工姓名第三个字符是O的员工信息
select * from emp where ename like '__O%';--前两位用_表示
--查询员工姓名中包含%的员工信息
select * from emp where ename like '%%%'; --错误,查询的是所有
select * from emp where ename like '%\%%' escape '\';
select * from emp where ename like '%&%%' escape '&';
--escape '\'即声明\为转义符,也可使用&等其它字符
--查询员工工资在1500和3000之间的员工名称
select ename from emp where sal>=1500 and sal<=3000;
select ename from emp where sal between 1500 and 3000;
--查询名字在某个范围的员工信息 ('JONES','SCOTT','FORD')
select * from emp where ename in ('JONES','SCOTT','FORD');
4.6 排序
/*
order by
升序:asc ascend(默认)
降序:desc descend
如果某列有null值,可指定null值排在前面和后面:nulls first,nulls last,
默认null值在前
同时排列多列,用逗号隔开
*/
--查询员工信息,按奖金降序
select * from emp order by comm desc nulls last;
--查询部门编号和工资,按部门升序,工资降序
select empno,sal from emp order by empno asc,sal desc;--结果还是按empno升序排列,这就导致sal近乎无序
4.7 函数
/*
函数必须要有返回值
单行函数:对某一行中的某个值进行处理
数值函数 字符函数 日期函数 转换函数 通用函数
多行函数:对某一列的所有行进行处理
max,min,count,sum,avg
*/
--多行函数
--统计工资总和
select sum(sal) from emp;
--查询最低工资
select min(sal) from emp;
--统计数据条数,直接写一个常量比写*更高效,也可写一个具体的列
select count(*) from emp;
select count(1) from emp;
select count(ename) from emp;
--统计平均奖金
select avg(comm) from emp;--550,显然是错误的,因为有null值
select sum(comm)/count(1) from emp;--2200/14=157.142857142857
select avg(nvl(comm,0)) from emp;--157.142857142857
--几种取整方式
--ceil(n)取大于等于n的最小整数
select ceil(sum(comm)/count(1)) from emp;--158
select ceil(-12.5) from dual;--(-12)
--floor(n)取小于等于n的最大整数
select floor(sum(comm)/count(1)) from emp;--157
select floor(-12.5) from dual;--(-13)
--round(n,t)四舍五入,t表示保留小数点后几位有效数字
--如果t为负数即处理整数部分
select round(147.128,2) from dual;--147.15
select round(147.128,0) from dual;--147
select round(147.128,-1) from dual;--150
select round(147.128,-2) from dual;--100
select round(147.128,-3) from dual;--0
--trunc(n,t)截断,t表示保留小数点后几位数字,
--如果t为负数即处理整数部分,处理完设为0
select trunc(147.128,2) from dual;--147.12
select trunc(147.128,0) from dual;--147
select trunc(147.128,-1) from dual;--140
select trunc(147.128,-2) from dual;--100
select trunc(147.128,-3) from dual;--0
--mod(n,t)求余,n/t后取余数
select mod(9,3) from dual;--0
select mod(9,2) from dual;--1
--substr(str,起始索引,长度)截取字符
--不论起始索引为0还是1,都是从第一个字符截取
select substr('abcdef',0,3) from dual;--abc
select substr('abcdef',1,3) from dual;--abc
select substr('abcdef',2,3) from dual;--bcd
--length(str)获取字符串长度
select length('abcdef') from dual;--6
--trim(str)去掉字符串左右两边空格
select trim(' abc def ') from dual;--abc def
--replace(str,s1,s2)替换字符,将str中的s1替换为s2
select replace('hello','l','o') from dual;--heooo
--日期函数
--sysdate查询今天日期
--查询的是oracle所在机器日期,我的oracle安装在虚拟机上,所以这是虚拟机上的日期
select sysdate from dual;
--add_months查询三个月后的今天的日期
select add_months(sysdate,3) from dual;
--查询三天后的日期
select sysdate+3 from dual;
--查询员工入职天数
select sysdate-hiredate from emp;
--查询员工入职周数
select (sysdate-hiredate)/7 from emp;
--查询员工入职月数,由于每月天数不同,所以使用months_between(date1,date2)
select months_between(sysdate,hiredate) from emp;
--查询员工入职年数
select months_between(sysdate,hiredate)/12 from emp;
--转换函数
--to_number(str)字符转数值,鸡肋,默认已经转换
select 100+'10' from dual;--110
select 100+to_number('10') from dual;--110
--to_char(n)数值转字符
select to_char(800.11) from dual;--800.11
select to_char(800.00) from dual;--800
--CL格式
--'9,999.99'用于指定格式
select to_char(1298.219,'9,999.99') from dual;--1,298.21
select to_char(1298.219, '9,999.9') from dual;--1298.2
--'0'表示在对应位置返回对应的字符,如果没有则以'0'填充
select to_char(1298.219, '9999.900') from dual;--1298.219
select to_char(1298.219, '00999.9') from dual;--01298.2
--'X'表示转换为16进制
select to_char(852,'xxxx') from dual;--354
--852/16=53余4,即个位为4;53/16=3余下5,即十位为5;3/16=0余3,即百位为3
select to_char(1298.219,'$9,999.99') from dual;--$1,298.21
select to_char(1298.219,'L9,999.99') from dual;--$1,298.21,L代表本地货币符号
--to_char()日期转字符
select to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual;--2020-03-15 09:07:51
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;--24小时制,2020-03-15 09:07:51
--只要年份
select to_char(sysdate,'yyyy') from dual;--2020
--只要天份
select to_char(sysdate,'d') from dual;--1 代表一周中的第几天
--今天为周日,结果为1,因为在美国周日为一周第一天
select to_char(sysdate,'dd') from dual;--15 代表一月中的第几天
select to_char(sysdate,'ddd') from dual;--75 代表一年中的第几天
select to_char(sysdate,'day') from dual;--sunday
select to_char(sysdate,'dy') from dual;--sun sunday的简写
--字符转日期
select to_date('2020-03-15','yyyy-mm-dd') from dual;--2020/03/15转为本地日期格式
--查询1981年到1985年入职的员工信息
select * from emp where hiredate between to_date('1981','yyyy') and to_date('1985','yyyy');
--通用函数
/*
nvl(param1,param2) 如果param1=null,就返回param2
如果param!=null,就返回param1
nvl2(param1,param2,param3) 如果param1=null,就返回param3;
如果param!=null,就返回param2
nullif(param1,param2) 如果param1=param2,就返回null,否则返回param1
*/
select nvl(1,2) from dual;--1
select nvl(null,2) from dual;--2
select nvl2(1,2,3) from dual;--2
select nvl2(null,2,3) from dual;--3
--coalesce(...)返回第一个不为null的值
select coalesce(null,null,2,3) from dual;--2
4.8 条件表达式
--case...when表达式(oracle和mysql都可使用)
--给表中姓名按条件取中文名
select case ename
when 'SMITH' then '啦啦啦'
when 'ALLEN' then '哈哈哈'
else '不知道'
end "中文名"
from emp;--end指给ename这列取一个别名"中文名"
--decode(oracle特有写法)
select decode(ename,'SMITH','啦啦啦','ALLEN','哈哈哈','不知道') "中文名" from emp;
4.9 分组 group by
--查询各部门人数,按部门编号排序
select deptno,count(1) from emp group by deptno;
select deptno,count(1) from emp;--错误,不是单组分组函数
select ename,count(1) from emp group by deptno;--错误,不是分组表达式
--前面不能写后面没有的数据,除了计数
--having过滤分组数据
--查询部门平均工资大于2000的部门
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000
--错误的写法
select deptno,avg(sal) avgsal from emp group by deptno having avgsal>2000
/*
sql的编写顺序
select ..from..where..group by..having..order by
sql的执行顺序
from..where..group by..having..select..order by
*/
--where和having的最大区别在于where后面不能有组函数,可以接单行函数