SQL -- 结构化查询语言 关系型数据库
分类: DDL DML DCL DQL TCL
Oracle 的数据类型:
字符 char() varchar2()
数字 number(p,s)
时间 date timestamp
文件 clob blob 二维表 table
创建表 CREATE
create table 表名 ( 列名 数据类型 [约束], 列名 类型 ... --表的结构) ;
约束: not null , primary key , foreign key , unique , check
表 列 column 字段 filed 属性
行 row 记录 row
create alter drop
--------------------------------------------------------------------------
修改表 ALTER
注: 前提 就是表中还没有任何数据
增加字段(列)
alter table 表名 add 列名 数据类型 ;
alter table 表名 add 列名 数据类型 not null ; --匿名约束
alter table 表名 add 列名 数据类型 default 默认值 ;
修改字段
alter table 表名 modify 列名 新的数据类型 ;
alter table 表名 modify 列名 新的数据类型 default 默认值 ;
修改字段名
alter table 表名 rename column 旧的列名 to 新的列名 ;
增加约束
alter table 表名 add constraint 约束名 约束的关键字 (列名) ;
--命名约束
alter table 表名 modify 列名 数据类型 not null ;
删除字段
alter table 表名 drop column 列名 ;
删除约束
alter table 表名 drop constraint 约束名 ;
修改表的名字
alter table 旧的表名 rename to 新的表名 ;
rename 旧的表名 to 新的表名 ;
SQL DML 语句
增删改查
简单查询:
select 从数据库表中提取信息。 语法:
select * | 列名 | 表达式 from 表名 where 过滤条件 order by 列名 ;
* --代表所有列
列名 --指定列,多列用逗号分隔
表达式 -- 常量 变量 函数等组成表达式
order by 默认升序 ASC ,降序 DESC
select stuname, age, classno from infos where seat<5 orader by age desc ;
增加数据 插入数据 insert 语法:
insert into 表名【(列名1,列名2,列名3...) 】 values (值1,值2,值3 ...) ;
时间函数
to_date() 将时间进行格式化输入
格式化字符 YYYY 年 year
MM 月 month
DD 日 day
hh24 24小时 hh12 12小时
MI 分
SS 秒
to_date('2020-02-26 11:28:35','yyyy-mm-dd hh24:mi:ss')
insert int infos values (...) ;
注意: 对数据的增删改,需要提交 commit 指令;
常量 == 字面量 值
select 执行的结果,获取得是一个 结果集
创建表的另外一个种方式 根据结果集创建表
crate table 表名 ( --结构);
insert into 表名 as select ... from ... ;
--向表中插入一个结果集
修改数据 update 更新 语法:
update 表名 set 列名=值, 列名=值 ... where 条件 ;
删除数据 delete 删除 语法:
delete from 表名 where 条件;
清空表中的所有数据
delete from 表名; --DML rollback回滚 安全
truncate table 表名; --DDL 不能回滚 不安全
drop table 表名 ; --- 删除表
补充: 设置sqlplus 环境
SQL> show linesize ;
SQL> set linesize 120 ; -- 设置每行宽度120个字符
SQL> col 列名 format a20 ; --设置列宽20个字符长度
SQL 增删改查 insert delete update select
用户SCOTT 口令 tiger 过期
雇员表 EMP
部门表 DEPT
薪水等级表 SALGRADE
SQL语句 操作符
算术运算 + 、 - 、 * 、 / --算术表达式
--复杂的运算使用 函数 来实现
问题: 每名员工的年终奖是2000元,请显示基本工资在2000元以上的员工的月工资,年总工资。
select ename 姓名 , sal "薪水", (sal*12+2000) as "年总工资" from emp where sal > 2000;
关系运算 = 等于 > 大于 < 小于 >= 大于等于 <= 小于等于 != 不等于 -- <> ^=
select ename 姓名 , sal "薪水", (sal*12+2000) as "年总工资" from emp where sal > 2000;
--通常作为where条件从句的一部分进行判断
逻辑运算 and 与 、 or 或 、 not 非
高级查询
消除重复的行
distinct
空值的判断:
is null , is not null
in操作
in (集合) , not in (集合)
between ... and ...
sal between 1000 and 2000 --- sal>=1000 and sal<=2000
模糊查询 like
通配符 % :表示零个或者多个任意字符 -- *
通配符 _ : 代表一个任意字符 -- ?
like 'S%' 以S开头的所有字符串
like '_S%' 第二个字符是S的所有字符串
字符串连接 ||
'Hello' || 'World' = 'HelloWorld'
集合运算:
select 执行结果就是一个集合
交集 intersect 返回两个查询共有的记录
并集 union [all] 返回各个查询的所有记录 [包括重复的记录]
补集 minus 返回第一个查询减去第二个查询剩余的记录
----------------------------------------------------------------------------------------
重难点
连接查询 (多表查询)
问题: 请查询出工资大于2000元的员工的,姓名,部门,工作,工资。
笛卡尔集 select * from a cross join b ; -- select * from a, b ;
select ename, dname, job, sal from emp, dept where emp.deptno=dept.deptno and sal>2000;
内连接:
inner join
满足连接条件的左右两表的记录都选取出来,不满足连接条件的记录不选取。
select e.ename, d.dname, e.job, e.sal from emp e, dept d where e.deptno=d.deptno and e.sal>2000;
--多表查询
select e.ename, d.dname, e.job, e.sal from emp e inner join dept d on e.deptno=d.deptno where e.sal>2000;
外连接:
问题: 查询出公司所有部门及员工的姓名、工作、工资。
部门名称、姓名、工作、工资
outer join
满足连接条件的左右两表的记录都选取出来,不满足连接条件的记录也可能选取出来。
左(外)连接
left join
select d.dname, e.ename, e.job, e.sal from emp e left join dept d on e.deptno=d.deptno;
右连接
right join
select d.dname, e.ename, e.job, e.sal from emp e right join dept d on e.deptno=d.deptno;
oralce 私有的写法:
select d.dname, e.ename, e.job, e.sal from emp e ,dept d where e.deptno(+)=d.deptno;
子查询
在select 、update 、 delete 等语句内部可以出现的 select 语句 。内部的语句 嵌套的select 语句 子查询
位置划分:
1、内部嵌套的select语句结果可以作为外部语句条件从句 where 的一部分。
2、内部嵌套的select语句可以作为外部查询等语句的临时表
类型划分:
1、单行子查询: 最多一行记录
2、多行子查询: 可能有多行记录
案例1: 查询出销售部(SALES) 下面的员工的姓名,工作,工资。
select ename, job, sal from emp where deptno = (select deptno from dept where dname='SALES' );
案例2:查询出emp表中比任意一个销售员("SALESMAN") 工资低的员工姓名、工作、工资。
select ename, job, sal from emp where sal < any [all] (select sal from emp where job='SALESMAN');
-- 多行子查询 需要用到 any , all , in , not in 等关键字 ,any 任意 , all 所有
伪列: oracle 表的附加列,不能(增删改)存储数据,只能用于查询(查)。
rowid 返回的是行的物理地址。 插入记录时生成, 可以快速定位行。
rownumber 为结果集的每一行标识一个行号。 查询时生成,可以限制查询返回行数。
案例3: 查询出员工表中前5名的员工的姓名,工作,工资。
select rownum, ename, job, sal from emp where rownum<=5;
案例4: 查询出工资最高的前5名的员工的姓名,工作,工资。
select * from (select ename,job,sal from emp order by sal desc ) where rownum<=5 ;
分页查询
select * from (select rownum r, ename, job, sal from emp ) t where t.r>=6 and t.r<=10 ;
子查询练习题:
1.创建一查询,显示与Blake在同一部门工作的雇员的姓名和受雇日期,但是Blake不包含在内。
select ename, hiredate from emp where deptno = (select deptno from emp where ename='Blake') and ename!='Blake' ;
2.显示位置在Dallas的部门内的雇员姓名、编号以及工作。
select ename, empno, job from emp where deptno in (select deptno from dept where loc='Dallas') ;
3.显示被King直接管理的雇员的姓名以及工资。
select ename, sal from emp where mgr = (select empno from emp where ename='King') ;
4.创建一查询,显示能获得与Scott一样工资和奖金的其他雇员的姓名、受雇日期以及工资。
select ename, hiredate, sal from emp where sal = (select sal from emp where ename='Scott')
and comm = (select comm from emp where ename='Scott') ;
select 高级查询 distinct , is null , in , between ... and ... , like % _ , ||
集合查询: 交集intersect 并集union 补集 minus
连接查询 -- 多表查询
内连接 inner join ... on
外连接 outer join
左外连接 left join
右外连接 right join
子查询:
按位置:
1、 子查询作为外部条件从句的一部分 where ...
2、 子查询作为外部查询的临时表 from ...
按返回:
1.单行子查询
2.多行子查询 any , all , in , not in
-----------------------------------------------------------------------------------
Oracle 函数
通俗地说就是封装了实现特定功能的代码块。 目的是为了代码重用
定义了一个名字叫fun的函数
public static int fun(int x, int y){
System.out.println("实现累加从"+x+"到"+y);
int relust = 0;
for (int i =x ; i<=y ; i ++ ){
relust += i ;
}
System.out.println("累加的计算完成,结果是:"+ relust);
return relust ;
}
oracle 内置的函数:
单行函数: mod(x,y) -- 了解
字符函数 : ASCII(x) , length(x)
数字函数 : power(x,y)
时间函数 : ADD_MONTHS(d,n) last_day(d) round(d,fmt) , EXTRACT(fmt from d) ,between_months(d,d)
转换函数 : TO_CHAR(d|n[,fmt]) , TO_DATE(x [,fmt]) , TO_NUMBER(x[,fmt])
其他的单行函数:
NVL(x,value) NVL2(x,value1,value2)
--注意 空值是不能进行运算的
聚合函数 -- 熟练掌握
avg() 求平均值
sum() 求和
min() 求最小值
max() 求最大值
count() 数据统计
分组 group by
select ... from ... where ... group by 分组的依据 ;
案例: 计算公司里每个岗位(JOB) 的人数。
select job, count(empno) from emp group by job ;
案例:提取显示一下公司里平均工资大于2000的部门(部门的编号)。
案例: 提取显示一下公司里(不包括总经理'PRESIDENT')平均工资大于2000的部门(部门的编号)。
select deptno, avg(sal) from emp where job!='PRESIDENT' group by deptno having avg(sal)>2000;
-- 分组前过滤 where 分组后过滤用 having
案例: 提取显示一下公司里(不包括总经理'PRESIDENT')平均工资大于2000的部门的名称(部门的名称)。
select dname from dept where deptno in (select deptno, avg(sal) from emp where job!='PRESIDENT' group by deptno having avg(sal)>2000) ;
select ename, dname from emp cross join dept where sal>2000 order by sal desc,ename desc; ----笛卡尔集?
select ename, dname,sal from emp , dept where emp.deptno(+)=dept.deptno and sal>2000 order by sal desc,ename desc; ----右连接
select ename, dname,sal from emp , dept where emp.deptno=dept.deptno(+) and sal>2000 order by sal desc,ename desc; -----左连接
检索所有的员工的姓名,以及他经理的姓名?
select e.ename, m.ename from emp e , emp m where e.mgr=m.empno; --自连接
select e.ename, m.ename from emp e inner join emp m on e.mgr=m.empno; -- 标准的自连接写法
查询薪水大于岗位平均薪水的员工?
select * from emp e where sal > (select avg(sal) from emp where job=e.job ) ; -- 相关子查询
查询工资子大于3000的员工所在的部门名称?
exists (select ... from ...) 存在子查询
--子查询返回的是 布尔值 ture , false
select dname from dept d where exists (select * from emp where sal>3000 and deptno=d.deptno) ;
其他函数
nullif(expr1, expr2) -- expr1等于expr2 返回空,否则返回exp1
select ename, job, nullif(length(ename),length(job)) from emp;
coalesce(expr1,expr2,expr3...exprn) -- 从左开始遇到第一个表达式非空就返回
select ename,job, coalesce(comm, sal, 10 ) from emp;
条件表达式函数:
case [expr] when ... then ...
when ... then ...
else ...
end
------------------------------------------------------
select ename,sal,case deptno when 10 then 'dept10'
when 20 then 'dept20'
when 30 then 'dept30'
else 'other' end department
from emp ;
select ename,sal,case when deptno =10 then 'dept10'
when deptno =20 then 'dept20'
when deptno =30 then 'dept30'
else 'other' end department
from emp;
-----------------------------------------------------------------------