1. 书写代码时,先把要书写的格式写出来,然后往内部填充内容,能降低代码的报错率。
2. 通过 :=& 这种弹框手动录入数据时,如果输入的是字符串时需要加单引号
3. 不能够通过循环来多次弹框录入数据,Oracle不支持(因为实际应用中不存在这种录入数据的情况)。
4. 注意书写存储过程中,传递的参数不要与数据库表中的列名一样,否则sql语句的执行会与预期的不同,并且很难找出原因
5. 在存储id主键数据时,如果在下面的sql语句中两张表内都用到了同一个id,这时,这个id需要从调用的地方生成并且传递过去,不能在sql执行的时候插入生成。
6. 语句报错时,大都是语法格式问题,查看分号是否少写,是否多写。
7. 一些语法区别要注意:如oracle的分支if有三种,有区别的就是if 条件 then elsif 条件 then else end if;
8.函数和存储过程很相似,但是存储过程主要用来书写业务逻辑,只为一个业务服务,里面写的时增删改查;
函数一般书写工具,在select中可以使用。
PL/SQL语法:
A. 匿名代码块:
declare
声明:数据类型、变量、常量(constant)、异常——⾃定义异常、游标
begin
代码块:核⼼代码基本都是sql语句。
exception
异常处理
end;
B. 赋值:在declare中 直接赋值 变量名:=值; 输入框赋值 变量名 :=&随便名字;
获取数据类型:在declare中 表名.列名%type:获取对应表的对应的列的数据类型;表名%rowtype:获取对应表的⼀⾏的数据类型。
C. 数据类型声明 record table:注意在代码块内声明和独立声明的赋值区别:
D. 分支if有三种:
1、Loopendloop⽤法
loop 循环体 循环变量更替 exit;显示退出——对应循环条件 end loop;
2、Whileloopendloop⽤法
while 条件 loop 循环体 循环变量更替 end loop;
3、Forinloopendloop⽤法;
for 变量名 in 1..结束的数字 loop 循环体 end loop;
与java等有区别的就是if 条件 then elsif 条件 then else end if;
E. 条件控制case:
case when 表达式 then 语句;when 条件 then 语句; end case;
case 表达式 when 常量1 then 语句 when 常量2 then 语句; endcase;
F. 异常处理 exception
when 异常名称 then 异常处理
when 异常名称 then 异常处理
when others then
自定义异常:
declare中声明⾃定义异常
名称 exception;
begin中抛出异常
raise 异常名称;
exception中接收,处理异常
when 异常名称 then 异常处理
G. 子程序即有名字的明明块即存储过程的创建
create [or replace] procedure 存储过程名称 (接受参数和返回参数名称【in、out、inout】数据类型)
is/as
声明:=&e;
begin
代码
exception
异常
end;
调用形式:
--1:call 存储过程名称(有参数的传递参数);
--2.直接代码块调用 在begin的代码块中直接写存储过程名称(有参数的传递参数);
--3.黑窗口调用
setserveroutputon;--开始控制台输出
Execpro_query_dept;--再用exec去执行
--4.直接在存储过程上右击:test测试
H. 函数
如果⼀个功能有多个返回值:⽤存储过程
只有单⼀返回值的情况下采⽤函数
函数必须有return
create [or replace] function 函数名称 (接受参数 数据类型) return 数据类型
is/as
声明:=&e;
begin
代码;
return 数据(返回类型的数据);
end;
I. 包:
包规范: —类似于接⼝。⾥边都是存储过程或者函数的定义变量。
—共有的。可以通过包名.函数名或者存储过程名进⾏调⽤。
包体 —类似接⼝的实现类。⾥边可以对共有的函数和存储过程进⾏实现。
可以书写宝规范中没有定义的存储过程、函数或者变量。在此处定义称之为私有的。只能在本包使⽤。外部不能调⽤
create or replace package 包名
声明
end 包名;
create or replace package body 包名
包规范中的具体实现——包名.函数名或者存储过程名进⾏调⽤以及私有的定义和实现——外部不能调⽤
end 包名;
J. 游标
显式游标使⽤
声明游标:cursor 游标名 is 查询语句;
打开游标:open cursor名称;
loop
读取数据--每⼀次都只能读取⼀⾏,所以在循环中书写。
fetch 游标名 into 变量名;变量名的数据类型根据查询语句来决定
exit when 游标名%notfound;
end loop;
关闭游标:close 游标名
显式游标属性:
%notfound:没有读取到数据
%found:读取到数据
%ISOPEN:判断是否打开
%ROWCOUNt:遍历到第⼏⾏
for循环的简便写法
declare
v_emp emp%rowtype;
begin
for v_emp in (select * from emp)
loop
dbms_output.put_line(v_emp.ename);
end loop;
end;
动态游标
declare
声明动态游标的数据类型:type 动态游标数据类型名 is ref cursor;
声明游标 游标名 动态游标数据类型名 ;
begin
open 游标名 for sql语句;
etch读取:loop遍历
close 游标名
end;
动态游标,返回结果集合
create or replace procedure getEmp(emps out sys_refcursor)
is
v_sql varchar2(200);
begin
v_sql:='select * from emp';
open emps for v_sql;
end;
隐含游标-没有声明,执⾏增删改以及select into会⾃动打开⼀个隐式游标,并且游标名统⼀都为
sql
K. 触发器
DML触发器
在对数据库表进⾏DML操作时触发,并且可以对每⾏或者语句操作上进⾏触发。
增删改没有查
⾏级:每涉及⼀条记录,触发⼀次,可以获取修改前和修改后数据
表级:⽆论执⾏语句涉及⼏条结果集合,只触发⼀次。⽆法获取修改前数据和修改后数据。
触发器组成:
Ø 触发事件
DML或DDL语句。//增删改
Ø 触发时间
是在触发事件发⽣之前(before)还是之后(after)触发
备份:之后
阻断:之前
Ø 触发操作
使⽤PL/SQL块进⾏相应的数据库操作(核⼼操作)
Ø 触发对象
表、视图、模式、数据库
Ø 触发频率
触发器内定义的动作被执⾏的次数。
语法说明
create or replace trigger 触发器名称
after/before
insert or update or delete [of 列名] on 表名
[
for each row--⾏级触发器;不写是⼀个表级触发器
when(条件)
]
begin
end;