1.事务: 一系列连续操作,不可分割,要不全部成功,全部失败
-- 事务结果: 一个: 成功或失败
--特征: A(原子性) C(一致性) I(个理性) D(持续性)
--有2个经典关键词: commit(提交) rollback (回滚)
函数和存储过程的区别:标识符不同;函数值有返回值,过程没有;函数在sql语句中可以直接调用,而过程不能直接调用。
insert into stu(id, age) values(100,123);
commit;
rollback;
transcation 事务
--设置事务保存点,实现回到一个时刻
--设置保存点 savepoint 保存点名字
savepoint a;
insert into stu values(1,1);
insert into stu values(2,2);
savepoint b;
update stu
set id=3
where id=2;
--还原
rollback to a;
--保存点可以建立多个,可以回到任意一个保存点
--小结: 如何创建保存点 : savepoint 保存点名
-- 提交或回滚 commit rollback to 保存点名
-- 事务提交前可以做任意更改,但是若双方对同一个对象执行操作,则会锁定 ,必须等提交或回滚以解锁
2.--隔离级别:
--一个事务同其他事务隔离的程度
--Oracle支持2种: read committed (读取已提交事务) serialziable (串行化)
--为何要有隔离级别: 为了避免并发访问问题: 1)脏读(读了未提交数据) 2)不可重复读(每次可以读取到不相同数据) 3)幻读(插入新行,读取新行数据
--如何设置Oracle隔离级别
--设置为读取已提交
--1. 开启一个事务T1,设置隔离级别叫读取已提交
set transaction isolation level read committed;
--2.执行插入操作
insert into stu values(4,4);
--3.提交
commit;
--4.查看数据
select * from stu ;
3.--过程
--概念: 也叫存储过程,指存储在数据库中供所有用户程序调用的子程序 。
--优点: 它有名字,可以重复运行。 同时还可以提供运行时的参数
--创建过程的语法: create or replace procedure 过程名(参数名 参数类型 数据类型)
-- as/is
-- pl/sql程序
--参数类型(分类)有2种:
--输入参数: in
--输出参数: out
--举例: 建立一个过程,输出hello
create or replace procedure pro_1
as
begin
dbms_output.put_line('hello');
end;
--如何运行过程
--调用(execute)过程名即可
exec pro_1
--调用begin .. end;
begin
pro_1;
end;
--显示当前的系统时间,过程实现
create or replace procedure p1
as
begin
--以年月日显示时间
dbms_output.put_line('当前系统时间'||to_char(sysdate,'yyyy-MM-dd hh24:mi:ss'));
end;
exec p1;
--过程带参 ,通过传入指定的学生编号,年龄,插入数据到表。编写此过程,最后运行
create or replace procedure p2(s_id int,s_age int)
as
begin
--插入数据
insert into stu(id,age) values(s_id,s_age);
end;
--执行过程
exec p2(5,50);
--输出参数
--通过过程传入编号,年龄,统计表中有几条数据,输出数目
create or replace procedure p3(s_id int,s_age int,rnum out int) --此处若是其他类型,请注意不要写长度
is
rc int:=0;
begin
--插入数据
insert into stu(id,age) values(s_id,s_age);
commit;
select count(id) into rc from stu;
rnum:=rc;
end;
--运行
declare
rc int:=0;
begin
p3(6,6,rc);
--输出
dbms_output.put_line(rc);
end;
--过程小结:
--1.一般过程是没有返回值的
--2.若使用了in参数,值可以接收值,不能给它输出的值(不能当输出参数)
--3. 输出参数out指定,可以指定多个。
--补充: 函数
--概念:一段功能,必须返回值
--语法:create or replace function 函数名(参数名 参数类型 参数数据类型)
-- return 函数返回类型
-- as/is
-- pl/sql程序
--举例: 通过函数输出hello
create or replace function f1
return varchar
as
begin
--主体中最后必须要有return语句
return 'hello';
end;
--函数运行
declare
r varchar2(20);
begin
r:=f1();
dbms_output.put_line(r);
end;
--另外的运行的方式 select 语句
select f1()
from dual;
--带参函数 ,插入员工编号,得到员工薪水,通过函数实现
create or replace function f2(emp_no in number)
return emp.sal%type
as
--定义薪水
emp_sal emp.sal%type;
begin
select sal
into emp_sal
from emp
where empno=emp_no;
--返回薪水
return emp_sal;
end;
--调用
select f2(7499) from dual;
declare
emp_sal emp.sal%type;
begin
emp_sal:=f2(7499);
dbms_output.put_line(emp_sal);
end;
--得到表中的行数
create or replace function f4(emp_no number,rc out number)
return emp.sal%type
as
emp_sal emp.sal%type;
begin
select sal
into emp_sal
from emp
where empno=emp_no;
select count(*) into rc from emp;
return emp_sal;
end;
--运行
declare
rc number;
rc1 emp.sal%type;
begin
rc1:=f4(7499,rc);
dbms_output.put_line('函数的返回值:'||rc1);
dbms_output.put_line('输出参数的值:'||rc);
end;
--函数和过程比较: 相同点: 都可以带参,都可以是输入,输出参数
-- 不同点: 过程不带返回,函数必须返回
--触发器:
--概念: 是一段pl/sql程序,与表相关联,每当一个特定的dml语句在指定的表上发出时,
--Oracle会自动的执行触发器中定义的语句序列
--触发器类型: 1.语句触发器 2.行级触发器
--触发器的语法:
--create or replace trigger 触发器名
--before|after
--delete|insert|update [of [列名]]
--on 表名
--[for each row] --这是行级触发器的关键词
--pl/sql程序
--:old,:new 伪记录变量 (可以存储之前的值和之后的值 )
--表
所做操作 :old :new
insert 将要插入的新的数据行
update 更新前改行的值 更新后的值
delete 删除前该行的值
--举例:有 一张表,stu,4行数据,设计触发器,更新时显示4个hello
create or replace trigger tri_stu
before
update
on stu
--for each row
begin
--显示hello
dbms_output.put_line('hello');
end;
--如何测试
update stu
set age=23
where id=1;
/*
1. 声明一个变量I,初始值为1,再声明一个常量名为maxrecords,值为100.
假定有一张表,里面有id和currentdate两个字段,请编写pl/sql程序往表中插入100条数据。最后显示有100条记录已经插入。
*/
create table tb11
(id number,
currentdate date);
declare
i int:=1;
maxrecords constant int:=100;
begin
for i in 1..maxrecords loop
insert into tb11(id,currentdate) values(i,sysdate);
end loop;
--给个提示
dbms_output.put_line('成功录入');
--提交
commit;
end;
/*
2. 编写一个pl/sql程序块向emp表添加新雇员编号(7901-7910,其中empno字段为主键)
*/
declare
i int:=7901;
begin
loop
--先判断
if i=7902 then
i:=i+1;
else
insert into emp(empno) values(i);
i:=i+1;
end if;
--设计退出循环条件
exit when i>7910;
end loop;
dbms_output.put_line('插入成功');
end;
/*
3. 根据指定的id值,从students表中查询该生的专业信息,放入v_major变量中,再使用case命令判断,
如果其值为computer science
,则为他选择一门课程,名为cs101,放入v_coursename变量中,并输出结果。(表结构自行设计)
*/
declare
v_major students.major%type;
v_coursename students.coursename%type;
begin
select major,coursename
into v_major,v_coursename
from students
where id=1;
--选择课程
case v_major
when 'computer science' then
v_coursename:='cs101';
end case;
--给出提示
dbms_output.put_line(v_coursename);
end;
--4. 计算显示部门人数最多的部门号、人数、工资总和,以及部门人数最少的部门号、人数、工资总和
declare
max_deptno emp.deptno%type;
max_count number;
max_totalsal emp.sal%type;
begin
select deptno,personnumber,totalsal
into max_deptno,max_count,max_totalsal
from
(select deptno,count(*) personnumber, sum(sal+nvl(comm,0)) totalsal
from emp
group by deptno
order by personnumber desc
)
where rownum=1;
--输出
dbms_output.put_line('人数最多的部门号:'||max_deptno||'人数:'||max_count||'工资总和:'||max_totalsal);
end;
--2张表, tb_cust ,tb_orders
--tb_cust: id , cid ,cname
--tb_orders: id ,orderid, subscribedate, paymentdate, custid
create table tb_cust
(id int,
cid varchar2(20),
cname varchar2(20)
);
--要求:输入客户编号不存在,显示自定义错误消息ora-20001
-- raise_application_error
--付款日期在预定日期后
--pl/sql程序
declare
--定义行类型变量, tb_orders
v_orders tb_orders%rowtype;
begin
--给变量赋值
v_orders.custid:=&custid;
--此处要给预定日期和付款日期赋值
v_orders.SUBBSCRIBEDATE:='&SUBBSCRIBEDATE';
v_orders.PAYMENTDATE:='&PAYMENTDATE';
--对客户表执行更新操作
update tb_cust
set id=v_orders.custid
where id=v_orders.custid;
--若没有此客户编号
if sql%notfound then
--给出提示
raise_application_error(-20001,'请输入正确的客户编号');
return;
end if;
--付款日期在预定日期之后
if v_orders.PAYMENTDATE<v_orders.SUBBSCRIBEDATE then
--给出提示
raise_application_error(-20002,'交付日期必须子预定日期之后');
return;
end if;
end;