一、入门
oracle有四个用户,分别为sys、system、sysman和scott,其中sys是oracle权限最高的用户,类似于Linux
系统的root,scott是示例用户,上课就以这个用户里的三张员工表empno、dept、salgrade作为示例来授课。
启动服务
1. 快捷键ctrl+alt+del打开任务管理器
2. 选择服务
3. 启动OracleServiceXXXX(XXXX是全局名字)和oracleXXXXXXXListener服务(选中一个按o快速找到哦)
这个非常重要(!important),没有启动一切免谈(记笔记.....)
验证数据库是否创建成功
win+R+cmd打开windows命令行控制台(小黑窗)
C:\User\PC>sqlplus /nolog
若出现SQL>则证明数据库创建成功
登陆
语法格式:conn[ect] 用户名/口令 [AS SYSDBA | AS SYSOPER]
注:中括号表示可以省略
登陆sys用户
conn /as sysdba(用户名和口令都为空)
只能以“sysdba”或者“sysoper”系统身份登录 ,不能用 normal。
登陆scott用户
刚开始scott用户默认被锁定,需要登陆sys用户之后执行alter user scott account unlock;
并重新设置口令即可登陆,默认口令是tiger
登陆:conn scott/tiger(password)
虚表
虚表不是真实存在的表,只有一个字段和一行记录,当需要查询且不想从已存在的表中获取数据时便可以使用虚表,更详细的解释你可以百度一下。
二、基础
结构查询语言的分类
考试好像一直考,应该蛮重要的吧。
SQL相关概念和规则
子句:关键字加其他语法元素,例如,select * 是一个子句,from table是一个子句。
列别名:列名 as 列别名 or 列名 列别名,需要注意的是若包含空格、需区分大写以及含特殊字符时,需加引号
关键字通常使用大写,其他语法元素小写,通常以子句为单位进行分行。
NULL
空值是一种无效的、未被赋值的、未知的或不可用的值。任何包含空值的算术表达式运算结果均为空值。(这一点需要注意)
处理空值的函数
nvl(comm,0):若comm不为空,就返回comm,否则返回0
nvl2(expr1,expr2,0):若expr1不为空,就返回expr2,否则返回0
NULLIF(expr1,expr2):数据类型需一致,相等返回null,否则返回第一个表达式
coalesce(expr1,expr2,...)返回第一个非空参数,数据类型需一致
特殊运算符
between and 判断要比较的值是否在某个范围内。 eg: sal [not] between 1500 and 2000
in 判断要比较的值是否和集合列表中的任何一个值相等。 eg: sal [not] in (1500,1600,1800)
like 判断要比较的值是否满足部分匹配。 eg: ename [not] like '%T_' 注:'%'代表任意多字符(>=0),下划线代表一个任意字符
is null 判断要比较的值是否为空值NULL 。 eg: where comm is [not] null
运算符优先级
()、算术运算符(+-*/)、连接运算符(||)、比较运算符(<> 不等于)、特殊比较运算符(like、in、between and、is null)、逻辑运算符(not>and>or)
消除重复行
在select字句中使用关键字DISTINCT可消除重复行。
eg :select distinct deptno from emp;
原义字符串和连接运算符
原义字符串
原义字符串是包含在SELECT列表中的一个字符、一个数字或一个日期。
日期和字符字面值必须用单引号引起来。
每个原义字符串都会在每个数据行输出中出现。
连接操作符
用于连接列与列、列和字符
形式上是以两个竖杠||
用于创建字符表达式的结果列
显示表结构
打开plsqldev(红色油桶),打开Command Window,或者在windows控制台上操作也行。
SQL>desc tablename;
SQL六个常用的执行语句
select*
from table
where condition
group by column
having condition
order by column [asc|desc] asc升序,desc是降序
执行顺序:from > where > group by > having > select > order by
三、函数
单行函数
1. 单行函数返回一个结果
2. 支持嵌套
3. 单行函数可以放在select、where、order by子句中
4. 单行函数对单行数据操作
字符函数(大小写转换函数和字符处理函数)
* lower(列名|表达式):将大写或大小写混合的字符转换成小写
* upper(列名|表达式) :将小写或大小写混合的字符转换成大写
* initcap(列名|表达式) :将每个单词的第一个字母转换成大写,其余的字母都转换成小写(这个不要漏了哦)
* concat(列名1,列名2):连接两个字段或表达式,类似于||
* substr(列名|表达式,n1,n2):返回第一个参数中,从第n1位开始, 长度为n2的子串 。
* length(column | expression):取字符长度
* instr(s1,s2,[,n1],[n2]) :返回s1中,子串s2从n1开始,第n2次出现的位置。n1,n2默认值为1
* lpad(s1,n1,s2):返回s1被s2从左面填充到n1长度后的字符串 。
* rpad(s1,n1,s2) :返回s1被s2从右面填充到n1长度后的字符串。
* trim:去除字符串头部或尾部(头尾)的字符
格式:TRIM([leading | trailing | both] character from source) 注意第一个参数和from
* replace(s1,s2,s3) : 把s1中的s2用s3替换。注意谁替换谁
用的比较多的是concat()、substr()、instr()、length()
数值函数
round(num,n):将num四舍五入到小数点后n位
trunc(num,n):将num截取到小数点后n位
mod(num,n):取num对n取余
日期函数
日期函数默认格式是DD-MM-RR,SYSDATE是系统当前时间
日期可直接加减数值,表示加减对应天数,两个日期相减之后得到相隔的天数,除以7是week,除以24是hour,可以转化成相应单位进行相加减
看图判断年份
RR 日期格式:用来判定按照DD-MM-RR格式给定的日期实际代表的日期是多少
从第一个表可以看出YY格式的年份和当前的年份属于同一个世纪,不用做任何判断。
RR格式的年份判断规律:同小同大均为当前世纪,前小后大为上世纪,前大后小为下个世纪
1.当前日期为2015年,指定日期格式为DD-MON-RR,指定日期为01-1月-01,该日期实际所代表的日期为?
当前日期为小,指定日期为小,所以当前日期是2001年(当前世纪)
2.当前日期为2015年,指定日期格式为DD-MON-RR,指定日期为01-1月-95,该日期实际所代表的日期为?
当前日期为小,指定日期为大,所以实际日期是1995年(上个世纪)
3.当前日期为1998年,指定日期格式为DD-MON-RR,指定日期为01-1月-95,该日期实际所代表的日期为?
当前日期为大,指定日期为大,所以实际日期是1995年(当前世纪)
4.当前日期为1998年,指定日期格式为DD-MON-RR,指定日期为01-1月-01,该日期实际所代表的日期为?
当前日期为大,指定日期为小,所以实际日期是2001年(下个世纪)
months_between(sysdate,hiredate):返回两个日期类型数据之间间隔的自然月数
select ename,job,months_between(sysdate,hiredate) months --当前系统时间与入职时间的间隔月数
from emp
order by months
add_months(sysdate,n):返回指定日期加上n个月后的日期
select empno,ename,job,add_months(hiredate,3) date --入职三个月后的日期
from emp
next_day:返回某一日期的下一个指定日期(有点绕,结合例子来看就懂了)
select next_day(sysdate,'星期一') NextMonday --下个周一是什么日期
from dual; --虚表
last_day:返回指定日期当月的最后一天的日期
select last_day(sysdate) LastDay from dual; --这个月的最后一天是什么日期
round(sysdate[,'format']):将date按format格式进行四舍五入,默认四舍五入为最近的天
format:世纪CC,年YY,月MM,日DD,小时HH24,分MI,秒SS(这个需要稍微记一下)
select ename,job,round(hiredate,'MONTH') --入职日期按月四舍五入
from emp;
trunc(sysdate[,format]):将date按format格式进行截断,和round差不多
--查询81年入职的员工姓名,入职日期按月截断的日期。
select ename,trunc(hiredate,'MONTH')
from emp
where substr(hiredate,-2,2) = '81';
extract([YEAR | MONTH | DAY] from date):返回日期类型数据中的年份、月份和日期
--部门编号是10的部门中所有员工入职月份。
select extract(month from hiredate) from emp;
转换函数
通常需要在字符类型、日期类型、数值类型之间进行显式转换,转换函数及对应关系如下图所示。
to_char(data,'format'):用于日期型
需要注意的是format大小写敏感,可通过format提取日期的年or月or日
下面表格的内容可以稍微记一下
select empno,ename,job,to_char(hiredate,'DD MONTH YYYY') hiredate --17 November 1981
from emp;
to_char(number,'format'):用于数值型
select to_char(sal,'$99,999') salary
from emp;
to_number(char,'format'):要转换的char类型数据必须是由数字组成的字符串。
to_date(char,'format'):要转换的char类型数据必须是可以转换成日期的字符。
select to_date('2019-1-10','YYYY-MM-DD') from dual;
通用函数
case函数
select ename,deptno,
(case deptno
when 10 then '销售部'
when 20 then '技术部'
when 30 then '后勤部'
else '无'
end) deptname,
from emp;
decode函数
select ename,deptno,
decode(deptno,
10, '销售部',
20,'技术部',
30,'后勤部',
'无') deptname,
from emp;
多行函数
分组函数
分组函数是对表中一组记录进行操作,每组只返回一个结果,即首先要对表记录进行分组,然后再进行操作汇总,每组返
回一个结果,分组时可能是整个表分为一组,也可能根据条件分成多组。
min(column):返回每组的最小值,适用于任何类型的数据
max(column):返回每组的最大值,适用于任何类型的数据
avg(column):返回每组的平均值,只能够对数值类型的列或表达式操作
sum(column):返回每组的总和,只能够对数值类型的列或表达式操作
count(column):返回满足条件的每组记录条数
查询职位以SALES开头的所有员工平均工资、最低工资、最高工资、工资和。
select avg(sal),min(sal),max(sal),sum(sal)
from emp
where job like 'SALES%';
组函数中DISTINCT
DISTINCT会消除重复记录后再使用组函数
select count(distinct deptno) from dept;
分组函数中空值处理
除了count(*)之外,其它所有分组函数都会忽略列中的空值,然后再进行计算。
select avg(comm) from emp; --avg(comm) 500
在分组函数中使用NVL 函数可以使分组函数强制包含含有空值的记录
select avg(nvl(comm,0)) from emp; --avg(nvl(comm,0)) ---157
需要注意的几点
select 子句中出现的除分组函数之外的列都应写在group by子句中
分组函数的筛选判断放在having子句中,不能放在where子句中
上面这个图很重要,多看几遍
多表连接
多表连接指的是在多个表之间通过一定的连接条件,使表之间发生关联,进而能从多个表之间获取数据
语法格式
SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column1 = table2.column2;
三点要求
* 在 WHERE子句中书写连接条件。
* 如果在多个表中出现相同的列名,则需要使用表名(或表别名)作为来自该表的列名的前缀。
* N个表相连时,至少需要N-1个连接条件。
最后一个条件需要特别注意一下
笛卡尔积
什么是笛卡尔积
第一个表中的所有行和第二个表中的所有行都发生连接。
什么时候会产生笛卡尔积
连接条件被省略或者无效时,简而言之,就是没有连接条件。
如何避免笛卡尔积
在where子句中包含有效的连接条件
当from后面有多个表时,无论题意如何,连接条件一定要有,且需要N-1个(N为表的数量)
等值连接
两个部门有相同的列,即可用等值连接,而且大概率会是用等值连接
select empno,ename,job,dname,loc
from emp,dept
where emp.deptno = dept.deptno;
非等值连接
两个表不存在相同的列,但两个表的列存在某种不可告人的关系
select ename,job,grade
from emp,salgrade
where sal between losal and hisal;--losal最低工资 hisal最高工资
自身连接
自身连接即自己跟自己连接,以别名区别
查询每个员工的姓名和直接上级姓名?
SELECT worker.ename||' leader is '||manager.ename
FROM emp worker, emp manager
WHERE worker.mgr = manager.empno;
外部连接
在两个表进行等值连接时,有些记录按照连接条件没有连接上,可在缺少匹配值的一边加上(+)
语法
符号(+)所在边的表增加一个“万能”的行,这个行全部由空值组成。它可以和另一边的表中所有不满足连接条件的行进行连接。
由于这个“万能”行的各列全部是空值,因此在连接结果中,来自“万能”行属性值全部为空值。
多表连接的写法
分析要查询的列都来自于哪些表,构成FROM子句;
分析这些表之间的关联关系,如果表之间没有直接关联关系,而是通过另一个中间表关联,则也要在FROM子句中补充中间关联表;
接下来在WHERE子句中补充表之间的关联关系,通常N个表,至少要有N-1个关联关系;
分析是否还有其它限制条件,补充到WHERE子句的表关联关系之后,作为限制条件;
根据用户想要显示的信息,补充SELECT子句。
分析是否有排序要求,如果排序要求中还涉及到其它表,则也要进行第2步补充排序字段所在的表,并且添加表之间的关联关系;
表别名
在多表连接且有相同列时,使用表别名可以区分来自不同表但是名字相同的列。
在定义表别名之后,在对列进行限制时,只能使用表别名,不能使用表名。
SQL:1999语法的连接
语法
这张图包含了SQL99所有连接方式的语法,看完后面的再来看这个表就不会一脸懵逼了
交叉连接
交叉连接是两个表进行交叉相乘,和笛卡尔积的效果一样,使用cross join子句。
SELECT emp.empno,emp.ename,emp.sal,emp.deptno,dept.loc
FROM emp
CROSS JOIN dept;
自然连接
自然连接类似于等值连接,对两个表之间所有相同名字和数据类型的列进行等值连接,使用natural join子句连接。
SELECT empno,ename,sal,deptno,loc
FROM emp
NATURAL JOIN dept;
USING子句
自然连接是使用所有名称和数据类型相匹配的列作为连接条件,而USING子句可以指定用某个或某几个相同名字和数据类型的列作为连接条件。
SELECT e.ename,e.ename,e.sal,deptno,d.loc
FROM emp e JOIN dept d USING (deptno)
WHERE deptno = 20 ;
使用USING子句创建连接时,应注意以下几点:
如果有若干个列名称相同但数据类型不同,自然连接子句可以用USING子句来替换,以指定产生等值连接的列。
如果有多于一个列都匹配的情况,使用USING子句只能指定其中的一列。
USING子句中的用到的列不能使用表名和别名作为前缀。
NATURAL JOIN子句和USING子句是相互排斥的,不能同时使用。
ON子句
自然连接条件基本上是具有相同列名的表之间的等值连接
如果要指定任意连接条件,或指定要连接的列,则可以使用ON子句;
用ON将连接条件和其它检索条件分隔开,其它检索条件写在WHERE子句;
ON子句可以提高代码的可读性。
code
SELECT e.empno, e.ename, e.deptno, d.deptno, d.loc
FROM emp e
JOIN dept d
ON (e.deptno = d.deptno); --我觉得很像where
左外连接
左外连接以FROM子句中的左边表为基表,该表所有行数据按照连接条件无论是否与右边表能匹配上,都会被显示出来,是不是觉得很像外部连接。
SELECT e.ename,e.deptno,d.loc
FROM emp e
LEFT OUTER JOIN dept d
ON (e.deptno = d.deptno);
右外连接
右外连接以FROM子句中的右边表为基表,该表所有行数据按照连接条件无论是否与左边表能匹配上,都会被显示出来。
SELECT e.ename,e.deptno,d.loc
FROM emp e
RIGHT OUTER JOIN dept d
ON (e.deptno = d.deptno);
全外连接
返回两个表等值连接结果,以及两个表中所有等值连接失败的记录
SELECT e.ename,e.deptno,d.loc
FROM emp e
FULL OUTER JOIN dept d
ON (e.deptno = d.deptno);