oracle数据库基本语法及查询

一.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;

你可能感兴趣的:(oracle)