基本语法
declare
--声明
a int;
b int;
res int;
begin
--逻辑开始执行
a:=&a;--输入a赋给a
b:=&b;
res:= a+b;
dbms_output.put_line(res);
--输出到控制台
end;
--代码块的结束
在查看里打开DBMS输出再连接到用户,就可以看到结果了
如果在其中使用select语句为
select 表的列名 into 定义的变量名 from 表名 where
--意思是把选出的结果赋值给变量
如果变量类型是表的某列的的类型则
可声明为
name emp.ename%type;
如果是想要表的一行则
tmp emp%rowtype;
但输出时需要将自己想输出的选出来,不能直接写变量
declare
name emp.ename%type;
sal emp.sal%type;
tmp emp%rowtype;
begin
--逻辑开始执行
name:=&name;
select sal into sal from emp where ename=upper(name);
select * into tmp from emp where ename=upper(name);
dbms_output.put_line(sal);
dbms_output.put_line(tmp.ename||'---'||tmp.sal);
--输出到控制台
end;
注意输入的是字符串的时候需要自己写单引号
循环
loop
loop
循环内容
exit when 结束条件
循环内容
end loop
declare
x int;
e int;
begin
x:= 1;
e:= 5;
loop
dbms_output.put_line(x);
exit when x=e;
x:=x+1;
end loop;
end;
for
declare
(记得定义)
begin
for x in 1..10
loop
循环内容
end loop;
end
while
while x <=10
loop
循环内容
end loop;
分支 if....else
if 判断1 then 语句1;
elsif 判断2 then 语句2;
elsif 判断3 then 语句3;
else 语句4;
end if;
1编写一个程序··PLSQL·块
2向emp·表中插入10条数据
3员工编码·从·1000·开始·1000·1001-1002...·[序列]
4员工姓名·为·3-5位随机数值或字母组合,·姓名不能相同.......[GUID·截取字符串
5员工工作·从·emp·表中的·job·随机赋值,job·不能为·MANAGER·…·[随机数排序,伪列第一个]
6员工领导和部内编码,-根据·job·指定,·随机一个即可
7入职时间·为·10.-·20·年之间·
8薪资·为所在部内的·最低和最高之间··1000-3000.
9如果·job·为·SALESMAN·可以设置奖金,奖金为·公司最低和最高奖金之间
--序列
create sequence x_id
start with 1000
increment by 1
maxvalue 1010
nocache;
declare
s emp.sal%type;
b emp.sal%type;
tmp emp%rowtype;
x int;
begin
for x in 1..9
loop
--随机截取3-5个不一样的字符当名字
select substr(sys_guid(),10,trunc(dbms_random.value(3,5))) into tmp.ename from dual;
--随机选取职业
select job into tmp.job from
(select job from emp where job !='MANAGER' order by dbms_random.value(1,50))
where rownum =1 ;
select mgr into tmp.mgr from(select mgr from emp where emp.job=tmp.job order by dbms_random.value(1,50)) where rownum =1;
--部门号
select deptno into tmp.deptno from(select deptno from emp where emp.job=tmp.job order by dbms_random.value(1,50)) where rownum =1;--
select to_date(to_char(trunc(dbms_random.value(2014,2004)))||'-'||to_char(trunc(dbms_random.value(1,12)))||'-'||to_char(trunc(dbms_random.value(1,30))),'yyyy-mm-dd') into tmp.hiredate from dual;--8
select max(sal) into s from emp group by deptno having emp.deptno=tmp.deptno ;
select min(sal) into b from emp group by deptno having emp.deptno=tmp.deptno ;
select trunc(dbms_random.value(b,s)) into tmp.sal from dual;
select max(co) into s from (select max(comm) co from emp group by deptno) ;
select min(co) into b from (select min(comm) co from emp group by deptno) ;
if tmp.job='SALESMAN' then
select trunc(dbms_random.value(b,s)) into tmp.comm from dual;
else tmp.comm := NULL;
end if;
dbms_output.put_line( tmp.ename||'--'||tmp.job||'--'||tmp.mgr||'--'||tmp.hiredate||'--'||tmp.sal||'--'||tmp.comm||'--'||tmp.deptno);
insert into emp values(m_id.nextval,tmp.ename,tmp.job,tmp.mgr,tmp.hiredate,tmp.sal,tmp.comm,tmp.deptno);
end loop;
end;
游标
相当于指针,用fetch into把获取到的放到变量,要记得打开和关闭
declare
cursor mycur is select * from emp;
tmp emp%rowtype;
begin
open mycur;
fetch mycur into tmp;
dbms_output.put_line(tmp.ename);
close mycur;
end;
--用for来遍历数据集,默认自动打开游标
for tmp in mycur
loop
dbms_output.put_line(tmp.ename);
end loop;
游标的状态
NOTFOUND --如果FETCH语句失败,则该属性为"TRUE",否则为"FALSE";
FOUND --如果FETCH语句成果,则该属性为"TRUE",否则为"FALSE";
ROWCOUNT --返回游标当前行的行数;
ISOPEN --如果游标是开的则返回"TRUE",否则为"FALSE";
--将定义声明成一个类型 ref 游标
declare
type 类型名 is ref cursor;
变量名 类型名;
v_sql varchar2(100);
begin
v_sql :='select * from emp';--把语句放进去
open 变量名 for v_sql; --打开游标
close 变量名;
end;
--可以用游标的状态来决定什么时候退出循环
loop -- 遍历游标
fetch v_vur into v_row; --读取了一行数据
exit when v_vur%notfound; -- fetch 失败退出循环, 没有数据了
dbms_output.put_line(v_row.ename);
end loop
create package pk_commons is type mycur is ref cursor;
end;
--然后可以在程序包查找
到时候可直接写类型的时候
变量名 pk_commons.mycur;
函数
有且仅有一个返回值
create or replace function fn(x int ,y int) return int ----函数声明,int只是声明类型如果是varchar2,不用写成varchar2(10),如果没有参数传则不用写括号
as
--对变量的声明
begin
--代码块
end;
--当这个函数运行会保存成一个文件
select * from user_procedures;
或者写成
create function fn(x int ,y int) return int
is
begin
end;
存储过程
作用是给第三方调用,给第三方提供接口,有多个输出结果
在进行传参和结果类型的定义的时候,会将他们放在一起用in表示入参,out表示出参,inout既当入参又当出参。
create or replace procedure page(
p_current in int,--收到目前在第几页
p_count in int,--一页有几条数据
p_page out int,--输出数据总共多少页
p_cur out pk_commons.mycur --之前给游标定义了一个包create package pk_commons is type mycur is ref cursor;
)
as
p_total int;
p_sql varchar2(1000);--给游标定义的sql语句
p_s int;--这页开始时所处的总数据的第几条
p_e int;--这页结束时所处的总数据的第几条
begin
select count(ename) into p_total from emp;--找到总数据共有多少条
p_page := ceil(p_total/p_count);--算出页数
p_s:= (p_current-1)*p_count;
p_e:= p_current*p_count;
p_sql := 'select * from
(select e.*,rownum rn from emp e where rownum<='||p_e||')t where t.rn>'||p_s;
open p_cur for p_sql;--打开游标
end;
编译成功后会在
记得要给该用户授权
grant DEBUG CONNECT SESSION,DEBUG ANY PROCEDURE to scott;
然后可以对他进行调试,填入输入值
在下方的输出变量中查看
CURSOR_ALREADY_OPEN 试图"OPEN"一个已经打开的游标
DUP_VAL_ON_INDEX 试图向有"UNIQUE"中插入重复的值
INVALID_CURSOR 试图对以关闭的游标进行操作
INVALID_NUMBER 在SQL语句中将字符转换成数字失败
LOGIN_DENIED 使用无效用户登陆
NO_DATA_FOUND 没有找到数据时
NOT_LOGIN_ON 没有登陆Oracle就发出命令时
PROGRAM_ERROR PL/SQL存在诸如某个函数没有"RETURN"语句等内部问题
STORAGE_ERROR PL/SQL耗尽内存或内存严重不足
TIMEOUT_ON_RESOURCE Oracle等待资源期间发生超时
TOO_MANY_ROWS "SELECT INTO"返回多行时
VALUE_ERROR 当出现赋值错误
ZERO_DIVIDE 除数为零