一:数据库的基本环境
1)Oracle数据库
Oracle甲骨文公司 Orcale DBMS
在DB中创建表table来保存数据
管理思路:通过系统表 来管理 用户表
(系统表) (用户表)
user_tables s_emp s_dept stu emp…
user_constraints 管理约束
user_sequences 管理序列
…
也称为:数据字典 DD
DBA关注 程序员关注
Oracle DBMS是一种多用户的管理系统:涉及多线程并发安全问题,采用了锁机制
1.1系统表:user_tables管理所有用户表(表名全部大写存储)
思路: 我们创建一张新的表,DBMS就会在系统表 添加一条记录,记载新表的信息(好比注册表)
desc user_tables; 第一个字段:table_name 表名
select table_name from user_tables;
- - -查询出当前数据库中有哪些用户表?
S_SALGRADE 表名使用大写字母保存
S_REGION
S_EMP
S_DEPT
注意:oracle中值的比较是 区分大小的
1.2虚表dual
特点:单行单列的表
1.3数据库习惯使用下划线分隔:s_emp s_dept dept_id first_name
用下划线的原因:全部大写保存时无法区分每个单词(oracle中是以大写保存的)
java标识符:类名 HelloWorld NullPointException
变量名 firstName
常量名 MAX_VALUE
java有时不用_命名的原因:区分大小写 驼峰式 能区分每个单词
2)如果访问Oracle数据库? sqlplus工具 自带小软件
使用sqlplus工具,发送并执行sql语句
方式:cmd控制台(2种方法,第一种更安全)
1)D:\> sqlplus
输入用户名 system
密码 1234(以实际密码为准,不回显)
2)D:\> sqlplus system/1234
只要看到提示符变为SQL> 说明登录成功
如果sqlplus命令找不到(不是内部外部命令)
需要修改系统环境变量Path 命令的搜索路径
需要将sqlplus命令所在路径名,追回到Path中
C:\oracle\product\10.1.0\db_1\bin
右击我的电脑-》系统属性-》高级
-》环境变量-》系统变量-》双击Path
-》在变量值框中 enter跳到最后(加到最后,防止冲突),加个;号,在粘贴刚才拷贝的bin路径,
-》关闭cmd窗口-》一定要重新启动cmd才可生效
远程登录服务器
cdm-》任何盘符下,telnet 主机名(比如像192.168.0.23)
-》回车-》login:openlab
-》回车-》Passoword:1234
-》……..
-》sun280% sqlplus
-》回车-》Enter user-name:openab
-》回车-》Enter password:
-》SQL>
…….
-》sun280% exit
下载: submit_me.sql 脚本 中文版(目前使用,本地安装了Oracle数据库)
submit_1.sql 英文版 备用(运程连接,同一台服务器中的Orcale数据库)
s_emp_er.emf E_R图 看熟
.emf 矢量图 缩放不会失真 专业文档中
.bmp 位图 缩放会失真
创建4张表:
s_emp 员工表
s_dept 部门表
s_region 区域表
s_salgrade 薪水级别表
二: Oracle 中常见的数据类型
1、数值类型
整数 number(n) n表示整数最大位数
number(8) 最多8位整数 99999999
小数 number(m, n) 表示m位有效数位,n位小数
number(8, 2) 8位有效数位,2位小数
999999.99
有效数位:从左边第1个非0数字开始,后面的都算
100.05 5位有效数位,2位小数
0.0005 1位有效数位,4位小数
number(2, 4) 2位有效数位,4位小数
0.0010 0.0099
2、字符型
定长: char(n) 固定分配n个字符空间
可变长: varchar2(n) 可变长的字符串,最多n个字符
优化的类型 IBM DB2也有这种类型, 向下兼容varchar(n)
varchar(n) 旧版本
3、日期型 date
信息:世纪、年、月、日、时、分、秒
使用sysdate查询系统当前时间:
select sysdate from dual;
三:sqlplus工具的使用
可以执行两类命令:sqlplus命令、sql命令
1、sqlplus环境的基本命令
1)查看表结构
sqlserver:使用存储过程 sp_help 表名
oracle:使用sqlplus命令 describe 表名 (描述)
简写成: desc 表名
desc可以确定表是否存在,也可以查看表结构
2)设置sqlplus的显示格式
show linesize; 显示一行的 字符宽度 默认是80个字符
set linesize 300; 设置一行的字符宽度
3)清空屏幕信息:
clear screen
win cmd清屏:cls
2、SQL命令:数据库业内有标准的
1)DDL 数据库定义语言 定义结构
create drop alter
2)DML 数据库操纵语言 操纵表中的数据
insert delete update select
3)TCL 事务控制语言 Transation
commit rollback savepoint
4) DCL 数据库控制语言 授权和回收 DBA来执行
grant 授权 revoke 回收
针对某个用户进行授权操作
比如针对数据库、表设置操作权限:只读 读/写
四:Oracle基本SQL
1、函数:
函数总结:
单行函数:
1.字符函数 length() lower() upper() substr()
2.数值函数 round() trunc() abs()
3.日期函数 sysdate to_char() to_date() add_months() last_day() trunc()
4.其它函数 nvl()
多行函数:
sum() avg() count() max() min()
单行函数:每条记录只返回一个结果
1)字符处理函数 char varchar2 varchar
oracle 函数 java方法
length() 字符串长度 length()
lower() 大写转小写 toLowerCase()
upper() 小写转大写 toUpperCase()
substr() 求子串 substring()
substr(处理的字符串,开始位置,截取字符数)
开始位置:
正数n:从左往右,第n个位置开始截取
负数-n: 从右往左,倒数第n个位置开始截取
数据库从1开始索引,java等开发语言从0开始索引
查询44号部门的员工名字(原样,全大写,全小写)
select first_name,upper(first_name),lower(first_name)
from s_emp
where dept_id=44;
经常用dual虚表(单行单列的表)测函数
select lower(‘ABC’) from dual;
select length(‘ABC’) from dual;
求每条记录first_name最后两个字符
select first_name,substr(first_name,-2,2) subs from s_emp;
select first_name,substr(first_name,length(first_name)-1,2) subs from s_emp;
2)数值处理函数 number
round() 四舍五入
select round(45.926,2) from dual; 45.93
select round(45.926,0) from dual; 46
select round(45.926,-1) from dual; 50
select round(45.926,-2) from dual; 0
trunc() 截取(不考虑四舍五入,只考虑舍去,第2个参数为正数时,从小数点后几位开始截取,负数,从小数点前几位开始截取)
select trunc(45.926,2) from dual; 45.92
select trunc(45.926,0) from dual; 45
select trunc(45.926,-1) from dual; 40
select trunc(45.926,-2) from dual; 0
abs() 绝对值
3)日期处理函数 date
3.0 日期类型中最常用的函数
sysdate 获取当前系统时间
sysdate+n 当前时间+n天
to_char() date->char
to_date() char->date
add_months(d1,n) d1日期,在加n个月
select add_months(sysdate,2) from dual;
select add_months(sysdate,-2) from dual; 减2个月
last_day(sysdate) sysdate对应用的最后1天,时分秒和sysdate日期的时分秒一致
select last_day(sysdate) from dual;
trunc(sysdate,’yyyy’) 针对sysdate对应的年份截取,年份以后全是初始值(当年第1月)
trunc(sysdate,’mm’) 针对sysdate对应的月份截取,月份以后全是初始值(当月的第1天)
trunc(sysdate) 针对sysdate对应的日期截取,日期以后全是初始值(当天的第0点)
trunc(sysdate,’dd’) 针对sysdate对应的日期截取,日期以后全是初始值(当天的第0点)
trunc(sysdate,’DAY’) 针对sysdate对应的周截取,回到当前周的第一天(周日)
trunc(sysdate,’hh’) 针对sysdate对应的小时截取,小时以后全是初始值(当时的第0分)
trunc(sysdate,’mi’) 针对sysdate对应的分钟截取,分钟以后全是初始值(当分的第0秒)
下个月第1天的0点
select trunc(add_months(sysdate,1),’mm’) from dual; 本月+1
select trunc(last_day(sysdate)+1) from dual; 回到本月最后1天,+1
3.1常用的日期格式:
标准的日期格式:
yyyy mm dd hh24:mi:ss
yyyy-mm-dd hh24:mi:ss
默认的日期格式:
DD-MON-RR
日 月 年
3.2查询系统当前时间
select sysdate from dual;
3.3修改当前日期格式
alter session set nls_date_format=‘yyyy-mm-dd hh24:mi:ss’;
NLS 区域语言支持
national language support
3.4对日期类型数据进行运算
加/减 1 单位:天
今天 明天 昨天
SYSDATE SYSDATE+1 SYSDATE-1
------------------- ------------------- -------------------
2016-02-03 22:05:38 2016-02-04 22:05:38 2016-02-02 22:05:38
求出距离当前时间,10分钟后的时间
select sysdate,sysdate+1/24/6 十分钟后 from dual;
查找员工的名字和入职日期
select first_name,start_date from s_emp;
to_char函数:date数据->char数据
to_char(日期数据,’日期格式’);
select to_char(sysdate,’yyyy-mm-dd’) from dual;
select to_char(sysdate,’hh24:mi:ss’) from dual;
select to_char(sysdate,’yyyy-mm-dd hh24:mi:ss’) from dual;
- - 查找员工的名字和入职日期
select first_name,to_char(start_date,’yyyy-mm-dd’) from s_emp;
select first_name,to_char(start_date,’hh24:mi:ss’) from s_emp;
select first_name,to_char(start_date,’yyyy-mm-dd hh24:mi:ss’) from s_emp;
- - 查询哪些员工是3月份入职的
select first_name, start_date from s_emp where to_char(start_date,’mm’) =’03’;
如果插入日期类型的数据
1.隐式类型转换
满足当前会话日期格式的字符串->date
默认会话日期格式:’DD-MON-RR’, ’01-1月-16’ ’01-Jun-16’
2.显示类型转换:to_date函数
to_date函数:char数据-》date数据
to_date(‘日期字符串’,’格式字符串’)
to_date(‘2016-01-01’,’yyyy-mm-dd’)
to_date(‘01-1月-16’,’DD-MON-RR’)
练习:
drop table stu;
create table stu(
id number(8) primary key,
name varchar2(15) not null,
startdate date
);
alter session set nls_date_format=‘DD-MON-RR’;
select siesta from dual;
insert into stu values(1, ’Tom’, ’01-9月-13’);
commit; 事件提交,大家访问数据库时都能看到
insert into stu values(2, ’James’, ’2013-09-01’);- - 会报错
insert into stu values(2, ’James’, to_date(’2013-09-01’,’yyyy-mm-dd’));
insert into stu values(3, ’Tom’, ’01-9月-13’);
向stu表中插入记录
3 Mary 2013-09-03 11:09:23(通过隐式转换)
4 Tony 2013-09-05 09:01:06(通过显示转换)
alter session set nls_date_format=‘yyyy-mm-dd hh24:mi:ss’;
insert into stu values(3, ‘Mary’, to_date(‘2013-09-03 11:09:23’,’yyyy-mm-dd hh24:mi:ss’));
commit;
insert into stu values(4, ‘Tony’, ‘2013-09-05 09:01:06’);
commit;
4)其它函数:
nvl(a,b) 空值替换函数(a如果是null,aa替换成b,前提是b要和a的数据类型一致)
多行函数:多条记录只返回一个结果,也叫组函数、聚集函数
SUM() 总和
AVG() 平均值
MAX() 最大值
MIN() 最小值
COUNT() 统计记录条数
count(name) 统计所有name记录条数(null时不统计)
count(*) 统计所有记录
查询所有员工的平均提成
select avg(nvl(commission_pct,0))from s_emp;
2、select
select *,字段名,表达式,函数调用...可以起别名
from 表1 别名1,表2 别名2,…
where 分组前的过滤条件 组合and or not
= > >= < <= <> != between a and b in
like
%, _ [] [^]
is null is not null
group by 字段名 分组字段
having 分组后的过滤条件
order by 字段名/别名/序号 排序规则:[asc]/desc...
执行顺序:
from 确定表-》where选择行-》group by分组-》再计算select 组函数-》having过滤 选择行-》最后order by 排序
例子1:找出员工的名字和薪水
select first_name,salary from s_emp;
例子2:找出员工的名字和年薪
select first_name,salary*12 from s_emp;
如何给字段、表达式起别名:
1)as 别名 表头 使用别名代替 默认全部大写
select first_name,salary*12 as 年薪 from s_emp;
2)省略as
select first_name,salary*12 yearsal from s_emp;
3)使用双引号 可以有特殊字符,比如空格 能区分大小写
select first_name,salary*12 as “c年 薪C” from s_emp;
select 1+2;
会报错:- -》结论:oracle中的select语句,必须要有select和from关键字
select之后的表达式,有几条记录,就会计算几次
select 1+2 from s_emp;
dual虚表的应用:
怎样才能只算一次,- - - 单行的表的虚表dual
select 1+2 from dual;
查看当前的系统时间
select siesta from dual;
例子3:查询出员工的全名:first_name last_name
如何进行字符的拼接
SqlServer中:使用+
如果不是字符,需要使用str()函数进行转化
’Hello‘ + str(123) ‘asd’ + ‘fgh’
oracle中:||表示字符串的拼接
select first_name || ‘ ’ || last_name “Full name” from s_emp;
select first_name+last_name from s_emp;
要求:查询当前数据库中有多少用户表?
用户表由系统表user_tables来管理,
用户表的表名称,通过table_name字段表示
select table_name from user_tables;- - - 假如返回145行
要求:写一条sql,返回近似以下结果
select * from S_EMP;
select * from S_DEPT;
select * from S_REGION;
select * from S_SALGRADE;
…
一共也返回145行
select ‘select * from’ || ’ ‘ || table_name || ‘;’ from user_tables;
用途:生成一组批量的sql语句
例子4:找出每个员工的年总收入 年薪+提成
思路:表 s_emp
月薪 salary
年薪 salary * 12
提成 commission_pct 10 12.5 17 百分比
年总收入 年薪 * (1+提成/100)
select first_name,salary * 12 from s_emp;
select first_name,
salary * 12 * (1+nvl(commission_pct,0) / 100) as 年总收入
from s_emp;
空值产生的影响:
1:空值null参与运算,结果也是空
解决:使用空值的转换函数nvl(字段名,空值的替换值)
比如:nvl(commission_pct,0)
如果commission_pct为null,使用0代替
如果commission_pct不为null,使用原值
注意:代替值的数据类型和宽度必须和字段一致
2:任何值包括null本身 和空值null比较,都为假,
空值不能直接比较,任何值和null值比较都为假,只能用:is null /is not null
oracle中tab1表
c1(UK) c2
null null
null null
是可以的,
例子5:查看员工分布在哪些不同的部门?
select dept_id from s_emp; - - -有重复dept_id出现
去除重复值?关键字distinct
只能写在select之后,管的是之后的所有字段,
在oracle9i或10g的某些版本中,不仅仅能去重,还会排序,
select distinct dept_id from s_emp;
oracle历史版本:9i 10g 11g 12c
查询出哪些部门和职位?
select distinct dept_id,title from s_emp;
distinct只能在select之后,如果有多个字段,表示联合唯一,组合在一起是唯一的
红 黑
红 蓝
红 绿
蓝 黑
蓝 红
例子6:排序 根据员工薪水从小到大排序
order by 字段名 排序规则, …
asc 从小到大 升序 默认可不写
desc 从大到小 降序
select first_name,salary
from s_emp
order by salary sac;
练习:查询出员工的信息:
id,first_name,dept_id,salary,按照部门号升序排序
select id,first_name,dept_id,salary
from s_emp
order by dept_id asc;
如果部门相同再按照薪水降序
select id,first_name,dept_id,salary
from s_emp
order by dept_id asc,salary desc;
例子7:查询id为10的员工信息
select id,first_name,dept_id,salary
from s_emp
where id=10;
如果提示未选定行(no rows):说明一行都没有,
查询Mark一个月挣多少钱?
select first_name,salary
from s_emp
where first_name=‘Mark’;
select first_name,salary
from s_emp
where first_name=‘mark’;
报错:未选定行
select * from s_dept;
SELECT * FROM s_dept;
以上两句sql查询结果一样
结论:oracle中值的比较区分大小写
oracle在功能上不区分大小写
但在性能上是区分的
建议sql格式要统一(统一的规范),减轻DBMS的负担,
比如:关键字全部大写,
例子8:查询出薪水在1500〜2000之间的员工信息
select id,first_name,dept_id,salary
from s_emp
where salary between 1500 and 2000;
例子9:列出41、42、43部门员工的薪水情况
select first_name,salary,dept_id
from s_emp
where dept_id in(41,42,43);
或者
select first_name,salary,dept_id
from s_emp
where dept_id =any(41,42,43);
或者
select first_name,salary,dept_id
from s_emp
where dept_id between 41 and 43;
例子10:查询所有的表名为’S_‘开头的表的名称
使用like进行模糊查询:
字段名 like ‘匹配字符串’ 模糊查询
匹配字符串:
% 0个或多个字符(任意个字符)
_ 任意1个字符
如果想表示特殊的字符,比如_本身,需要转义,使用\_ 表示_本身
同时还需要使用escape关键字(只有oracle中要使用escape明确指定),来明确指定转义符
like ’S\_%’ escape ‘\’, 使用了转义符,能够取得字符的本意,推荐使用\
[] 在范围内的1个字符
[^] 不在范围内的1个字符
SELECT table_name FROM user_tables WHERE table_name like ’S_%’;
例子11:找出哪些员工没有提成?
判断某个字段是否为空:
is null
is not null
select first_name, commission_pct from s_emp where commission_pct is null;
select first_name, commission_pct from s_emp where commission_pct is not null;
找出工资比1500高的并且有提成的员工信息?
select id,first_name,salary,commission_pct from s_emp where salary>500 and commission_pct is not null;
常用的比较连接词归纳
肯定形式 否定形式
in not in
等价于=any 等价于<>all
like not like
is null is not null
between a and b not between a and b
查询42部门的员工的年薪,年薪升序排序
- - 推荐使用以下
select id,dept_id, first_name,salary*12 yearsal
from s_emp
where dept_id=42
order by yearsal;
sql执行顺序:先from决定表s_emp->再where选择行->再select 找列, 计算出salary*12 投影->最后order by排序
- - 以下使用序号指定排序的字段,select后,从1开始递增
select id,dept_id, first_name,salary*12 yearsal
from s_emp
where dept_id=42
order by 3 asc;
例子12:平均提成
select avg(nvl(commission_pct,0)) from s_emp;
有多少部门
select count(distinct deept_id) from s_emp;
统计出各个工薪级别有多少员工
s_emp s_salgrade
salary grade losal hisal
select s.grade 薪资级别,count(id) 对应员工数
from s_emp e
right outer join s_salgrade s
on e.salary between s.losal and s.hisal
group by s.grade
order by s.grade;
统计出工薪级别为5的员工人数
select s.grade,count(id)
from s_emp e
right outer join s_salgrade s
on e.salary between s.losal and s.hisal
group by s.grade
having s.grade=5;
例子13,谁的工资最低
select id,first_name,salary from s_emp where salary=(select min(salary) from s_emp);
谁和Mark从事同样的工作
select id,first_name,title
from s_emp
where title=(select title from s_emp where first_name=‘Mark’)
group by id,first_name,title
having first_name<>’Mark’
order by id;
找出哪些人是领导
select first_name
from s_emp
where id in(select distinct manager_id from s_emp where manager_id is not null);
找出哪些人不是领导
select first_name
from s_emp
where id not in(select distinct manager_id from s_emp where manager_id is not null);
哪些部门的平均工资比41号部门的平均工资高?
//select avg(salary) from s_emp where dept_id=41;
select dept_id,avg(salary) from s_emp group by dept_id;
select dept_id,avg(salary)
from s_emp
group by dept_id
having avg(salary)>(select avg(salary) from s_emp where dept_id=41);
3、表连接(重点)
数据库的设计 使用table来存储业务数据
关系型数据库 关系 二维表table 实体 实体间的关系
E-R模型 E-R图
数据库具备良好的设计:
1NF:每个属性不可在分(关系型数据库基本要求)
2NF:提供PK主属性 保证实体完整性
3NF:解除了非主属性之间的依赖关系 拆表(一般采用)
3NF减少数据冗余,解决了数据的不一致问题,从而形成一种良好 设计
3NF特点:将一张表拆分成n张表,数据分布在不同的表中,(合久必分)
由于数据分布在不同的表中,为了一次获取不同表中的数据,就需要进行多表连接查询(分久必合)
3.1如何实现两张表的关系?
1)最主要的关系:主键- - 外键(主外键关系)
员工表 部门表 区域表
s_emp s_dept s_region
id(PK)
dept_id(FK) *- - - 1 id(PK)
region_id(FK) *- - - 1 id(PK)
2)其它
3.2如何进行表连接
语法:from 表1,表2,…
问题:会产生笛卡尔积 会匹配所有记录
为了避免笛卡尔积,需要指定表连接条件
3.3表连接的分类
(1)内连接 inner join on
特点:记录会严格匹配
1)等值连接
2)非等值连接
3)自连接
(2)外连接 outer join on 对内连接的补充
特点:解决的是一个都不能少的问题
1)左外连接
2)右外连接
3)全外连接
- - - - - - - - - -
(1)内连接 inner join on
特点:记录会严格匹配,可能造成记录丢失(空值的影响)
标准sql写法:内连接: from 表1
inner join 表2
on 连接条件(都通用)
1)等值连接:两个表的关系通过等值方式联系在一起(查询结果=FK所在表的记录条数)
查询员工名称、和对应部门名称
select first_name,name
from s_emp e,s_dept d
where e.dept_id=d.id;
select first_name,name
from s_emp e
inner join s_dept d
on e.dept_id=d.id;
查询部门名称、和对应区域名称
select d.name,r.name
from s_dept d,s_region r
where d.region_id=r.id;
查询Mark在哪个地区上班?(3张表,通过2个等值连接条件,联系在一起)
s_emp s_dept s_region
id(PK)
dept_id(FK) = id(PK)
region_id(FK) = id(PK)
first_name name
select e.first_name,r.name
from s_emp e,s_dept d,s_region r
where e.dept_id=d.id and d.region_id=r.id
and e.first_name=‘Mark’ ;
2)非等值连接
> >= < <= <> between and
查询员工的名字、薪水、薪水等级
select e.first_name,e.salary,s.grade
from s_emp e,s_salgrade s
where e.salary between s.losal and s.hisal;
3)自连接:如果1张表中两个字段之间有关系,可以采用自连接
技巧:将1张表通过起别名的方式,模拟成2张表
s_emp表 id(PK) 员工id
manager_id(FK) 领导id 参照于本表的id(s_emp的id)
查询员工id,员工名字,对应的领导id
select id,first_name,manager_id from s_emp;
查询员工的名字和其领导的名字
select e.first_name,ec.first_name
from s_emp e, s_emp ec
where e.manager_id=ec.id;
标准sql写法:内连接 inner join on 连接条件(不是常用)
select e.first_name,ec.first_name
from s_emp e
inner join s_emp ec
on e.manager_id=ec.id;
发现Carman这个员工不见了(他的领导id是null)
内连接实现不了,只能在用外连接来扩展
(2)外连接 outer join on 对内连接的补充
特点:解决的是一个都不能少的问题
//标准sql写法:外连接 : from 表1
outer join 表2
on 连接条件(通用)
1)左外连接 保证左边表的记录1个都不能少,
oracle语法:
要想让左边表 记录1个都不能少, 在对方(右边)加(+)
查询员工的名字和其领导的名字
select e.first_name,ec.first_name
from s_emp e,s_emp ec
where e.manager_id=ec.id(+);
左边 右边
标准sql语法:from 左表 left outer join 右表 on 连接条件
select e.first_name,ec.first_name
from s_emp e
left outer join s_emp ec
on e.manager_id=ec.id;
select e.first_name,ec.first_name
from s_emp e
outer join s_emp ec
on e.manager_id=ec.id;
2)右外连接 保证右边表的记录1个都不能少,
oracle语法:
要想让右边表 记录1个都不能少, 在对方(左边)加(+)
标准sql语法:from 左表 right outer join 右表 on 连接条件
3)全外连接 保证两边表的记录1个都不能少,
oracle语法:
不允许两边同时添加(+)
标准sql语法:from 左表 full outer join 右表 on 连接条件
外连接sql脚本:outerjoin.sql,测试用
t_emp t_dept
drop table t_emp;
drop table t_dept;
create table t_emp(
id number(5) primary key,
name varchar2(15),
dept_id number(5)
);
insert into t_emp values(1, ’Tom’, 11);
insert into t_emp values(2, ’James’, 12);
insert into t_emp values(3, ‘Mary’, null);
insert into t_emp values(4, ’Tony’, 13);
insert into t_emp values(5, ’Ajax’, 11);
insert into t_emp values(6, ’Nill’, 12);
commit;
create table t_dept(
id number(5) primary key,
name varchar2(15) not null
);
insert into t_dept values(11, ‘Java’);
inserc commit;
t_emp表
ID NAME DEPT_ID
-- ------------------------------ ----------
1 Tom 11
2 James 12
3 Mary
4 Tony 13
5 Ajax 11
6 Nill 12
t_dept表
ID NAME
--- -----
11 Java
12 C++
13 DB
14 Web
现象:Mary没有部门,14部门没有员工
练习1:查询所有员工信息和对应的部门信息
内连接(Mary对应的部门丢失)
select e.id,e.name,e.dept_id,d.name
from t_emp e,t_dept d
where e.dept_id=d.id;
左外连接
select e.id,e.name,e.dept_id,d.name
from t_emp e,t_dept d
where e.dept_id=d.id(+); (=左边的表记录1个都不少)
select e.id,e.name,e.dept_id,d.name
from t_emp e
left outer join t_dept d (outer join 的左边的表记录1个都不能少)
on e.dept_id=d.id;
右外连接
select e.id,e.name,e.dept_id,d.name
from t_emp e,t_dept d
where e.dept_id(+)=d.id; (=右边的表记录1个都不少)
select e.id,e.name,e.dept_id,d.name
from t_emp e
right outer join t_dept d (outer join 的右边的表记录1个都不能少)
on e.dept_id=d.id;
全连接:只能用标准sql写法
select e.id,e.name,e.dept_id,d.name
from t_emp e
full outer join t_dept d (outer join 的两边的表记录1个都不能少)
on e.dept_id=d.id;
练习1:查询所有员工信息和对应的部门信息
练习1:查询所有员工信息和对应的部门信息
练习1:查询所有员工信息和对应的部门信息
select e.id,e.name,e.dept_id,d.name
from t_emp e,t_dept d
where d.id=e.dept_id(+);
select e.id,e.name,e.dept_id,d.name
from t_emp e
left outer join t_dept d
on d.id=e.dept_id;
网友评论