Oracle入门操作

Orale 入门操作–以oralce11g为例

1 Orcale11体系结构概述

数据库管理系统

实例(instance):一组的甲骨文后台进程以及在服务其中的分配的共享内存区域
数据库(database):基于磁盘的数据文件,控制文件
数据库服务器(database server):管理数据库的各种软件工具,比如SQLPLUS,OEM
关系:数据库为实例提供数据,实例用于管理,日志文件,参数文件和归档日志文件等组成的物理文件集合和控制数据库;数据库可以被多个实例装载和打开,而一个实例在其生存期内只能装载和打开一个数据库

数据块的逻辑和物理结构

数据块(Data Blocks):逻辑存储结构中最小的逻辑单位
数据区(Extent):由一组连续的甲骨文数据块所构成的甲骨文存储结构
段(Segment):由一个或多个数据区构成,是一个独立的逻辑存储结构
表空间(TableSpace):数据库最大逻辑划分区域

查询命令

    ----查看数据库大小
    col name format a30
    col name format a20
    select name,value from v$parameter
    where name='db_block_size';
    -----查看数据字典信息
    col table_name for a30;
    col comments for a30;
    select * from dict;
    ----查看数据文件信息
    col file_name for a50;
    set linesize 100;
    select file_name,tablespace_name from dba_data_files;
    ---查看临时文件信息
    col file_name format a50;
    col tablespace_name format a20;
    select file_name,tablespace_name from dba_temp_files;
    ---查看临时文件信息
    col name format a60;
    select * from v$controlfile;
    ---查看redo日志信息
    select * from v$logfile;
    ---查看系统是否采用归档模式
    col name format a30;
    select dbid,name,log_mode from v$database;
    ---查看归档日志文件的路径
    set pagesize 30;
    show parameter log_archive_dest;
    ---查询服务器参数
    col name for a30;
    col value for a30;
    select name,value,ismodified from v$parameter;
    ----查看警告文件路径
    col name for a30;
    col value for a30;
    select name,value from v#parameter
    where name='background_dump_dest';
    ----查看用户跟踪文件路径
    col name for a30;
    col value for a30;
    select name,value from v$parameter
    where name='user_dump_dest';

系统全局区SGA

高速数据缓冲区 Database buffer cache
重做日志缓冲区 red log buffer cache
共享池 Shared Pool
大型池 Large pool
Java池
池流 

程序全局区PGA

查询命令

--查看当前系统全局SGA信息
show parameter sga
--查看当前用户进程PGA
show parameter pga
--查看当前实例进程信息
set pagesize 50;
select name,description from v$bgprocess;
--查看所有用户的信息
select * from dba_users;
--查看数据库表空间的信息
select * from dba_tablespaces;
--查看档期数据库中所有数据表的描述
select * from dba_tables;
--查看当前用户所属表信息
select table_name from user_tables;
--查看当前数据库实例名称
select * from global_name
GLOBAL_NAME

SQL PLUS 命令

SQL *PLUS是一个基于C/S两层结构的客户端操作工具,
包括客户层(即命令行窗口)和服务器层(数据库实例)

set命令

--set命令的语法格式
set system_variable value
system_variable:变量名
value:变量值
--设置在命令提示符前显示档期系统时间
set time onset time off;

--显示查询时间
set timing on;
set timing off;

--设置一页显示行数,一页默认14行
show pagesize;
set pagesize 25;
select user_id,username,account_status
from dba_users;

--设置一行显示多少个字符,默认为80
show linesize;
set linesize 100;

--设置显示结果不会自动滚屏,按页暂停
set pause on;
set pause '按键继续';
select * from emp;
set pause off;

--设置emp表中数值显示格式为 $999,999,999.00
set numformat $999,999,999.00
select ename,job,sal from scott.emp;

--清除样式
clear column;
清屏
clear screen;

help 命令

--查看clear命令帮助
help clear;

describe 命令

查询指定数据对象的组成结构

--显示scott.emp表结构
desc emp;

spool 命令

把查询结果输出到指定文中,这样可以保存查询结果并方便打印

--将表中的记录保存到c:\emp.txt
spool c:\emp.txt
select empno,ename,job,sal fomr scott.emp
where job='SALESMAN';
spool off;

define命令

定义一个用户变量并且可以分配给它一个char值

define vjob='SALESMAN';
define vjob;
select * from scott.emp where job='&job';

&job临时变量

解锁用户:alter user scott account unlock;
更改密码:password scott
切换用户:conn scott/password;
select * from scott.emp where job='&job';

--使用变量进行查询
select empno,ename,job,sal from scott.emp where job='&vjob';

show命令
显示sql *plus系统变量的值或是 sql plus环境的值

--查看当前数据库实例的数据库大小
show parameters db_block_size;
show parameters sga;

edit命令
实现在记事本中编辑

edit
select empno,ename,job,sal,deptno
from scott.emp
where job='MANGER'
/

save命令
实现将sql缓冲区中的最近一条sql语句或pl/sql块保存到一个文件中

select ename,job,sal
from scott.emp
where job='SALESMAN'
save c:\salesman.sql replace;

get命令
把sql脚本文件内容放进sql缓冲区

--list:列出缓冲区现有脚本
list
select ename,job,sal
from scott.emp
where job='SALESMAN'
--run:执行缓冲区现有脚本
run
/
--get命令
get c:\salesman.sql;
select ename,job,sal
from scott.emp
where job='SALESMAN'

start和@命令
执行一个sql脚本文件

start c:\salesman.sql

column命令
实现格式化查询结果,设置列宽度,重新设置列标题等功能

--使用format格式化emp表中员工工资
col sal format $999,999,999.00
select empno,enmae,sal from scott.emp;

--使用heading选项把emp表中的字段换为中文
col empno heading 雇员编号
col ename heading 雇员姓名
col sal heading 雇员工资
select empno,ename,sal from scott.emp;

--使用null选项把emp表中comm值为null显示为‘空值’字符串
col comm null '空值'
select empno,ename,comm
from scott.emp
where comm is null;

ttltle和btitle命令
ttitle 设置打印时每页顶部的标题
btitle 。。。。。。底部。。。

set linesize 100;
set pagesize 25;
ttitleleft 'Monthly Analysis' center '10 March 2014'
right 'Page:' Format 999 SQL.PNO skip center
'employee report' skip 2;
setunderline=
btitle skip 2 left 'corporate planning departemnt right
'company confidential';
select * from scott.emp;
ttitle off;
btitle off;

用户模式

模式与模式对象

模式为一个数据库用户所有,并且具有与该用户相同的名称,比如,system模式,scott模式。
在一个模式内部不可以直接访问其他模式的数据库对象。

检索数据

简单查询

--检查所有的列
select * from emp;

--检查指定的列
select ename from emp;

--带有表达式的select的子句
select sal,sal*1.5 from emp;

--为列指定别名
select ename as 员工姓名,job as "职务" from emp;
select ename 员工姓名,job,职务,from emp;

--显示不重复记录
select distinct job from emp;

筛选查询

比较筛选: = ,>, <, <>, !, >=, <=

--显示工资大于1500的员工信息
select ename,job,sal from emp where sal>1500;

--显示job不是‘president’,‘manager’的员工信息
select ename,job,sal from emp where job not in
('PRESIDENT','MANAGER');

--按照部门分组,统计部门平均工资,找出平均工资大于2000的部门,结果按工资降序排序。
select deptno,avg(sal) 平均工资
from emp
group by deptno having avg(sal)>2000
order by avg(sal)
desc;

--显示工资在2000到3000之间的员工信息
select ename,job,sal 
from emp 
where sal between 2000 and 3000;

--显示没有奖金的员工信息
select ename,job,sal,comm
from emp
where comm is null;

--逻辑筛选and|or|not 
--显示工资在2000到3000之间的员工信息
select ename,job,sal
from emp
where sal>=2000 and sal<=3000;

--如何显示所有员工中最高工资和最低工资
select max(sal),min(sal) from emp;

分组查询和排序查询

select min(sal),avg(sal),deptno,job 
from emp group
by deptno,job
order by deptno,job;

聚合类函数

select deptno,avg(sal) 平均工资 from emp
group by deptno
order by avg(sal)
desc;

多表关联查询

内连接:inner join
外连接:left join | right join | full join
自然连接: natural join
交叉连接 cross join
自连接:
--内连接
select empno,ename,job,dname
from emp inner join dept
on emp.deptno=dept.deptno;

--在外连接之前向emp表中添加一条数据
insert into emp values(8000,'Tom','manager',7839,to_date
('1986-10-5','YYYY-MM-DD'),2500,NULL,NULL);
--在外连接之前向dept表中添加一条数据
insert into dept values(50,'PLAN','London');

--left join
select empno,ename,job,dname
from emp left join dept
on emp.deptno=dept.deptno;

--right join
select empno,ename,job,dname
from emp right join dept
on emp.deptno=dept.deptno;

--full join
select empno,ename,job,dname
from emp full join dept
on emp.deptno=denpt.deptno;

--natural join
select empno,ename,job,dname
from emp natural join dept
where sal>2000;

--自连接:查询所有管理者所管理的下属员工信息
select manager.ename LEADER,employee.ename CLERK
from emp manager 
inner join emp employee 
on manager.empno=employee.mgr
order by manager.empno;

--cross join
select count(*) from dept cross
join emp;

Oracle常用系统函数

字符类函数

--initcap函数,将每个单词的第一个字母大写
select initcap('oh my god')
information from dual;

省略xxx

数字类函数

ABS(n)返回n的绝对值
CEIL(n)返回大与或等于n的最小整数
cos 返回n的余弦值
exp 返回e的n次幂
florr 返回小于或等于n的最大整数
log(n1,n2)返回以n1为底,n2的对数
mod(n1,n2) 返回n1除以n2的余数
power(n1,n2) 返回n1的n2次方
round(n1,n2) 返回舍入小数点右边n2位的n1的值,n2的默认为0。
sign(n) 若n为负数,则返回-1,若n为正数,返回1,若n=0,返回0
sin(n)返回正弦值
sqrt(n)返回n的平方根,n为弧度
trunc(n) 返回结尾到n2位小数的n1的值,n2默认设置为0,当n2默认设置时,会将n1截尾为整数,如果n2为负值,就截尾在小数点左边相应的位上
select ceil(7),ceil(7.3),ceil(-7.3) from dual;
-- 7 8 -7

select floor(7),floor(7.3),floor(-7.3) from dual;
--7   7    -8

select power(2,3) from dual;
-- 8

select round(3526.82) sal from dual;
select round(3526.82,1) sal from dual;
select round(3526.82,2) sal from dual;
select round(3526.82,-1) sal from dual;
-- 3527  3526.8  3526.82  3530

select trunc(3526.82) sal from dual;
select trunc(3526.82,1) sal from dual;
select trunc(3526.82,2) sal from dual;
select trunc(3526.82,-1) sal from dual;
-- 3527  3526.8  3526.82  3530

日期和时间类函数

--sysdate()的返回值是date类型
--日期格式由当前会话NLS_DATE_FORMAT参数设定
select sysdate 系统日期 from dual;
alter session set NLS_DATE_FORMAT 'MM-DD-YYYY HH24:MI:SS'
select sysdate from dual;

转换类函数

select to_char(sysdate,'yyyy-mm-dd') 系统日期 from dual;
select to_char(sysdate,'yyyy-mm-dd HH24:MI:SS') "NOW" 
from dual; 


--显示每个雇员的年工资,注意需要使用nvl()函数来处理null值
select sal*13 + nvl(comm,0)*13 "年薪", ename,comm from emp;

子查询的用法

什么是子查询subquery

在sql语句内的另外一条select语句,也被称为内查询或内select语句

单行子查询

返回一行数据

示例:

--显示emp表中工资最高的人员信息
select ename,sal from emp
where sal=(select max(sal) from emp);

--显示与SMITH同部门的所有员工
select * from emp
where deptno = 
(select deptno from emp
where ename = "SMITH");

多行子查询

返回多行数据,使用比较符号in,any,all

--查询和部门10的工作相同的雇员的名字,岗位,工资,部门号
select * from emp
where job in
(select distinct job from emp
where deptno =10);

--显示工资比部门30的所有员工的工资高的员工的姓名,工资和部门号
select ename,sal,deptno
from emp
where sal > all
(select sal from emp
where deptno = 30);
--使用max方法查询:
select ename,sal,deptno
from emp
where sal > 
(select max(sal) from emp
where deptno =30);

--显示工资比部门30的任意一个员工的工资高的员工姓名,工资和部门号
select ename,sal,deptno
from emp where sal > any
(select sal from emp where deptno=30);
--使用min
select ename,sal,deptno
from emp where sal > (select min(sal)
from emp where deptno=30);

多列子查询

返回多个列数据的子查询语句

--查询与SMITH的部门和岗位完全相同的所有雇员
select * from emp 
where (deptno,job) =
(select deptno,job from emp
where ename = 'SMITH');

--查询与SCOTT的岗位和工资完全相同的雇员
select * from emp
where (job,sal) = (
select job,sal from emp
where ename = "SCOTT");
--显示高于自己部门平均工资的员工的信息
--1 查出各个部门的平均工资和部门号
select deptno,avg(sal) salavg from emp
group by deptno;
--2 把上面的查询结果看作是一张子表
select e.ename,e.deptno,e.sal,ds.salavg
from emp e,
(select deptno,avg(sal) salavg from emp group by deptno) ds
where e.deptno = ds.deptno and e.sal > ds.salavg;

关联子查询

--显示工资高于同职位平均工资的员工的信息
select empno,ename,sal
from emp e
where sal > 
(select sal(avg) from emp where job = e.job);

--使用内嵌视图
select empno,ename,sal
from emp e,
(select job,avg(sal) salavg from emp
group by job) js
where emp.job=js.job and e.sal > js.salavg
order by sal;

操作数据库

插入数据

--根据emp表创建一个新表
create table emp2 as (select * from emp);

--向emp表插入一条数据
insert into emp
values(7935,'TOM','CLERK',7782,to_date('1988-10-30','yyyy-mm-dd'),1000,0,10);

--向dept表中插入一条数据
insert into dept(deptno,dname,loc)
values(50,'PLANNING','BEIJING');

更新数据

--上调emp表中销售员(salesman)的工资 20%
update emp2 set sal=sal*1.2
where job='SALESMAN';

删除数据

--删除emp表中empno = 7369的员工的信息
delete from emp2 where empno = 7369

--删除表中所有的记录
truncate table emp;

PL/SQL编程语言基础

基础

--结构
declare xxx --声明部分,声明变量,常量,数据类型,游标,异常处理名称
begin xxx --可执行部分,
--通过变量赋值,流程控制,数据查询,数据操纵,数据定义,事物控制,游标处理等实现块的功能
exception xxx --处理执行过程中产生的异常
end;--使用/符号执行结构

分类:

  • 匿名块:动态生成,执行一次,不能由其他应用程序调用

  • 命名块:一次编译可多次执行的PL/SQL程序,包括函数,存储过程,包,触发器等。

词法单元

  • 字符集:大小写字母,数字,非显示字符,数字符号,标点符号
    *不区分大小写,除由单引号引起来的字符串和格式化后的日期

  • 标识符:用于定义变量,常量,异常,游标,名称,游标变量,参数,子程序名称和其他程序单元名称

  • 分割符:指有特定含义的单个符号或组合符号

  • 常量值
    字符型:区分大小写
    数字型:整数,实数
    布尔型:true,false,null
    日期型:表示日期值

--数字类型
number 
--字符类型
varchar2
char
--日期类型
date
timestamp
--行标识符类型
rowid
--布尔类型
boolean(true,false,null)
--lob类型
clob
blob
nclob
bfile
--引用类型
ref cursor
ref object_type
--记录类型
record
--集合类型
table
varray

变量与常量的定义

1 每行只能定义一个变量
2 constant表示常量,必须赋初值
3 使用not null的时候,必须赋初值
4 没有赋初值,则默认为null
5 使用default或是":="为变量初始化
declare
    v1 number(4);
    v2 number(4):=2;
    v3 number(4) not null :=3;
    c4 constant number(4) default 4;
begin
    dbms_output.put_line('v1:'||v1);
    dbms_output.put_line('v2:'||v2);
    dbms_output.put_line('v3:'||v3);
    dbms_output.put_line('v4:'||v4);
end;
*注意设置 set serveroutput on

SQL语句:
select xxx into
查询1个字段或是多个字段信息,结果存储在某一种数据类型变量中

--查询员工号为109的员工所在部门的平均工资
--借助变量传递
select department_id into v_deptno
from hr.employees
where employee_id=109;
select avg(sal) into v_sal
from hr.employees 
where department_id = v_deptno;
--嵌套结构
declare
    v_sal number(8,2);
    v_deptno number(4);
begin
    begin
        select department_id into v_deptno
        from hr.employees where employee_id = 109;
    end;
    select avg(salary) into v_sal
    from hr.employees
    where department_id=v_deptno;
    dbms_output.put_line(v_sal);
end;
--使用子查询
declare
    v_sal number(8,2);
begin
    select avg(sal) into v_sal
    from hr.employees
    where department_id = 
    (select department_id from employees
    where empoyee_id=109);
    dbms_output.put_line(v_sal);
end;


--查询员工号为109的员工的first_name,存储变量到v_fname中并输出。
declare
    v_fname varchar2(10);
begin
    select firstname into v_fname
    from hr.employees
    where employee_id=109;
    dbms_output.put_line(v_name);
exception
    when no_data_found then
    dbms_output.put_line('There is not such an employee');


--查询员工号为109员工的副irstname和工资分别存储到变量v_name,v_sal中,并输出
declare 
    v_name hr.employee.first_name%type;
    v_sal hr.employee.sal%type;
begin
    select first_name,salary into v_name,v_sal
    from hr.employees
    where employee_id = 109;
    dbms_output.put_line("first name:"||v_name||" Salary:"||v_sal);
exception
    when no_data_found then
    dbms_output.put_line("There is no such an employee");
end;
  • 记录类型 record

包含若干个成员分量的复合类型,需要先生命部分定义,然后在执行部分引用


--查询员工号为109的员工的first_name和salary,存储在记录变量中并输出
declare
    type emp_record is record
    (
        v_name hr.employees.first_name%type,
        v_sal hr.employees.sal%type
    );
    empinfo emp_record;
begin
    select first_name,sal into empinfo
    from hr.employees
    where employee_id=109;
    dbms_output.put_line();
    dbms_output.put_line("first name:"||v_name||" Salary:"||v_sal);
exception
    when no_data_found then
    dbms_output.put_line("There is no such an employee");
end;
  • %rowtype

    定义一个与数据库中某个表结构一致的记录类型的变量
    ** 变量的类型 会随着 表的变化 而变化
    ** 如果数据库列表中有not null,则 %rowtype返回的数据类型没有这个限制

--查询员工号为109的员工的所有信息,存储在rowtype类型变量中,输出first_name和salary中
declare 
    v_emp hr.employees%rowtype;
begin
    select * into v_emp
    from hr.employees
    where employee_id =  109;
    dbms_output.put_line('first name:'||v_emp.first_name||',salary:'||v_emp.salary);
end;
  • 使用&x变量在运行时提示输入实际值
declare
    v_empno hr.employees.employee_id%type;
    v_fname hr.employees.first_name%type;
begin
    v_empno := &x;
    select first_name into v_fname
    from hr.employees
    where employee_id = v_empno;
    dbms_output.put_line(v_empno||''||v_fname);
end;

控制结构

  • 选择
if    
elsif    
else           
end if

--输入一个员工号,修改该员工的工资,如果该员工为10号部门,则工资增加100;若为20号,则增加150;若为30,则增加200,否则增加300

declare
    v_empno hr.employees.employee_id%type;
    v_deptno hr.employees.department_id%type;
    v_increment number(4);
begin
    v_empno := &x;
    select department_id into v_deptno
    from hr.employees
    where employee_id = v_empno;

    if v_deptno = 10 then v_increment:=100;
    elsif v_deptno = 20 then v_increment := 150;
    eleif v_deptno = 30 then v_increment := 200;
    else v_increment:=300;
    end if;
    update hr.employees set salary = salary+v_increment
    where employee_id = v_empno;
end;
case
    when  then
    when  then
end case;

--根据输入的员工号,修改该员工的工资
declare
    v_empno hr.employees.employee_id%type;
    v_sal hr.employees.sal%type;
    v_increment number(4);
begin
    v_empno := &x;
    select salary into v_sal from hr.employees
    where employee_id = v_empno;

    case
        when v_sal < 1000 then v_increment := 200;
        when v_sal < 2000 then v_increment := 150;
        when v_sal < 3000 then v_increment := 100;
        ele v_increment:=50;
    end case;
    update hr.employees set salary = salary+v_increment
    where employee_id = v_empno;
end;

循环结构

Loop循环

Loop
    sequence_of_statement;
    exit[when condition];
end loop;

--利用loop循环求1-100之间偶数的和
declare
    v_counter number(3) := 1;
    v_sum number:=0;
begin
    loop
        if mod(v_counter,2)=0 
        then v_sum:=v_sum+v_counter;
        end if;

        v_counter := v_counter +1;
        exit when v_counter >100;
    end loop;
    dbms_output.put_line(v_sum);
end;

while 循环

while conditon loop
    sequence_of_statement;
end loop;

-- 
declare
    v_counter number(3) := 2;
    v_sum number := 0;
begin
    while v_counter <= 100 loop
    v_sum := v_counter+v_sum;
    v_counter := v_counter +2;
    end loop;
end;

for 循环

for loop_counter in low..high
loop
    sequence_of_statement
end loop;

--
declare
    v_sum number := 0;
begin
    for v_counter in 1..100
    loop
        if mod(v_counter,2)=0
        then v_sum +=v_sum+v_counter;
        end if;
    end loop;
    dbms_output.put_line(v_sum);
end;

游标(Cursor)

游标是oracle系统在内存中开辟的一个工作区,可以存放select语句返回的查询结果,可以是单条,也可以是多条,也可以是零条。
游标工作区中,存在一个指针(pointer),在初始状态,它指向查询结果的首记录。

  • 显式游标
    由用户定义和操作,用于处理返回多行数据的select查询

  • 隐式游标
    由系统自动进行操作,用于处理dml语句和返回单行数据的select查询

步骤:

定义游标 cursor name is select_statement;
打开游标 open name;
检索游标 fetch name into var_list|record_var;
关闭游标 close cursor_name;

显式游标

显式游标属性

%isopen 布尔型:如果游标已经打开返回true,否则为false
%found 布尔型:如果最近一次使用fetch,有返回结果则true
%notfound 布尔型:如果最近一次使用fetch, 没有返回结果则true
%rowcount 数值型:返回到目前为止,从游标缓冲区检索的元组数
--使用hr.employees表,设计一个游标,根据输入的部门号查询某个部门的员工信息,部门号在程序运行时指定
alter user hr account unlock;
password hr

conn hr

declare
    v_deptno hr.employees.department_id%type;
    cursor cur_emp is
        select * from hr.employees
        when department_id = v_deptno;
    v_emp curemp%rowtype;
begin
    v_deptno := &x;
    open cur_emp;
    loop
        fetch cur_emp into v_emp;
        exit when cur_emp%notfound;
        dbms_output.put_line(v_emp.employee_id||' '||v_emp.first_name||' '||v_emp.last_name||' '||v_emp.salary||' '||v_deptno);
    end loop;
    close cur_emp;
end;

--利用简单循环统计并输出各个部门的平均工资
declare
    cursor cur_sal is
    select departement_id,avg(sal) from hr.employees
    group by department_id;
    v_dept cur_sal%rowtype;
begin
    open cur_sal;
    loop
        fetch cur_sal into v_dept;
        exit when cur_sal%notfound;
        dbms_output.put_line(
        v_dept.department_id||':'||
        round(v_dept.avgsal,2));
    end loop
    close cur_sal;
end;

--利用while循环统计并输出各个部门的平均工资
declare
    cursor cur_sal is
    select department_id,avg(salary) from hr.employees
    group by department_id;
    v_dept cur_sal%rowtype;
begin
    open cur_sal;
    fetch cur_sal into v_dept;
    while cur_sal%found
    loop
        dbms_output.put_line(...);
        fetch cur_sal into v_dept;
    end loop;
    close cur_sal;
end;

--利用for循环统计输出各个部门的平均工资
declare
    cursor cur_sal is
    select departement_id,avg(salary) from employees
    group by department_id;

begin
    open cur_sal;
    for v_dept in cur_sal loop
        dbms_output.put_line(...);
    end loop;
end;
--由于用for循环检索游标的时候,游标的打开,数据的检索,是否检索到数据的判断
--以及游标的关闭都是自动进行的,因此
--**可以不再生命部分定义游标,而在for语句中直接使用子查询

隐式游标

也称为SQL游标,主要处理insert,update,delete以及单行的select into 语句
没有open,fetch,close等操作命令

隐式游标属性和显示一致

SQL%isopen
SQL%FOUND
SQL%NOTFOUND
SQL%ROWCOUNT
--提示输入员工号,然后修改该员工的工资,将其工资增加100,如果该员工不存在,则提示。如果员工存在,则输出其first_name和更新后的salary
declare
    v_empno employees.employee_id%type;
    v_fname employees.first_name%type;
    v_sal employees.first_name%type;
begin
    v_empno := &x;
    update hr.employees set salary = salary + 100
    where employee_id = v_empno;
    if SQL%NOTFOUND then
        dbms_output.put_line("没有雇员需要上调工资");
    else
        select first_name,salary into v_fname,v_sal
        from hr.employees
        where employee_id = v_empno;
        dbms_output.put_line();
    end if;
end;

--提示输入员工号,然后修改该员工工资
--将其工资增加100
--如果该员工不存在,则向employees表中插入一个员工号为1000,工资为1500的员工。
--如果员工存在,则输出其first_name和更新后的salary
delcare
    v_empno hr.employees.employee_id%type;
    v_fname hr.employees.first_name%type;
    v sal hr.employees.salary%type;
begin
    v_empno := &x;
    update employees set salary = salary +100
    where employee_id = v_empno;
    if sql%notfound then
        insert into employees(employee_id,salary)
        value(1000,1500);
    else
        select first_name,salary into v_fname,v_sal
        dbm_output.put_line();
    end if;
end;

过程

alter user hr account unlock;
password hr

set serverouput on;

show error
--创建存储过程
create or replace procedure procedure_name
(parameter1,parameter2...)
as/is
begin
exception
end;

--删除存储过程
drop procedure proc_name;

--创建存储过程,以部门号为参数,查询该部门的平均工资,并输出该部门中比平均工资高的员工号,员工名
create or replace procedure pro_avgsal(
    p_deptno employees.departement_id%type)
as
    v_sal employees.salary%type
begin
    select avg(salary) into v_sal from employees
    where department_id = p_deptno;
    dbms_output.put_line(p_deptno||' '||'average salary is: '||v_sal);

    for v_emp in (select * from employee
    where department_id = p_deptno and salary > v_sal)
    loop dbms_output.put_line();
    end loop;
exception
end;

exec pro_avgsal(100);

--创建一个存储过程
--通过部门编号查询该部门的总人数和平均工资
create or replace procedure pro_dept(
    p_dept employee.department%type,
    p_avgsal out employees.salary%type,
    p_count out number)
as
begin
    select avg(salary),count(*) into p_avgsal,p_coutn
    from employee
    where department_id = p_dept;
excetion
    when no_data_found then
    dbsm_output.put_line('the department don't exists');
end;

--调用
var v_avgsal number;
var v_count number;
exec pro_dept(100,:v_avgsal,:v_count);
print v_avgsal v_count

declare
    v_avgsal employees.salary%type;
    v_count number(2);
begin
    pro_dept(100,v_avgsal,v_count);
    dbms_output.put_line();
end;


--创建一个存储过程,通过员工名称查询员工工资,如果员工工资低于2000,则按百分比提高员工工资。
create or replace procedure pro_sal(
    p_name emp.ename%type,
    p_percent number)
is
    v_sal emp.sal%type;
begin
    select salary into v_sal from employees
    where ename=p_name;

    if v_sal < 2000 then
    update employee set sal = sal *(1+p_percent)
    where ename=p_name;
    end if;
end;

exec('Lucy',0.20)


--创建名为“proc_secure_dml”的存储过程,检查当前用户操作时间是否为工作时间,即非周六,周日,并且时间为8:00-18:00
create or replace pro_secure_dml
is
begin
    if to_char(sysdate,'hh24:mi') 
    not between '08:00' and '18:00' 
    or to_char(sysdate,'dy','nls_date_language=american')
    in ('sat','sun')
    then 
        raise_application_error(-20205,'只能在正常的工作时间内进行改变');
    end if;
end pro_secure_dml

函数

create or replace function function_name(parameter)
return return_datatype
as/is
begin
exception
end function_name;

函数可以在sql语句的以下部分调用

select语句的目标列
where和having子句
connect by,start with, order by, group by子句
insert 语句的values子句中
update语句的set子句
--创建名为‘Func_emp_salary’的函数,以员工编号为参数,返回员工的工资
create or replace function func_emp_salary(
    f_empno employees.employee_id%type)
return employees.salary%type
as
    v_sal employees.salary%type
begin
    select salary into v_sal 
    from employees
    where employee_id = f_empno;
    return v_sal;
exception
    when no_data_found then
    raise_application_error(-20000,'there is not such an employee!);
end;
--调用
declare
    v_salary employees.salary%type;
begin
    v_salary:=func_emp_salary(100);
    dbms_output.put_line();
edn;

--创建函数,以员工编号为参数,返回该员工所在部门的平均工资
create or replace function func_dept_avg_sal(
    f_empno employees.employee_id%type)
return employees.salary%type
as
    v_avgsal employees.salary%type;
    v_depno employees.department_id%type;
begin
    select department_id into v_depno
    from employees
    where employee_id=f_empno;
    select avg(salary) into v_avgsal
    from employees
    where department_id = v_depno;
    return v_avgsal;
exception
    when no_data_found then
    raise_application_error(-2000,'there is not such an employee!');
end;
--调用func_emp_dept_avgsal函数
declare
    v_avgsalary employees.salary%type;
begin
    v_avgsalary := func_emp_dept_avgsal(100);
    dbms_output.put_line('salar'||v_avgsalar);
end;


--删除函数
drop function fun_name;

包是包含了一个或是多个子程序单元(过程,函数等)的容器

create or replace package package_name
is/as
end;

--创建一个软件包,包括2个变量,2个过程和1个异常
create or replace package pkg_emp
as 
    minsal number;
    maxsal number;
    e_beyongbound exception;
    procedure update_sal(
        p_empno number,p_sal number);
    procedure add_employee(
        p_empno number,p_sal number);
end;

--创建包体
create or replace package body pkg_mep
as 
    procedure update_sal()
    xxx
    end update;
    procedure add_employee()
    xxx
    end add_employee;
end pakg_emp;
--调用
begin
    pkg_emp.update_sal(150,8000);
    pkg_emp.add_employee(2011,9000);
end;

触发器

触发器是一种特殊类型的存储过程,编译后存储在数据库服务器中
当特定事件发生的时候,由系统自动调用执行
用于维护那些通过创建表时的生命约束不坑实现的复杂的完整性约束,并对数据库中特定时间进行监控和相应。

语句级触发器

针对一条dml语句而引起的触发器执行
*不使用for each row子句,无论数据操作影响多少行,触发器只会执行一次

行级别触发器
针对dml操作所影响的每一行数据都执行一次触发器
创建这种触发器的时候,必须在语法中使用for each row这个选项

替换触发器

instead of
与其他类型触发器不同的是,替换触发器定义在试图(view)上的,而不是定义在表上。
视图:多个基表连接组成的逻辑结果,一般不允许用户进行dml操作
通过替换触发器中编写适当的代码对视图进行操作

用户事件触发器

因进行ddl操作或是用户登录,退出等操作而引起运行的一种触发器

触发器的组成

触发器头部:
    作用对象:表,视图,数据,模式
    触发事件:激发触发器执行的事件
    触发时间:after,先执行事件;before,先执行触发器
触发器体

执行顺序:

(1)如果存在,则执行语句级前触发器
(2)对于受触发事件影响的每一条记录
    如果存在,则执行行级前触发器
    执行当前记录的触发事件
    如果存在,则执行行级后触发器
(3)如果存在,则执行语句级后触发器
--创建触发器,保证非工作时间禁止对employees表进行dml操作
create or replace trigger trg_secure_mep
before insert or update or delete
on employees
begin
if toxxx
end if;
end trg_secure_emp;

--执行
update employees set salary = salary-10;


--为employees表创建一个触发器
当执行插入操作时,统计操作后员工人数
当执行更新员工工资操作时,统计更新后员工平均工资
当执行删除员工操作时,统计删除后各个部门的员工人数
create or replace trigger trg_emp_dml
after insert or update or delete on employees
declare
    v_count number;
    v_sal number(6,2);
begin
    if inserting then
        select count(*) into v_count from employees;
        dbms_output.put_line();
    elsif updating then
        xxx
    elsif deleting then
        xxx
    end if;
end trg_emp_dml;

--行级别触发器,要加上
for each row

数据表

创建表

--创建学生信息表,该表包括了学生编号,学生姓名,性别,年龄,系统编号,班级编号,建档日期等信息
create table students
(
    stuid number(10) primary key,
    sname varchar2(8),
    sex char(2),
    age number(3),
    departno varchar2(2) not null,
    classno carchar2(4) not null,
    registerdate date default sysdate
);

--创建班级表,该表包括了班级编号,班级名称
create table classz
(
    classno varchar2(4) primary key,
    classname varchar2(10) unique
);

数据完整性和约束性

primary key 主键约束
not null 非空约束
unique 唯一性约束
foreign key 外键约束
check 范围约束
--主键约束
constraint stu_pk primary key
constraint stu_pk priamry key(stuid)

--唯一性约束
constrain classz_un unique
constrain classz_un unique(classname)

--外键约束
constraint stu_fk foreign key(classno)
references classz(classno)

--check约束
check(age between 17 and 50),
check(sex in('man','women')),

--alter table 添加约束
--add
alter table classz add constraint stu_pk primary key(classno)
--modify
alter table students modify sex no null;
--drop 删除
alter table classz drop constraint stu(约束名称);

--disable 禁用 enable 恢复
alter table students disable constraint gender_ck;

--删除表
drop

--更新表
update

用户管理与权限分配

create user tom identified by m123;

alter user tom account unlock;

drop user tom; --删除


--授权

grant create session to tom;
grant create session,create table to tom;

--导入导出
grant exp_full_database,imp_full_database to tom;

你可能感兴趣的:(SQL实践)