Oracle 11g 数据库基础教程
课堂笔记
系统服务
操作系统通过服务来管理安装好的Oracle 11g数据库产品的运行
在运行Oracle数据库前 要检查数据库服务有没有启动好
开始»控制面板»管理工具»服务
OracleServiceORCL:数据库服务(数据库实例),是Oracle核心服务,是数据库启动的基础,只有该服务启动,Oracle数据库才能正常启动。(必须启动)
OracleOraDb11g_home1TNSListener:监听服务,该服务只有在远程访问数据库才需要。(必须启动)
OracleDBConsoleorcl: Oracle控制台服务,即企业管理器服务。只有该服务启动了,才可以使用Web方式的企业管理器管理数据库。(非必须启动)
文件体系结构
C:\app\Administrator
oradata:以数据库为单位,存放数据库的物理文件,包括数据文件、控制文件和重做日志文件。
product:存放Oracle 11g数据库管理系统相关的软件,包括可执行文件、网络配置文件、脚本文件等。
安装好数据库后,自动有3个用户:
系统用户:sys、system
普通用户:scott
用户名/密码 Scott/123456
把字体放大:
鼠标光标对准SQL Plus»右键单击»属性»弹出“SQL Plus”属性列表
启动数据库控制OEM
开始»所有程序»Oracle-OraDb11_g_home1»Database Control-orcl
口令:123456
OEM控制台的URL格式为:https://主机名或主机IP地址:要连接的数据库的服务端口号/em
https://localhost:1158/em
2.2.2 启动SQL Plus
(1)菜单命令方式启动SQL Plus
开始»所有程序» Oracle-OraDb11_g_home1»应用程序开发»SQL Plus
(2)命令行方式启动SQL Plus
开始»所有程序»附件»命令提示符
13.1.4 用户的锁定与解锁
如果遇到scott用户被锁定,解锁步骤如下:
①connsystem/123456;
②alteruser scott account unlock;
③alteruser scott identified by 123456;
2.2.3SQL Plus常用命令
①conn[ect]命令先断开当前连接,然后建立新的连接(切换用户)
②如果要以sys(特权用户)的身份连接,必须要带as sysdba或as sysoper
SQL>conn sys/123456 as sysdba
③disconn[ect]命令作用是断开与数据的连接,但不退出SQL Plus环境
SQL>disconn
④exit命令作用是断开与数据库的连接,并且完全退出SQL Plus环境
SQL>exit
⑤建表、解锁»带分号‘;’
(1)linesize:设置行显示的长度,默认值为80。如果输出行的长度超过80个字符,则换行显示
SOL>set linesize 130;
(2)serveroutput:设置是否显示执行dbms_output.put_line命令输出的结果。
若该变量值为on,则显示输出结果,否则不显示输出结果。默认值为off。
SOL>show serveroutput
SOL>set serveroutput on
(3)time:设置是否在SQL Plus命令提示符之前显示时间(on),默认值为off,不显示。
SOL>show time
SOL>set time on
(4)timig:设置是否显示SQL语句的执行时间,默认值为off,不显示SQL语句的执行时间。
SOL>show timing
SOL>set timing on
(5)spool:将SQL Plus屏幕内容存放到文本文件夹中(记录屏幕数据)
SQL>spoold:\t1.txt 路径/文件名
SQL>spooloff (必须结束)
(6)desc[ribe]:显示任何数据库对象的结构信息(描述表结构)
SQL>descemp;
2.3 SQL Daveloper
创建数据库连接
测试»连接
课堂内容:
select * from emp;
selectempno,ename,to_char(hiredate,'yyyy-mm-dd hh:mi:ss')from emp;
6.2 表的创建与管理
--创建表
--创建部门表
create table department
(
deptid number(2) primary key,
dname varchar2(20) unique,
loc varchar2(20)
);
--创建雇员表(Employee),包括员工号、员工名、工作职位、主管领导、雇佣日期、基本工资、补贴、部门号等员工信息。
create table employee
(
empid number(4) primary key,
ename char(10) not null,
job char(10),
mgr number(4) ,
hiredate date,
baseSal number(7,2),
comm number(7,2),
deptid number(2) constraint fk_deptidreferences department(deptid)
);
--修改表
--添加约束
alter table employee add constraint ck_sal check(baseSal between 1000 and 3000);
--修改表结构 (添加列,修改列,删除列)
--修改部门表,添加一列tele ,字符类型 长度13
alter table department add tele char(13);
--修改部门表,修改tele ,长度15
alter table department modify tele char(15);
--删除列 tele
alter table department drop column tele;
--查看用户下的表
select * from cat;
--用数据字典:user_tables
desc user_tables
select table_name,tablespace_name,status fromuser_tables where table_name='DEPARTMENT';
在Oracle中可以通过查询数据字典视图获取用户信息
6.3 索引的创建与管理
--创建索引
--在emp表 ename列上创建索引 (单个列上创建索引)
create index idx_ename on emp(ename);
--多个上列创建索引
create index emp_idx_j on emp(ename,job);
--创建基于函数的索引
create index emp_fun_idx onemp(UPPER(ename));
--删除索引
drop index emp_fun_idx;
6.4 视图的创建与管理
创建视图前要在SQL Plus先授权
授权:SQL> grantcreate view to scott;
--创建视图
--简单视图:查询的数据来自一个表
--复杂视图:查询的数据包括多个表
--1,创建只读视图,建立一个10部门员工的只读视图dep_10。
create or replace view dep_10
as
select * from emp where deptno=10
with read only;
select * from dep_10
--2,在emp建立视图emp_v1,包括empno,ename,job,sal
create or replace view emp_v1
as
select empno,ename,job,sal from emp;
--视图操作(简单视图可以进行增删改查)
insert into emp_v1values(8000,'chenxin','SALESMAN',2300);
select * fromemp order by empno desc
--复杂视图(复杂视图不可以进行增删改查)
--创建一个包含各部门的部门号、部门人数和部门平均工资的视图
create or replace view sal_avg as
select deptno,avg(sal) avgsal ,count(*)total
from emp
group by deptno;
课堂作业:
一、创建表
1,建立学生表student
学号: sno 数字类型 长度2 主键
姓名: sname 字符类型 长度8 非空
年龄 age 数字类型 长度2
出生日期 birthdate 日期类型
create table student
(
sno number(2) primary key,
sname varchar2(8) not null,
age number(2),
birthdate date
);
2,班级表class
班级号 cno 数字类型 长度2 主键
班级名 cname 字符类型 长度20
班级人数 rs 数字类型 长度2
学号 sno 数字类型 长度2 外键
create table class
(
cno number(2) primary key,
cname char(20) ,
rs number(2),
snonumber(2) references student(sno)
);
二、修改表
1) 修改表student,使 age 在13到15之间
alter table student addconstraint ck_age check(age between 13 and 15);
2) 修改表student,添加电话tele 字符 长度17
alter table student add telechar(17);
3) 删除tele字段
alter table student dropcolumn tele;
6.5 序列
--创建序列
--查看部门表dept数据
select* from dept;
create sequence dept_seq
increment by 10
start with 50;
--使用序列 nextval 和 currval 两个属性
insert into dept values(dept_seq.nextval,'管理部','aaaaaaa');
--查看序列当前值
select dept_seq.currval fromdual;
insert into dept values(dept_seq.nextval,'纪检部','ccccccc');
--删除序列
drop sequence dept_seq;
7.1数据插入
数据操作 insert , update ,delete , select
日期类型数据插入方法
select * from emp;
1)原始数据插入方法
insert into emp(empno,ename,hiredate,sal)
values(8000,'chenxin',to_date('2018-06-02','yyyy-mm-dd'),1800);
2)带有时分秒的数据插入
insert intoemp(empno,ename,hiredate,sal)
values(8001,'liang',to_date('2010-06-0310:11:12','yyyy-mm-dd hh:mi:ss'),1800);
--查看
selectempno,ename,to_char(hiredate,'yyyy-mm-dd hh:mi:ss'),sal from emp;
3)insertinto 表1 select * from 表2
--创建部门表 department
create table department
(deptid number(2) primary key,
deptName char(10),
deptloc varchar2(20)
);
--往表里插入数据
insert into department select * from deptwhere deptno in (10,30);
select * fromdepartment;
4) createtable 表1 as select * from 表2
create table ndept as select * fromdept;
select * from ndept;
光标放在选中的行的最前边 键盘按Shift+ End 瞬间整行选中
--修改数据
update dept set loc='bbbbb'where deptno=50;
select * from dept;
update dept setdname='yirong',loc='bbbbb' where deptno=60;
commit; 提交
--删除数据
delete from dept wheredeptno=50;
--整个表的数据都删除,不能回滚
truncate table ndept;
rollback; 回退
SQL Plus中事务是隐形开始的
当发出commit或rollback命令时事务才算结束
Oracle SQL Developer 工具»首选项»代码编译器
可以调整字体还有显示行数
课堂作业:
第一步:在SQL Plus中授权
SQL*Plus: Release 11.2.0.1.0Production on 星期六 6月 2 10:33:45 2018
Copyright (c) 1982, 2010,Oracle. All rights reserved.
请输入用户名: system/123456
ERROR:
ORA-28002: the password willexpire within 7 days
连接到:
Oracle Database 11gEnterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP,Data Mining and Real Application Testing options
SQL> create user stu_user identified by stu123;
用户已创建。
SQL> grant connect,resource to stu_user;
授权成功。
SQL> grant create view,create any index,create sequence tostu_user;
授权成功。
第二步:在SQL Developer中新建连接
--(2)创建表并插入数据
--创建book表
create table book
(
no char(10) primary key,
title varchar2(80) not null,
author varchar2(20) not null,
publish varchar2(20) not null,
pub_date date not null,
price number not null
);
--创建reader表
create table reader
(
rno char(10) primary key,
rname char(8) not null
);
--创建borrow表 联合主键
createtable borrow
(
no char(10) not null,
rno char(10) not null,
borrow_date date,
constraint pk_no_rno primary key(no,rno)
);
--往book表中插入数据
select * from book;
insert into book(no,title,author,publish,pub_date,price)
values (100001,'Oracle 9i数据库系统管理','李代平','冶金工业出版社',to_date('2003-01-01','yyyy-mm-dd'),38);
insert into book(no,title,author,publish,pub_date,price)
values (100002,'Oracle 9i中文版本入门与提高','赵松涛','人民邮电出版社',to_date('2002-07-01','yyyy-mm-dd'),35);
insert into book(no,title,author,publish,pub_date,price)
values (100003,'Oracle 9i开发指南:PL/SQL程序设计','Joan Casteel','电子工业出版社',to_date('2004-04-03','yyyy-mm-dd'),49);
insert into book(no,title,author,publish,pub_date,price)
values (100004,'数据库原理辅助与提高','盛定宇','电子工业出版社',to_date('2004-03-01','yyyy-mm-dd'),34);
insert into book(no,title,author,publish,pub_date,price)
values (100005,'Oracle 9i中文版本实用培训教程','赵伯山','电子工业出版社',to_date('2002-01-01','yyyy-mm-dd'),21);
insert into book(no,title,author,publish,pub_date,price)
values (100006,'Oracle 8实用教程','翁正科等','电子工业出版社',to_date('2003-07-08','yyyy-mm-dd'),38);
--往reader表中插入数据
select * from reader;
insert intoreader(rno,rname) values (200001,'张兰');
insert intoreader(rno,rname) values (200002,'李凤');
insert intoreader(rno,rname) values (200003,'孟欣');
insert into reader(rno,rname)values (200004,'谢非');
insert intoreader(rno,rname) values (200005,'刘英');
--往borrow表中插入数据
selectno,rno,to_char(borrow_date,'yyyy-mm-dd hh:mi:ss') from borrow;
insert into borrow(no,rno,borrow_date)
values (100001,'200001',to_date('2004-08-1010:06:14','yyyy-mm-dd hh:mi:ss'));
insert into borrow(no,rno,borrow_date)
values (100002,'200002',to_date('2004-08-1010:06:27','yyyy-mm-dd hh:mi:ss'));
insert into borrow(no,rno,borrow_date)
values (100003,'200003',to_date('2004-08-1010:06:36','yyyy-mm-dd hh:mi:ss'));
insert into borrow(no,rno,borrow_date)
values (100004,'200004',to_date('2004-08-1010:06:48','yyyy-mm-dd hh:mi:ss'));
insert into borrow(no,rno,borrow_date)
values (100005,'200005',to_date('2004-08-1010:06:58','yyyy-mm-dd hh:mi:ss'));
--(3)插入一条图书信息
insert into book(no,title,author,publish,pub_date,price)
values (100007,'java网络编程','李程等','电子工业出版社',to_date('2000-08-01','yyyy-mm-dd'),35);
select * from book;
--(4)将图书编号为100007的图书价格改为29
update book setprice='29'where no=100007;
select * from book;
--(5)删除图书编号为100007的图书信息
delete from book whereno=100007;
select * from book;
--(6)给表reader增加一列,列名为地址addr , 文本变长50
alter table reader add addr char(50);
select * from reader;
--(7)在book表的price上添加一个检查约束,保证该列的取值在0-100之间
alter table book addconstraint ck_price check(price between 0 and 100);
--(8)在book表的title列上创建唯一约束idx_title
alter table book addconstraint idx_title unique(title);
--(9)创建视图book_v1,包含: 书号no,书名title和出版日期pub_date
create or replace view book_v1
as
select no,title,pub_date from book;
select * from book_v1;
--(10)创建序列reader_seq,起始值为200006,增量为1 ,并向reader表插入一条数据
create sequence reader_seq
increment by 1
start with 200006;
select * from reader;
insert into readervalues('200006','陈欣','广东韶关');
课堂内容3 函数和运算符:
--集合运算 union ,intersect,minus
--(1)并集 union
select * from emp;
selectempno,ename,sal,deptno from emp where deptno=10
union
selectempno,ename,sal,deptno from emp where deptno=20;
--(2)交集 intersect 返回两个结果集共同的记录
select * from emp intersect
select * from emp wheredeptno=10;
--(3)减 minus
select * from emp minus
select * from emp wheredeptno=10;
--(4)连接运算符 "||" 连接两个字符串
select '陈欣'||'陈乙荣' from dual;
select '今天是'|| sysdate fromdual;
--函数 包含数值函数、字符函数和日期函数
--(1)数值函数
-- ceil(向上取整) floor(向下取整)
select ceil(3.4),floor(3.6)from dual;
-- power(n次方) sqrt(平方根)
select power(2,10),floor(16)from dual;
--mod (求余)
select mod(5,2) from dual;
-- round(保留小数点后两位,小数点后第三位四舍五入) 和 trunc(保留小数点后两位,小数点后第二位直接截断) 处理小数位数
selectround(3.1567,2),trunc(3.14159265754,2) from dual;
--(2)字符处理函数
--字符串连接
selectconcat('abc','def'),'abc'||'def' from dual;
--求长度
select length('welcome')from dual;
select * from emp wherelength(ename)=4;
--查找字符串第一次出现的位置
selectinstr('welcomeco','co') from dual;
--字符串截取 substr
select substr('HelloWorld',6,5) from dual;
selectename,substr(ename,1,3) from emp;
--字符串变大写和小写
selectupper('abc'),lower('DEF') from dual;
--填充 lpad(左填充),rpad(右填充)
selectlpad('HelloWorld',15,'-'),rpad('HelloWorld',15,'-')from dual;
--左右都填充
selectlpad('HelloWorld',15,'-'),rpad(lpad('HelloWorld',15,'-'),20,'-') from dual;
--去掉空格
select ltrim(' abc'),rtrim('cde ')from dual;
--(3)日期处理函数
--sysdate 返回系统当前日期
select sysdate from dual;
selectto_char(sysdate,'yyyy-mm-dd') from dual;
--add_months 返回日期加上月份后的日期
selectadd_months(sysdate,2),add_months('02-4月-15',1) from dual;
备注:
‘add_months(sysdate,2)’中,sysdate是指系统当前日期 (2018-6-4 周一),2是指当前日期的月份+2,结果是04-8月 —18
‘add_months('02-4月-15',1)’中,'02-4月-15'表示指定的日期,1是指定的日期月份+1
--months_between 返回两个日期之间相差的月份
selectmonths_between(sysdate,'08-8月-08')from dual;
--返回两个日期之间相差的天数(四舍五入取整)
selectround(months_between(sysdate,'08-8月-08')*30,0)from dual;
--last_day 返回日期所在月份最后一天的日期
select last_day(sysdate)from dual;
--查询最后一天入职的员工
insert intoemp(empno,ename,hiredate,job,sal) values(8000,'陈欣',to_date('2019-06-30','yyyy-mm-dd'),'总监',10000);
selectempno,ename,hiredate,job,sal from emp where hiredate=last_day(hiredate);
--(4)转换函数 to_char to_dateto_number
selectto_char(sysdate,'yyyy-mm-dd hh:mi:ss') ,to_char(sysdate,'mm') from dual;
select to_number('23') *2from dual;
select * from emp;
--(5)空值函数 nvl
select empno, sal, comm, nvl(comm,0)from emp;
selectempno,sal,comm,nvl(comm,0),sal+nvl(comm,0) 工资奖金和 from emp;
课堂作业3 运算符和函数
课堂作业3 函数和运算符:
1,查看系统当前日期和时间
select sysdate from dual;
查询结果:
selectto_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual;
查询结果:
2,显示2013年11月1日到现在过了多少个月?(提示:使用months_between,round)
selectround(months_between(sysdate,'01-11月-13'))from dual;
查询结果:
3,显示奥运会到现在过了多少天?
selectround(months_between(sysdate,'08-8月-08')*30,0)from dual;
查询结果:
4,从’HelloWorld!’截取出’Hello’
select substr('HelloWorld',1,5) from dual;
查询结果:
5,对数字4.56向上取整
select ceil(4.56) from dual;
查询结果:
6,显示字符’!’在 字符串’HelloWorld!Welcom’中第一次出现的位置
select instr('HelloWorld!Welcom','!')from dual;
查询结果:
7,显示’S’在字符串’ SALESMAN’中第一次出现的位置
select instr('SALESMAN','S')from dual;
查询结果:
8,返回字符串’Hello’和’World’连接后的字符串,并求连接后字符串的长度。
select 'Hello'||'World',length('Hello'|| 'World') from dual;
查询结果:
9,使用Lpad和Rpad函数显示字符串‘---you are welcom---’
select rpad(lpad('you arewelcom',17,'-'),20,'-') from dual;
查询结果:
10,分别显示系统当前日期的年、月和日部分,使用to_char
selectto_char(sysdate,'YYYY'),to_char(sysdate,'mm'),to_char(sysdate,'dd') from dual;
查询结果:
11,查询员工表emp中员工名字长度为5的员工号、员工名和工资
select * from emp;
select empno,ename,sal fromemp where length(ename)=5;
查询结果:
12,查询emp表,显示字段员工号、员工名称,工资,佣金,工资和佣金的和,部门号
select empno 员工号, ename 员工名称, sal 工资, comm 佣金,nvl(comm,0),sal+nvl(comm,0)工资和佣金的和 ,deptno 部门号 from emp;
查询结果:
13,查询员工表的员工信息和部门号是20的员工信息的交集,包括员工号、员工名、入职日期和部门号
select * from emp;
selectempno,ename,hiredate,deptno from emp intersect
selectempno,ename,hiredate,deptno from emp where deptno=20;
运行结果:
课堂内容4 条件、别名的使用、逻辑运算符的使用、聚合函数
--数据查询
select * from emp order bydeptno;
--查询工资大于2500的员工信息,包括员工号、员工名、工作和工资
select empno,ename,job,salfrom emp where sal>2500;
--查询中使用别名
--查询工作是销售员'SALESMAN'的员工信息,包括员工号、员工名、工作和工资,并按工资降序排列
select empno 员工号,ename 员工名,job 工作,sal 工资 fromemp
where job='SALESMAN' orderby sal desc;
--逻辑运算符的使用 and or not
--查询部门号为20,同时工资高于2000的员工信息
select * from emp wheredeptno=20 and sal>2000;
--查询不在部门20工作的员工信息
select * from emp where notdeptno=20;
--排序 多个字段排序 order by总是出现在最后
--查询员工信息,包括员工号、员工名、工作和工资,并按工作升序排列,按工资降序排列
select empno 员工号,ename 员工名,job 工作,sal 工资 fromemp
order by job asc,sal desc;
--查询中使用运算符
数据只是查询 对表里数据没有真正的改变
数据只是查询 对表里数据没有真正的改变
selectempno,job,sal,sal+sal*0.1 from emp where deptno=10;
--使用distinct去掉重复行
查看一共有哪几种工作
select distinct(job) fromemp;
--模糊查询,使用通配符 % _
--查询名字的首字母为"A"的员工信息
select * from emp whereename like 'A%';
--查询名字里包含字母"A"的员工信息
select * from emp whereename like '%A%';
--查询员工号第二位为9的员工信息
select * from emp whereempno like '_9%';
--between 和 in 的用法
--查询员工工资在1000到3000的员工信息,包括员工号、员工名、入职日期和工资
selectempno,ename,hiredate,sal from emp where sal between 1000 and 3000;
--查询从2月到5月入职的员工信息,包括员工号、员工名、入职日期和工资
select to_char(sysdate,'mm')from dual;
--条件 where 里面不可以出现别名排序可以
方法1:
selectempno,ename,hiredate,sal,to_number(to_char(hiredate,'mm' )) yf from emp
whereto_number(to_char(hiredate,'mm' ))between 2 and 5
order by yf desc;
方法2:
selectempno,ename,hiredate,sal from emp
where to_char(hiredate,'mm')between 2 and 5
order byto_char(hiredate,'mm') desc;
--in 表示范围
--查询部门号10和部门号20的员工信息,包括员工号、员工名和部门号
select empno,ename, deptnofrom emp where deptno in (10,20)
order by deptno desc;
--null和is一起使用
--查询佣金为空的员工信息
select * from emp where commis null;
--查询佣金不为空的员工信息
select * from emp where commis not null;
--聚合函数 max min avg sumcount(*) count(字段名)
--查询员工的最高工资
select max(sal) 最高工资 from emp;
select min(sal) 最低工资,round(avg(sal),2)平均工资,sum(sal) 和, count(*) 人数 from emp;
--求最早入职的员工的入职日期
selectmin(hiredate),max(hiredate) from emp;
--统计员工人数
select count(*),count(empno)from emp;
空值函数null必须转化成0来参与计算
--分组查询 使用group by
select * from emp order bydeptno;
--分组查询各部门的部门号、人数和工资总额
select deptno,count(*),sum(sal)from emp group by deptno;
--分组查询各部门的部门号、人数和工资总额,统计人数超过4的部门号码和人数 having 一定跟在group by后边
select deptno,count(*),sum(sal)from emp
group by deptno
having count(*)>4;
--统计20部门中平均工资高于1000的各工种的员工人数和平均工资
select avg(sal),count(*),jobfrom emp where deptno=20
group by job
having avg(sal)>1000;
课堂作业4 基本查询
(1)列出部门30和部门20的雇员的编号、名字和部门号。
selectempno,ename, deptno from emp where deptno in (30,20)
orderby deptno desc;
(2)列出所有办事员(CLERK)的姓名、编号和部门号。
select ename,empno,deptno from emp where job in ('CLERK');
select ename,empno,deptno from emp where job='CLERK';
(3)找出佣金高于薪金的雇员名字、薪金和佣金。
selectename,sal,comm from emp where comm>sal;
(4)找出佣金高于薪金60%的雇员。
selectempno,ename,job,sal,comm from emp where comm>sal*0.6;
(5)找出带有佣金的雇员的雇员编号、雇员名称和佣金。
selectempno,ename,comm from emp where comm is not null;
(6)找出没有佣金或佣金低于100的雇员。
selectempno,ename,job,comm from emp where comm is null or comm<100;
(7)显示正好为5个字符的雇员姓名
select * fromemp where length(ename)=5;(length字符函数,计算字符串char的长度 )
select * fromemp where ename like '_____';
(8)显示不带有"R"的雇员姓名
select * fromemp where ename not like '%R%';
(9)显示所有雇员姓名的前三个字符
select substr(ename,1,3) from emp;
(10)显示雇员姓名和服务年限,并根据其服务年限,将最老的雇员排在最前面。
select ename 雇主姓名,to_char(sysdate,'yyyy')-to_char(hiredate,'yyyy')服务年限 from emp
order by 服务年限 desc;
(11)显示姓名字段的任何位置包含“A”的所有雇员的姓名。
select * from emp whereename like '%A%';
(12)查询各部门的人数.
select deptno,count(empno)from emp group by deptno;
(13)查询从事不同工作的员工人数
select distinctjob,count(empno) from emp group by job;
(14)按部门号分组,查询平均工资高于2000的部门号和平均工资.
select deptno 部门号,round(avg(sal),2) 平均工资 from emp
group by deptno
having avg(sal)>2000;
课堂内容5 多表查询 交叉连接 内连接 外连接 自连接
--多表连接 包括内连接(等值),外连接和自连接
--内连接(等值连接) inner join ..on
--查询员工所在的部门信息,包括员工号、员工名、工资和部门名称
当两表有相同的字段 用别名
方法1
select a.dname,b.empno,b.ename,b.sal fromdept a inner join emp b on a.deptno=b.deptno;
方法2
select a.dname,b.empno,b.ename,b.sal fromdept a , emp b where a.deptno=b.deptno;
--外连接(左外连接和右外连接):发生在两个表之间
--左外连接
--查询没有员工的部门信息,包括部门号、部门名称
select a.deptno,a.dname,b.* from dept a leftjoin emp b on a.deptno=b.deptno
where b.empno is null;
--右外连接
select b.deptno,b.dname,b.* from emp a rightjoin dept b on a.deptno=b.deptno
where a.empno is null;
系统用户还有一个hr用户 里有资料可以练习
第一步:在SQL Plus中更改用户:
SQL*Plus: Release 11.2.0.1.0 Production on 星期三 6月 611:04:45 2018
Copyright (c) 1982, 2010, Oracle. All rights reserved.
请输入用户名: system/123456
ERROR:
ORA-28002: the password will expire within 7days
连接到:
Oracle Database 11g Enterprise EditionRelease 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining andReal Application Testing options
SQL> alteruser hr account unlock;
用户已更改。
SQL> alteruser hr identified by hr;
用户已更改。
SQL> connhr/hr
已连接。
SQL>
第二部:在SQL Developer建立新的连接:
select * from regions; (a 区域表)
select * from countries order by region_id;(b 国家表)
select * from locations order by country_id;(c 地区表)
--多表连接 查询亚洲地区包含的国家信息,包括地区名称、国家名称、城市名称和城市地址
方法1:
selecta.region_name,b.country_name,c.city,c.street_address from regions a
inner join countries b ona.region_id=b.region_id
inner join locations c onb.country_id=c.country_id
where a.region_name='Asia';
方法2:
selecta.region_name,b.country_name,c.city,c.street_address from regions a,countriesb,locations c
where a.region_id=b.region_id andb.country_id=c.country_id and a.region_name='Asia';
:
--查询不包含国家的区域,显示区域id和区域名称
方法1:
insert into regions values(5,'X区域');
select a.* from regions a left join countriesb on a.region_id=b.region_id
where b.country_id is null;
方法2:
select * from regions where region_id notin(select distinct(region_id) from countries);
课堂内容6 子查询
--自连接 (表自身进行连接)
--查询员工的编号、姓名以及上司的编号和姓名
select * from emp;
方法1:
select a.empno 员工号, a.ename 员工名, b.empno 上司编号, b.ename 上司名称 from emp a inner join emp b on a.mgr=b.empno;
方法2:
select a.empno 员工号, a.ename 员工名, b.empno 上司编号, b.ename 上司名称 from emp a ,emp b where a.mgr=b.empno;
--查询比7499员工工资高的员工编号、员工名和工资
select a.empno,a.ename,a.sal,b.sal from empa,emp b where a.sal>b.sal and b.empno=7499;
--子查询
--查询工资最高的员工信息
select * from emp where sal=(select max(sal)from emp);
--子查询的分类
1)单行子查询:子查询返回一个单个值:主查询的条件和子查询之间使用比较运算符 > >= < <= = !=
--查询高于所有员工平均工资的员工信息
select * from emp where sal>(selectavg(sal) from emp);
--查找与7369雇员号在同一个部门的所有职员信息。包括雇员号、雇员姓名、职位、薪酬和雇佣日期。
select empno,ename,job,sal,hiredate,deptnofrom emp where deptno=(select deptno from emp where empno=7369);
--查找与7369雇员从事相同工作的雇员信息。包括雇员号、雇员姓名、职位、薪酬雇佣日期。
select empno,ename,job,sal,hiredate,deptnofrom emp where job=(select job from emp where empno=7369);
2)多行子查询-子查询返回多个值,主查询和子查询之间使用 in/not in/ any/ all
>any:表示大于某一个(大于最小值)
all:表示所有
>all:表示大于最大值
--查询与部门号10的雇员从事相同工作的雇员信息。包括雇员号、雇员姓名、职位、薪酬和雇佣日期。
select empno,ename,job,sal,hiredate,deptnofrom emp where job in (select job from emp where deptno=10);
--1>查询比部门10某个雇员工资的雇员信息,包括雇员号、雇员姓名、职位、薪酬和雇佣日期。
selectsal from emp where deptno=10;
selectempno,ename,job,sal,hiredate,deptno from emp where sal>any(select sal fromemp where deptno=10);
--2>查询比部门20所有雇员工资的雇员信息,包括雇员号、雇员姓名、职位、薪酬和雇佣日期。
方法1:
select empno,ename,job,sal,hiredate,deptno from emp wheresal>all(select sal from emp where deptno=20);
方法2:
select * from emp where sal>(select max(sal)from emp where deptno=20);
--相关子查询 子查询引用主查询中的列
--查找所有工资高于本部门员工平均工资的员工信息。
select * from emp a where sal>(selectavg(sal) from emp b where a.deptno=b.deptno );
--查询部门信息以及该部门包含的员工人数
select a.*,(select count(*) from emp b wherea.deptno=b.deptno) from dept a;(经典)
课堂作业5多表连接和子查询
select * from emp;
--1.列出薪金比“SMITH”多的雇员信息。
select * from emp where sal>(select salfrom emp where ename='SMITH');
--2.查询高于最低工资的员工信息
select * from emp where sal>(selectmin(sal) from emp);
--3.列出薪金高于公司平均水平的所有雇员信息。
select * from emp where sal>(selectavg(sal) from emp );
--4.列出与“SCOTT”从事相同工作的所有雇员。
select empno,ename,job,sal,hiredate,deptnofrom emp where job=(select job from emp where ename='SCOTT');
--5.列出与部门号20的员工从事相同工作的员工信息,包括员工号、工作和工资。
select empno,job,sal,deptno from emp wherejob in (select job from emp where deptno=20);
--6.查询员工所在的部门信息,包括员工号、员工名、工资和部门名称
select * from dept;
select a.empno,a.ename,a.sal,b.dname from empa,dept b where a.deptno=b.deptno;
--7.使用dept和emp表,查询没有员工的部门信息,包括部门号、部门名称
select deptno,dname from dept where deptnonot in (select distinct deptno from emp);
--8.查询部门信息以及相应部门包含的人数
select a.*,(select count(*) from emp b wherea.deptno=b.deptno) as 部门人数from dept a;
--9.查询工资高于部门20所有员工工资的员工信息,包括员工号、员工名和工资
select empno,ename,sal from emp wheresal>all(select sal from emp where deptno=20);
--10.查询工资等于最高工资的员工信息
select * from emp where sal=(select max(sal)from emp);
课堂内容7 plsql变量定义和赋值
9.2 PL/SQL程序结构
--plsql程序块
包括三个部分
declare --声明变量
...
begin --可执行部分
…
Exception --异常处理部分
…
end;
--编写plsql程序块,定义一个变量赋值,然后输出。
set serveroutput on --设置输出
declare
v_num number:=12;
begin
v_num:=10; 等号右边的值赋给等号左边的变量
dbms_output.put_line(v_num);
end;
--定义变量和常量
declare
v_namechar(15):='chenxin';
PIconstant number:=3.14;
begin
dbms_output.put_line(v_name||' '||PI);
end;
--变量赋值
1)变量名:=值;
2)select .. into
--用一个完整的PL/SQL块实现查询雇员号为7934的雇员信息(sal,comm)
declare
v_sal number(7,0); --(7,0) 表示7位数,没有小数
v_comm number(7,0);
begin
select sal,comm into v_sal,v_comm from empwhere empno=7934;
dbms_output.put_line('员工的工资:'||v_sal||' '||'奖金:'||v_comm);
exception
when no_data_found then
dbms_output.put_line('员工号不存在!');
end;
--用一个完整的PL/SQL块实现根据输入的雇员号查看雇员信息(sal,comm)
declare
v_sal number(7,0);
v_comm number(7,0);
v_eno number;
begin
v_eno:=&请输入员工号;
select sal,nvl(comm,0) into v_sal,v_comm fromemp where empno=v_eno;
dbms_output.put_line(v_eno||'员工的工资:'||v_sal||' '||'奖金:'||v_comm);
exception --捕获程序错误异常处理
when no_data_found then
dbms_output.put_line('无此员工!');
end;
--编写一个plsql块,根据输入的部门号,求出部门名称,输出。
declare
v_deptno number(2,0);
v_dname varchar2(14);
begin
v_deptno:=&请输入部门号;
select dname into v_dname from dept wheredeptno=v_deptno;
dbms_output.put_line(v_deptno||'部门名称为:'||v_dname);
exception
when no_data_found then
dbms_output.put_line('no department!');
end;
课堂内容8 变量定义和赋值
--数据类型 %type和%rowtype的用法
%type:定义列类型
set serveroutput on
declare
eno emp.empno%type;
begin
select empno into eno from emp where ename='SMITH';
dbms_output.put_line(eno);
end;
%rowtype:定义行类型
--输入部门号,显示该部门的名称和位置
declare
dept_row dept%rowtype;
dno number(2,0);
begin
dno:=&请输入部门号;
select * into dept_row from dept wheredeptno=dno;
dbms_output.put_line(dept_row.deptno||' '||dept_row.dname||' '||dept_row.loc);
exception
when no_data_found then
dbms_output.put_line('无此部门!');
end;
课堂作业 变量定义和赋值
--1,编写pl/sql块,计算圆面积,根据输入半径,计算圆面积并输出。(使用常量)
--定义常量 declare PI CONSTANT number:=3.14; 圆的面积=r*r*PI(3.14)
set serveroutput on
declare
PI CONSTANT number:=3.14;
r number;
begin
r:=&请输入半径;
dbms_output.put_line('圆的面积为:'||r*r*PI);
end
;
--2,编写PL/SQL块,使用emp表根据输入的部门编号统计部门内的员工总人数
declare
v_deptno number(2,0);
v_count number;
begin
v_deptno:=&请输入部门编号;
select count(deptno) into v_count from emp
where deptno=v_deptno;
dbms_output.put_line('部门'||v_deptno||'总人数为:'||v_count);
exception
when no_data_found then
dbms_output.put_line('无此部门!');
end;
/*
selectcount(deptno) into v_count from emp
wheredeptno=v_deptno;
select count(deptno)from emp;
wheredeptno=20
*/
--3,编写PL/SQL块,使用emp表使用属性类型,根据输入的员工编号,求出员工名称和工资并输出。(可使用%type 或 %rowtype)
declare
emp_row emp%rowtype;
eno number(4,0);
begin
eno:=&请输入员工编号;
select * into emp_row from emp whereempno=eno;
dbms_output.put_line(eno||'员工名称:'||emp_row.ename||' 工资:'||emp_row.sal);
exception
when no_data_found then
dbms_output.put_line('无此员工!');
end;
课堂内容 控制结构
--空语句null
begin
null;
end;
--plsql语句
空语句 null;
赋值语句 两种
--分支和循环语句
通过if条件控制语句为不同部门的员工增加工资。
--根据输入员工号,判断该员工属于哪个部门,部门10加薪100,部门20加薪200,其他部门加薪300,显示加薪后的员工号和工资
set serveroutput
方法1(推荐):
declare
v_eno emp.empno%type;
v_dno emp.deptno%type;
v_sal emp.sal%type;
begin
v_eno:=&请输入员工号;
select deptno,sal into v_dno,v_sal from empwhere empno=v_eno;
dbms_output.put_line('部门:'||v_dno||'加薪之后的薪水'||v_sal);
ifv_dno=10 then
update emp set sal=sal+100 where empno=v_eno;
elsif v_dno=20 then
update emp set sal=sal+200 where empno=v_eno;
else
update emp set sal=sal+300 where empno=v_eno;
endif;
select sal into v_sal from emp where empno=v_eno;
dbms_output.put_line('员工:'||v_eno||'加薪之后的薪水'||v_sal);
exception
when others then
dbms_output.put_line('员工不存在!')
end;
方法2:
declare
v_eno emp.empno%type;
v_dno emp.deptno%type;
v_sal emp.sal%type;
begin
v_eno:=&请输入员工号;
select deptno,sal into v_dno,v_sal from empwhere empno=v_eno;
dbms_output.put_line('部门:'||v_dno||'加薪之后的薪水'||v_sal);
ifv_dno=10 then
update emp set sal=sal+100 where empno=v_eno returning sal into v_sal;
elsif v_dno=20 then
update emp set sal=sal+200 where empno=v_eno returning sal into v_sal;
else
update emp set sal=sal+300 where empno=v_eno returning sal into v_sal;
endif;
dbms_output.put_line('员工:'||v_eno||'加薪之后的薪水'||v_sal);
exception
when others then
dbms_output.put_line('员工不存在!');
end;
通过case选择控制语句为不同部门的员工增加工资。
declare
v_eno emp.empno%type;
v_dno emp.deptno%type;
v_sal emp.sal%type;
begin
v_eno:=&请输入员工号;
select deptno,sal into v_dno,v_sal from empwhere empno=v_eno;
dbms_output.put_line('部门:'||v_dno||'加薪之后的薪水'||v_sal);
casev_dno
when 10 then
update emp set sal=sal+100 where empno=v_eno;
when 20 then
update emp set sal=sal+200 where empno=v_eno;
else
update emp set sal=sal+300 where empno=v_eno;
endcase;
select sal into v_sal from emp where empno=v_eno;
dbms_output.put_line('员工:'||v_eno||'加薪之后的薪水'||v_sal);
exception
when others then
dbms_output.put_line('员工不存在!');
end;
--输入一个数,判断该数是奇数还是偶数
declare
v_num number(2,0);
begin
v_num:=&请输入一个数;
ifv_num!=0 then
ifmod(v_num,2)=0 then
dbms_output.put_line(v_num||'偶数');
else
dbms_output.put_line(v_num||'奇数');
endif;
else
dbms_output.put_line('0不参与判断');
endif;
end;
--根据评分结果输出评价
declare
grade char(2);
remark varchar2(20);
begin
grade:='&ch';
case grade
when 'A' then remark:='is Excellent';
when 'B' then remark:='is Good';
when 'C' then remark:='is Normal';
when 'D' then remark:='is Bad';
else remark:='big Problem';
endcase;
dbms_output.put_line('remark '||remark);
end;
课堂内容 循环结构
循环结构有3种形式,分别为loop循环、while循环、for循环
--循环
一、简单循环(loop循环)
--语法:
/*
loop
statements;
end loop;*/
(1)使用loop循环依次输出1到5之间的平方数。
set serveroutput on
declare
i number:=1;
begin
loop
dbms_output.put_line(i||'的平方'||i*i);
i:=i+1;
if i>5 then
exit;
end if;
endloop;
end;
(2)使用loop循环计算1到10的和。
declare
s number :=0; --定义一个变量存放和
i number :=0; --定义一个循环变量 赋初值0
begin
loop
i:=i+1;
s:=s+i; --累加
if i>=10 then --判断i的值是否大于10
exit;
end if;
endloop;
dbms_output.put_line('1到10的和是'||s);
end;
二、while循环
--语法:
/*
while 条件
loop
statements;
end loop;*/
(1)使用while .. loop循环计算1到10的和。
declare
s number :=0;
i number :=0;
begin
whilei<10
loop
i:=i+1;
s:=s+i;
endloop;
dbms_output.put_line('1到10的和是'||s);
end;
三、for-loop循环(--类似与for循环)
--语法:
/*
for loop_count in [reverse]lower_bound..height_bound loop
statements;
end loop;*/
其中loop_count为循环变量
lower_bound 为低边值(最小值)
height_bound 为高边值(最大值)
--(1)使用for循环依次输出1到5之间的立方数。
declare
i number:=1;
begin
for iin 1..5
loop
dbms_output.put_line(i ||'的立方为'|| i*i*i);
endloop;
end;
--reverse关键字 表示循环变量从高边值向低边值递减计数 (通俗记就是从大到小排序)
declare
i number:=1;
begin
for iin reverse 1..5
loop
dbms_output.put_line(i ||'的立方为'|| i*i*i);
endloop;
end;
--(2)使用for .. loop循环计算1到10的和。
declare
s number:=0;
begin
for iin 1..10
loop
s:=s+i;
endloop;
dbms_output.put_line('1到10的和是'|| s);
end;
--使用循环完成1到50内的偶数和并输出
--1.简单循环(loop循环)
declare
s number :=0; --定义一个变量存放和
i number :=1; --定义一个循环变量
begin
loop
if i mod 2 =0 then
s:=s+i;
end if;
i:=i+1;
exit when i>50;
endloop;
dbms_output.put_line('1到50内的偶数和是'||s);
end;
--2.while .. loop循环
declare
s number :=0;
i number :=1;
begin
whilei <=50
loop
ifmod(i,2)=0 then --i/2的余数=0 i就为偶数
s:=s+i;
endif;
i:=i+1;
endloop;
dbms_output.put_line('1到50内的偶数和是'||s);
end;
--3.for-loop循环
declare
s number :=0; --定义一个变量存放和
begin
for iin 1..50
loop
if i mod 2 =0 then
s:=s+i;
end if;
endloop;
dbms_output.put_line('1到50内的偶数和是'||s);
end;
--计算100以内能被3整除的数,每行输出10个数
提示:
dbms_output.put --输出,不换行,使用dbms_output.put_line看到输出的数据
dbms_output.put_line --输出,换行
declare
v_count number:=0;
begin
for iin 1..100
loop
ifmod(i,3)=0 then
dbms_output.put(i||' ');
v_count:=v_count+1; --统计输出数的个数
if mod(v_count,10)=0 then
dbms_output.put_line(' ');
end if;
endif;
endloop;
dbms_output.put_line(' ');
end;
课堂作业 循环和分支
1、根据输入的部门号,统计部门内的员工人数。
select* from dept;
setserveroutput on
declare
v_deptnonumber(2,0);
v_countnumber;
begin
v_deptno:=&请输入部门编号;
selectcount(deptno) into v_count from emp
wheredeptno=v_deptno;
dbms_output.put_line('部门'||v_deptno||'总人数为:'||v_count);
exception
whenno_data_found then
dbms_output.put_line('无此部门!');
end;
2、使用任意循环方式,计算6的阶乘。
--①for-loop循环
declare
snumber :=1; --定义一个变量存放和
begin
for i in 1..6
loop
s:=s*i;
end loop;
dbms_output.put_line('6的阶乘为'||s);
end;
--②while .. loop循环
declare
snumber :=1;
inumber :=1;
begin
while i <=6
loop
s:=s*i;
i:=i+1;
end loop;
dbms_output.put_line('6的阶乘为'||s);
end;
--③简单循环(loop循环)
declare
snumber :=1; --定义一个变量存放和
inumber :=1; --定义一个循环变量
begin
loop
s:=s*i;
i:=i+1;
exit when i>6;
end loop;
dbms_output.put_line('6的阶乘为'||s);
end;
3、编写PL/SQL块,使用CASE语句更新相应部门的员工补贴。部门10补贴100,部门20补贴80,部门30补贴50,40补贴30。(使用SCOTT用户的emp表,补贴字段名称为“comm”)。
自己做的 审题错误
select * from emp;
declare
v_eno emp.empno%type;
v_dno emp.deptno%type;
v_comm emp.sal%type;
begin
v_eno:=&请输入员工号;
select deptno,comm into v_dno,v_comm from emp where empno=v_eno;
dbms_output.put_line('部门:'||v_dno||'补贴之后有:'||v_comm);
case v_dno
when 10 then
update emp setcomm=comm+100 where empno=v_eno;
when 20 then
update emp set comm=comm+80where empno=v_eno;
when 30 then
update emp set comm=comm+50where empno=v_eno;
else
update emp set comm=comm+30where empno=v_eno;
end case;
select comm into v_comm from emp where empno=v_eno;
dbms_output.put_line('员工:'||v_eno||'补贴之后有:'||v_comm);
exception
when others then
dbms_output.put_line('员工不存在!');
end;
老师解答:
select* from emp order by deptno;
declare
v_deptnonumber(2,0);
v_increnumber;
begin
v_deptno:=&请输入部门号;
casev_deptno
when10 then v_incre:=100;
when20 then v_incre:=80;
when30 then v_incre:=50;
when40 then v_incre:=30;
endcase;
updateemp set comm=nvl(comm,0) +v_incre where deptno=v_deptno;
end;
rollback;
4、编写PL/SQL块,用以接受雇员的雇员号(empno)。如果雇员在公司工作时间满15年,则增加1000元的薪水。如果工作时间在10年到15年之间,则增加500元的薪水。如果工作时间少于10年,则增加200元的薪水。
declare
v_time number;
v_eno emp.empno%type;
v_sal emp.sal%type;
begin
v_eno:=&请输入员工号;
select sal into v_sal from emp where empno=v_eno;
dbms_output.put_line('员工:'||v_eno||'加薪之前的薪水'||v_sal);
select to_char(sysdate,'yyyy')-to_char(hiredate,'yyyy')into v_time from emp where empno=v_eno;
ifv_time<10 then
updateemp set sal=sal+200 where empno=v_eno returning sal into v_sal;
elsif v_timebetween 10 and 15 then
updateemp set sal=sal+500 where empno=v_eno returning sal into v_sal;
else
updateemp set sal=sal+1000 where empno=v_eno returning sal into v_sal;
end if;
select sal into v_sal from emp where empno=v_eno;
dbms_output.put_line('员工:'||v_eno||'加薪之后的薪水'||v_sal);
exception
when others then
dbms_output.put_line('员工不存在!');
end;
老师解答:
declare
v_empno emp.empno%type;
v_hiredate date;
v_sal emp.sal%type;--增加钱的薪水
v_year number; --入职年限
v_incre number; --增加薪水
begin
v_empno:=&请输入雇员号;
select hiredate,sal into v_hiredate,v_sal from emp where empno=v_empno;
dbms_output.put_line(v_empno||'增加之前的薪水:'||v_sal);
select round(months_between(sysdate,v_hiredate)/12) into v_year fromdual;
/*select to_number(to_char(sysdate,'yyyy'))-to_number(to_char(v_hiredate,'yyyy'))into v_year from dual;*/
ifv_year>15 then
v_incre:=1000;
elsif v_year<=15 and v_year>=10 then
v_incre:=500;
elsif v_year<10 then
v_incre:=200;
endif;
update emp set sal=sal+v_incre where empno=v_empno;
select sal into v_sal from emp where empno=v_empno;
dbms_output.put_line(v_empno||'增加之后的薪水:'||v_sal);
end;
未完待续......