一.SQL语句及子查询的用法:
这里是在scott用户下完成的,首先需要解锁scott用户
alter user scott account unlock;
password scott;
set timing on;
set time on;
set pagesize 10;
set linesize 100;
show user
show error
set serveroutput on;
select * from emp;
1.显示工资大于1500的员工信息
select * from emp where sal>1500;
2. 显示首字母为S的员工姓名和工资
select ename,sal from emp where ename like 'S%';
3. 显示job不是'PRESIDENT','MANAGER'的员工信息
select ename from emp where job not in('PRESIDENT','MANAGER');
4. 显示工资在2000至3000之间的员工信息
使用between and 和><都可以
select ename from emp where sal between 2000 and 3000;
select ename from emp where sal >=2000 and sal<= 3000;
5. 显示所有员工中最高工资和最低工资
使用聚集函数 min();max()
select min(sal)min_sal,max(sal) max_sal from emp;
6. 按照部门分组,统计部门平均工资,结果按工资降序排列
需要聚集函数AVG()
select avg(sal),deptno
from emp
group by deptno
order by avg(sal);
7. 显示emp表中工资最高的员工信息
需要用到子查询 用于找出最高工资
select ename from emp where sal=(
select max(sal) from emp
);
8. 显示与smith同部门的所有员工
使用子查询先找出smith的部门 --注意字符串使用的是单引号,不是双引号
select ename from emp where deptno=(
select deptno from emp where ename='SMITH'
);
9. 查找部门10的所有工作岗位
select job from emp where deptno=10;
10. 显示工资比部门30的所有员工的工资都高的员工的姓名,工资和部门号
使用子查询首先找出部门30的员工的最高工资 进行比较的时候可以使用聚集函数,即单行子查询
如果不使用聚集函数就是多行子查询 必须使用多行比较符(in all any)
select ename, sal, deptno from emp where sal>all(
select sal from emp where deptno=30
);
select ename, sal, deptno from emp where sal>(
select max(sal) from emp where deptno=30
);
11. 显示工资比部门30的任意员工的工资高的员工姓名,工资和部门号
select ename, sal, deptno from emp where sal>any(
select sal from emp where deptno=30
);
select ename, sal, deptno from emp where sal>(
select min(sal) from emp where deptno=30
);
12. 查询部门30的最低工资的员工信息
select min(sal) from emp where deptno=30;
13. 查询与smith的部门和岗位完全相同的所有雇员
子查询中先找出smith的部门和岗位
select ename from emp where (deptno,job)in(
select deptno,job from emp where ename='SMITH'
);
14. 查询与SCOTT的岗位和工资完全相同的雇员
select distinct ename from emp where (deptno,sal)in(
select deptno,sal from emp where ename='SCOTT'
);
15. 显示高于自己部门平均工资的员工信息
在from子句中使用了子查询(使用内嵌视图) 首先找到自己部门的平均工资
select ename from emp p ,(select avg(sal) avg_sal,deptno from emp group by deptno) q
where p.sal>q.avg_sal and p.deptno=q.deptno;
16. 显示工资高于同职位平均工资的员工信息
首先找到同职位的平均工资
select ename from emp p,(select avg(sal) sal,job from emp group by job )q
where p.sal>q.sal and p.job=q.job;
或者直接使用where里面的子查询也可以
select ename from emp p where sal>(
select avg(sal) from emp where job=p.job
)
order by sal;
二.数据表对象、查询、视图的创建及基本操作;
1. 现有一个商店的数据库,记录客户及其购物情况,由下面三个表组成:
要求如下:
1)商品表(goods):建立主键;商品类别、供应商、不能为空值;单价必须大于0.
2)客户表(customer):姓名、住址不能为空值;客户性别必须是男或者女,默认是男;电邮不能重复;身份证号不能重复.
3)购买表(purchase):建立联合主键(customerId,goodsId);购买数量必须在1-30之间;建立外键.
4)每个表中插入至少两条记录,内容要模拟现实。
1) goods(商品号goodsId,商品名 goodsName,单价 unitprice,商品类别category,供应商provider);
这里把主外码写成表级别约束 其他写成列级别约束
create table goods(
goodsId char(10),
goodsName varchar2(10),
unitprice number(5,2) check(unitprice>0),
category varchar2(10)not null,
provider varchar2(10)not null,
constraint prim_1 primary key(goodsId)
);
2) customer(客户号customerId,姓名name,住在address,电邮email,性别sex,身份证cardId);
create table customer(
customerId char(10),
name varchar2(10) not null,
address varchar2(10) not null,
email varchar2(10)unique,
sex varchar2(10)default'男' check(sex in('男','女')),
cardId char(10) unique,
constraint prim_2 primary key(customerId)
);
3) purchase(客户号customerId,商品号goodsId,购买数量nums);
create table purchase(
goodsId char(10),
customerId char(10),
nums number(20) check(nums between 1 and 30),
--一个联合主码 两个外码
constraint pri_2 primary key(goodsId,customerId),
constraint foreign_1 foreign key(goodsId)references goods(goodsId),
constraint foreign_2 foreign key(customerId) references customer(customerId)
);
----------------------------------------------------------------
插入数据
insert into goods values();
insert into goods values();
insert into customer values();
insert into customer values();
insert into purchase values();
insert into purchase values();
2.创建学生表,该表包含了学生编号、学生姓名、性别、年龄、系别编号、建档日期等信息。
create table student(
studentId char(10),
name varchar(8) not null,
sex char(5) default '男' check(sex in('男','女')),
age char(5) not null,
deptno varchar(10) not null,
undata data(10),
constraint prim_1 primary key(studentId)
);
3.创建班级表,包含班级编号和班级名称。
create table class(
classNo varchar(5),
className varchar(5) not null,
constraint prim_2 primary key(classNo)
);
三. 用户、角色的创建 和管理及权限的管理
1. 系统权限级联问题
注意只有具有dba系统管理员的权限才可以创建用户
创建用户tom ken;
create user tom identified by 123;
create user ken identified by 123;
1) system授权用户tom create session权限,并且允许tom授予其它用户此权限
grant create session to tom with admin option;
2) tom授予ken create session权限。
3) 现在system收回tom create session权限,那么tom还能登陆么?
conn tom/123;
grant create session to ken;
revoke create session from tom;
回收完之后tom不可以登陆了,ken可以登陆 不会级联收回该用户之前授予其他用户的系统权限
4) (4)ken 还能登陆么?
2.对象权限级联问题
1) system授权用户tom, 查询scott模式下emp表的权限,并且允许tom授予其它用户此权限。
grant select on scott.emp to tom with grant option;
2) tom授予ken查询scott模式下emp表的权限。
grant select on scott.emp to ken;
3) 现在system收回tom 上述权限
revoke select on scott.emp from tom;
4) 那么ken还能查询scott模式下emp表么?
不能
3.创建角色 appdev,授予登录权限及基本对象创建权限。将角色授权给tom。
create role appdev;
grant connect,resource to appdev;
grant appdev to tom;
4.删除角色
drop role appdev;
5.删除用户
drop user tom;
四. PL/SQL的语法及流程控制语句和游标的使用
1.编写PL/SQL语句块,使用scott用户下的emp表,根据输入的员工号查询该员工的姓名和工资并输出,如果员工号不正确,则给出提示。
declare
V_empno emp.empno%type;
V_name emp.ename%type;
V_sal emp.sal%type;
begin
V_empno:=&x;
select ename,sal into V_name,V_sal from emp
where empno=V_empno;
dbms_output.put_line('该员工姓名为'||V_name||'工资为'||V_sal);
exception when no_data_found then
dbms_output.put_line('没有找到数据');
end;
2.编写PL/SQL语句块,使用scott用户下的emp表,根据输入的员工号查询该员工的所在部门,所在部门平均工资、总人数并输出,
如果员工号不正确,则给出提示。
declare
V_empno emp.empno%type;
V_sal emp.sal%type;
V_count number(3);
begin
V_empno:=&x;
select count(*),avg(sal) into V_count,V_sal from emp
where deptno=(select deptno from emp where empno=V_empno);
dbms_output.put_line('该部门人数为'||V_count||'平均工资为'||V_sal);
exception when no_data_found then
dbms_output.put_line('员工号不正确');
end;
3. 查询HR用户下的EMPLOYEES表,根据输入的first_name,查询拥有相同first_name的雇员信息。
--如果没有此first_name,应给出提示。
--如果只有1个first_name,应给出提示。
--如果有多个first_name相同用户,显示重名的总人数及他们的最高工资。
declare
V_count num(5);
V_fname hr.employees.first_name%type;
V_salary hr.employees.salary%type;
begin
V_fname:=&x;
select count(*),max(salary) into V_count,V_salary from hr.employees where first_name=V_fname;
if(count=1)then dbms_output.put_line('只有一个人');
elsif(count>1)then
dbms_output.put_line('该部门人数为'||V_count||'最高工资为'||V_salary);
else dbms_output.put_line('没有该用户');
end;
4.输入1-7内的整数,根据输入的整数,输出星期一至星期日。
declare
begin
case()
end case;
end;
5.根据输入的整数,输出该整数的所有因数,不包括1和它本身。
declare
V_zhengshu number(3);
V_count number:=2;
begin
V_zhengshu:=&x;
loop
if mod(V_zhengshu,V_count)=0 then
dbms_output.put_line(V_count);
end if;
V_count:=V_count+1;
exit when V_count>V_zhengshu-1;
end loop;
end;
6. 使用hr.employees表,设计一个游标,根据输入的部门号查询某个部门的员工信息,部门号在程序运行时指定。
declare
V_department_id hr.employees.department_id%type;
cursor cur_name is (select* from hr.emplyees where department_id=V_department_id);
V_curcel cur_name%rowtype;
begin
V_department_id:=&x;
open cur_name
loop
fetch cur_name into cur_cel;
exit when cur_name%notfound
dbms_output.put_line('部门号为'||cur_cel.department_id ||''||cur_cel.employee_id||''||cur_cel.salary);
end loop;
close cur_name;
end;
7.利用简单循环统计并输出各部门的平均工资。
declare
cursor cur_sel is select avg(sal)sal,deptno from scott.emp group by deptno;
V_cur_sel cur_sel%rowtype;
begin
open cur_sel;
loop
fetch cur_sel into V_cur_sel;
exit when cur_sel%notfound;
dbms_output.put_line('部门号为'||V_cur_sel.deptno||'平均工资为'||V_cur_sel.sal);
end loop;
close cur_sel;
end ;
8.利用while循环统计并输出各部门的平均工资。
declare
cursor cur_sel is select avg(sal)sal,deptno from scott.emp group by deptno;
V_cur_sel cur_sel%rowtype;
begin
open cur_sel;
fetch cur_sel into V_cur_sel;
while cur_sel%found loop
dbms_output.put_line('部门号为'||V_cur_sel.deptno||'平均工资为'||V_cur_sel.sal);
fetch cur_sel into V_cur_sel;
end loop;
close cur_sel;
end;
9. 利用for循环统计并输出各部门的平均工资。
declare
begin
for V_cur_sel in (select avg(sal)sal,deptno from scott.emp group by deptno)
loop
dbms_output.put_line('部门号为'||V_cur_sel.deptno||'平均工资为'||round(V_cur_sel.sal,2));
end loop;
end ;
10.提示输入员工号, 然后修改该员工工资, 将其工资增加100。如果该员工不存在, 则提示。
如果员工存在则输出其frst_name和更新后的salary.
declare
V_empno SCOTT.emp.empno%type;
V_sal scott.emp.sal%type;
V_ename scott.emp.ename%type;
begin
V_empno:=&x;
update scott.emp set sal=sal+100 where empno=V_empno; --先更新在判断,如果没有则插入 有的话输出
if SQL%notfound then
dbms_output.put_line('插入');
else
select ename,sal into V_ename,V_sal from scott.emp where empno=V_empno;
dbms_output.put_line(V_ename||''||V_sal);
end if;
end;
11. 提示输入员工号,然后修改该员工工资,将其工资增加100。如果该员工不存在
,则向employees表中插入一个员工号为1000,工资为1500的员工。如果员工存在则输出其first_name和更新后的salary.
五.掌握存储过程、函数、触发器的创建及基本操作。
1.创建一个存储过程,以部门号为参数,查询该部门的平均工资,并输出该部门工资比平均工资高的员工号和员工姓名。
create or replace procedure pro_sel (V_deptno scott.emp.deptno%type)
as
V_sal scott.emp.sal%type;
--每一条数据都需要跟平均工资比较,所以需要用到循环,用到游标
begin
select avg(sal) into V_sal from scott.emp where deptno=V_deptno;
for V_num in (select * from scott.emp where sal>V_sal) loop
dbms_output.put_line('员工号'||V_num.empno||'员工姓名'||V_num.ename);
end loop;
end pro_sel;
执行存储过程 exec pro_sel (10);
2.创建一个存储过程,通过员工姓名查询员工工资,如果员工工资低于2000,则按百分比提高员工工资。
create or replace procedure pro_sel (V_ename scott.emp.ename%type)
as
V_sal scott.emp.sal%type;
--每一条数据都需要跟平均工资比较,所以需要用到循环,用到游标
begin
select avg(sal) into V_sal from scott.emp where ename=V_ename;
if V_sal<2000 then
update emp set sal=sal*0.1;
dbms_output.put_line(V_sal);
end if;
end pro_sel;
exec pro_sel ('SMITH');
4.创建名为‘FUNC_EMP_SALARY’的函数,以员工编号为参数,返回员工工资。
5. 创建名为 ‘func_emp_dept_avgsal’的函数,以员工号为参数,返回该员工所在部门的平均工资。
create or replace function func_dept_info(V_empno scott.emp.empno%type)
return scott.emp.sal%type
as
V_sal scott.emp.sal%type;
V_deptno scott.emp.deptno%type;
begin
--先找部门 再找工资
select deptno into V_deptno from emp where empno=V_empno;
select avg(sal) into V_sal from emp where deptno=V_deptno;
return V_sal;
exception when no_data_found then
raise_application_error(-1000,'没有这个顾客');
end;
--函数的调用
declare
v_var scott.emp.sal%type;
begin
v_var:=func_dept_info(7521);
dbms_output.put_line(v_var);
end;
6.创建名为‘func_dept_maxsal’的函数,以部门号为参数,返回部门最高工资
7. 1)创建名为‘func_dept_info’的函数,以部门号为参数,返回部门名、部门人数、以及部门平均工资。
2)调用函数,创建一个匿名块,输出各部门的名称,部门人数,部门平均工资
8. 触发器:
--(1)为employees表创建一个触发器,
--当执行插入操作时,统计插入操作后员工人数;
--当执行更新员工工资操作时,统计更新后员工平均工资;
--当执行删除员工操作时,统计删除后各个部门的员工人数。
create or replace trigger tri_name after select or insert or delete on employees
declare
--
begin
if selecting then
select count(*) from employees;
elsif updating then
select avg(sal) from employees;
else
for V_count in (select count(*) num,department_id from employees group by department_id)loop
dbms_output.put_line(V_count.num||''||V_count.department_id);
end loop;
end if;
end tri_name;
(2)为employees表创建一个触发器,当插入新员工时显示新员工的员工号、员工名;当更新员工工资时,显示修改前后员工工资;当删除员工时,显示被删除的员工号、员工名。
create or replace trigger tri_name after select or insert or delete on employees
for each row
declare
--
begin
if inserting THEN
dbms_output.put_line(:new.employee_id||''||:new.first_name||''||:new.last_name);
elsif updating THEN
dbms_output.put_line(:new.salary||''||:old.salary);
else
dbms_output.put_line(:old.employee_id||''||:old.first_name||''||:old.last_name);
end if;
exception when no_data_found then
raise_application_error(-9999,'chuxiancuowu');
end tri_name;