记录类型百分号type,使用它的优点,所引用的数据库列的数据类型不必知道,要不你就得知道它的
类型和他的一样的,这里你可以实时改变,列的数据类型改变,我这里也跟着改,动态的来获取你的类型
这里还有个百分号rowtype,返回一个记录类型,其数据类型和数据库表的类型一样,一个列一样
你这里有多少列我这里也有,列名叫什么我也跟你一样,然后你的列的类型,也一样,这就过了,他表示的是等于符号
这个叫一般运算符
加减乘除,这个叫赋值了,这个我们后边讲游标的时候,游标有可能有参数,参数的赋值用这个
逻辑运算符,这个我们讲SQL里面都说过,你需要用到的你就来用
变量的赋值,用到连接的用到双竖线
通过select语句来完成对数据库的赋值,然后每次执行select语句就赋值一次,一般要求被赋值的变量,
与select的列名要一一对应,select一个什么salary,工资,into于一个变量,然后赋给一个人,你要再赋予一个人,
就要循环了,再赋予一个人就再赋予一次,一条一条的出来
不能讲select语句赋给布尔类型的变量,这就是一个要求
然后可转换的数据类型,在讲SQL中也提过,to_number,to_char,to_date
注释,两个这个,表示的是单行的
然后这样是表示多行的,这种每种语言都有,文档注释是JAVA特有的
第三章,PL/SQL的流程控制语句,第一个叫条件语句,我们说条件语句有两种格式的,
一种叫if then,一个叫case when then when then,先看这个,if就跟讲JAVA里面一样,
JAVA里面if也说了三种结构,最简单的是一种情况,if一个东西,他返回的也是一个布尔类型的,
如果满足真的话,就执行后面的then,分号结束,endif,因为你讲PL/SQL他没有大括号的概念,JAVA
里面有大括号的概念,我一包就知道哪里是语句块,大括号结束,大括号结束就相当于endif,他这里没有
大括号呢,只有通过单词,叫关键字,关键字来标识,你这个语句块结束了
两个的话加一个else,多个的话就没有e了,els,没有e,然后if,这是一个词,中间也不能加空格,
这个是跟JAVA不一样的
那我们写一个例子,写这个吧,查询150号员工的工资,如果工资大于1万,打印这个,若这个之间就打印这个,
否则打印这个,declare,他的工资大于这么多,可以把工资放在这个变量里,看看这个变量是不是大于1万,
是这个意思吧,所以v_sal,employees表的salary的类型,一样的,这样写,然后,begin,我就select,salary,
into v_sal,from employees表,where employee_id等于150,把这个人的工资放到这儿,if,没有写小括号,
直接写if,如果你这个v_sal它是大于等于1万的,then dbms_output.put_line打印这个叫salary>=10000,
分号结束,这里写了三种情况,elsif,同样满足我们JAVA里面讲的,把更严格的放上边,只需要写上一个5000
就行了,就不用and salary小于1万了,then,再else,else就直接打印了,else这样,最后记得写一个endif,
表明这个条件判断语句结束了,紧接着我这个程序就结束了
declare
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id = 50;
if v_sal >= 10000 then dbms_output.put_line('salary>=10000');
elsif v_sal > 5000 then dbms_output.put_line('5000<=salary<=10000');
else dbms_output.put_line('salary<5000');
endif;
end;
这个人的工资大于等于1万的,这个程序就写完了,还有一种思路就是,什么思路,我用一个变量,
来记录你这个人妖输出的语句,这个写法没问题,写出来了,然后我再记录一下你这个类型,v_temp,
这个变量是varchar类型的,10个吧,当你工资大于等于1万的时候,我给这个变量赋个值,冒号等于,
当这个的时候,else,这个能看懂,然后结束,结束完了以后,你可以在这儿,dbms_output.put_line,
v_temp,跟着你可以把他的工资给他打印一下,v_sal双竖线,然后这样
declare
v_sal employees.salary%type;
v_temp varchar2(30);
begin
select salary into v_sal from employees where employee_id = 150;
if v_sal >= 10000 then v_temp := 'salary >= 10000';
elsif v_sal >= 5000 then v_temp := '5000<=salary<10000';
else v_temp := 'salary < 5000';
dbms_output.put_line(v_sal || ',' || v_temp);
end;
然后大于等于1万,这种想法要注意,我们在JAVA当中也涉及到过,我可以把你要输出的这个东西,
那我就赋给一个变量,对这个变量进行一个操作,就这样,我们体会了if else,方法二,case when then,
这个例子你可以看看,这是另一种条件表达式,叫case一个东西,当这样的时候执行这个,when then then,
最后加一个else,end,然后结束
我们把刚才这个练习,给他改成case when then,我们JAVA里面讲一个条件判断的时候,一个叫if else if,
还有一个叫switch case,这两个哪个好啊,显然if else更方便一些,没有共鸣啊,是吧,switch case的时候,
一个他就那么几种数据类型的可以用,再一个switch一个变量,case的是你离散时的值,然后相比,如果你要比较这个
数的范围,如果很大,或者是连续的,比较这个温度,温度在0到15度之间,说这个温度,那你用switch就费劲了,你这个中间的
温度那是连续的,你不可能把每一个温度都给他写出来,这个时候你只能用if else,有些时候一些值,如果就那么几个,你用
if else不如用switch效率高,这儿呢是同理的,这个if,else if,if then, elsif then,这个也是更具有通用性的,然后用case
when then,那就相当于JAVA中的switch case一样,那我们用它来写操作一下来看看,操作的话这块不要了,把这个工资放到这里面,
下一步就是case吧,我case一下你这个工资,v_sal,当你这个工资大于等于1万的时候,then,then这个吧,加个else,记得要加一个end,
表示结束,知道为什么报错,我们讲switch的时候,switch case,case里面,不能够放范围的,是不是只能放变量,你不能case salary,
when,salary大于1万,case只能填变量,这个也是一样,这里只能写值,那你这个怎么处理,那我只能在这里处理了,这个肯定是已经
获取到他的工资了,工资除以5000,加上一个trunc,这样不就可以得到离散的值了吗,如果你工资小于5000的,这一串值是0,如果要5000到
1万之间的,是1,大于1万的就是2,所以说你这个改的话,把2大的写到else里边,所以我们这里从小的写,先0,再1,不是0不是1,
这样你看行不行
declare
v_sal employees.salary%type;
v_temp varchar2(30);
begin
select salary into v_sal from employees where employee_id = 150;
v_temp :=
case trunc(v_sal/5000) when 0 then 'salary < 5000'
when 1 then '5000<=salary<10000'
else 'salary>10000'
end;
dbms_output.put_line(v_sal||','||v_temp);
end;
我是让你看到调的过程当中,哪种格式是对的,我们刚才是不是这样写的,不能够写范围,我们没有写范围,
这样处理的时候,当然这个是写错了,不能写分号,然后你变量赋值不能写这儿,每次不能写这儿,你得给他拿出来,
拿到这儿来,你就写成这样,变量赋值,然后当是这样的时候,给他赋一个他,要么他要么他,打印,打印试试,因为这个
人工资是大于1万的,dbms_output.put_line,我这里简写,打个1,他这个也不行,他这个也特别呕心
declare
v_sal employees.salary%type;
v_temp varchar2(30);
begin
select salary into v_sal from employees where employee_id = 150;
case trunc(v_sal/5000) when 0 then dbms_output.put_line('1')
when 1 then dbms_output.put_line('1')
else dbms_output.put_line('1')
end;
dbms_output.put_line(v_sal || ',' || v_temp);
end;
他这个特别的呕心,而且还有哪里呕心,他这里还特别有局限性,我们刚才用的trunc,如果我把这个等号删了,
实际上你这里是错的,我把等号写在这儿,意味着如果要等于5000的话,现在我不放在那个语句,现在我放到这种
情况,那你这个时候一trunc的话,坏事了,因为如果这个工资是5000,你得的结果是1,如果是1的话输出这个,使用
case when then的时候,这个限制条件很多,一个呢他只能写具体的值,他不能写取值范围,这点不如if else好,
再一点,既然你这写具体的值,既然你写具体的值的话你就要考虑到,你这个值的范围,因为人家这儿的话,正常的时候
是比5000多,含5000的时候,都是1,当然小于1万了,如果5000就给你放到另一个范围里面,这样就写不了了,就只能够
用if else了,这就是使用它的局限性,但是他至少也算是一种表达方式吧,你就把的if else顺序当成JAVA里的if else,
case when then相当于JAVA里的switch case,我们再练一下他
8. 使用 CASE ... WHEN ... THEN ... ELSE ... END;
要求: 查询出 122 号员工的 JOB_ID, 若其值为 'IT_PROG', 则打印 'GRADE: A';
'AC_MGT', 打印 'GRADE B',
'AC_ACCOUNT', 打印 'GRADE C';
否则打印 'GRADE D'
declare
--声明变量
v_grade char(1);
v_job_id employees.job_id%type;
begin
select job_id into v_job_id
from employees
where employee_id = 122;
dbms_output.put_line('job_id: ' || v_job_id);
--根据 v_job_id 的取值, 利用 case 字句为 v_grade 赋值
v_grade :=
case v_job_id when 'IT_PROG' then 'A'
when 'AC_MGT' then 'B'
when 'AC_ACCOUNT' then 'C'
else 'D'
end;
dbms_output.put_line('GRADE: ' || v_grade);
end;
查询出122号员工的JOB_ID,如果他的值是这个,打印这个,这个打印这个,这个打印这个,declare,declare里面写啥,声明job_id,
v_job_id,varchar型的,先这样,然后打印一个东西,这个打印的东西给他当成一个变量,varchar2,这个差不多,begin,select
job_id,into job_id,from employees where,employee_id等于122,把这个人的job_id给拿出来,v_temp等于,回来case,case
v_job_id,when 'IT_PROG',then,我简写了,打印A,when 'AC_MGT',then,这个没有分号,还是挺别扭的,else,然后就没有了,
打印v_job_id,然后执行,加个end,这个部门的,它是D
declare
v_job_id varchar2(10);
v_temp varchar2(10);
begin
select job_id into v_job_id from employees where employee_id = 122;
v_temp :=
case v_job_id when 'IT_PROG' then 'A'
when 'AC_MGT' then 'B'
when 'AC_ACCOUNT' then 'C'
else 'D'
end;
end;
下面就循环了,循环三种结构,loop,表示循环体,分号结束
exit when,循环条件,然后end loop,表示结束,这两个之间是可以加东西
有一个输出1到100,用三种方式写,先说刚才的第一种
9. 使用循环语句打印 1 - 100.(三种方式)
1). LOOP ... EXIT WHEN ... END LOOP
declare
--初始化条件
v_i number(3) := 1;
begin
loop
--循环体
dbms_output.put_line(v_i);
--循环条件
exit when v_i = 100;
--迭代条件
v_i := v_i + 1;
end loop;
end;
2). WHILE ... LOOP ... END LOOP
declare
--初始化条件
v_i number(3) := 1;
begin
--循环条件
while v_i <= 100 loop
--循环体
dbms_output.put_line(v_i);
--迭代条件
v_i := v_i + 1;
end loop;
end;
3).
begin
for i in 1 .. 100 loop
dbms_output.put_line(i);
end loop;
end;
先不能loop,先declare,begin,end,我们还没有讲异常呢,我们讲循环的时候,我们讲JAVA的时候包括三部分,
第一部分,叫初始化条件,第二部分,叫循环体也行,三循环条件,四迭代条件,这样三部分,然后放到这儿,任何循环
都是这样一个结构,都少不了,declare的算初始化条件,声明一个什么样的变量,然后然他执行loop,然后就是循环体,
case when算循环条件,跟endloop算迭代条件,先写第一部分,声明一个变量,v_i这是一个变量,这是number类型的,
写大一点也无所谓,冒号等于从1开始,这就是初始化条件,begin,loop什么执行,这个是2,dbms输出,输出一下v_i,
输出他以后,exit when,结束就是v_i,大于等于100的时候,exit when当结束的时候,如果没有到这个的时候,
v_i = v_i +1,然后,然后end loop,这儿是3,这儿是第四步,冒号等于
declare
v_i number(5) := 1;
begin
loop
dbms_output.put_line(v_i);
exit when v_i >= 100;
v_i := v_i + 1;
end loop;
end;
从1开始,然后到100结束,先打印一下,把这个循环体放到这,这个就到99了
declare
v_i number(5) := 1;
begin
loop
dbms_output.put_line(v_i);
v_i := v_i + 1;
exit when v_i >= 100;
end loop;
end;
因为你打印99,等于99加1了,把等于去了,这就到100了
declare
v_i number(5) := 1;
begin
loop
dbms_output.put_line(v_i);
v_i := v_i + 1;
exit when v_i > 100;
end loop;
end;
你这个你可以省了,让他在循环体里面执行也行,这是说的第一种方式,loop,exit when,end loop,
这都是他的关键字,第二种,就是while,while loop,然后执行,end loop
用这种格式操作一下他,初始化条件,都这样写,where v_i小于等于100,loop执行,dbms_output.put_line,
执行完了以后,v_i要让他执行一个值,然后还有别的操作不,还有end loop,还有什么,这个跟我们讲的while
有点类似
declare
v_i number(5) := 1;
begin
while v_i<=100 loop
dbms_output.put_line(v_i);
v_i := v_i + 1;
end loop;
end;
这里是循环条件,这里是循环体,然后你得加上一个迭代部分,这个不加的话就成了死循环了,
这是第二种方式,再往后,for,for循环,for循环的时候,JAVA里面的for循环重新定义了一个变量,
int i = 0,这个也是一样,循环计数器就是你定义的一个变量,只不过他的类型需要你指定了
你看看这个格式,叫in,这个你先忽略,下限,两个点,上限,loop,要执行的语句,再end loop,所以就来,
这里不要了,你可以不用,begin,for循环,定义一个变量,比如c,in,从1开始,点点到一百,loop,开始执行,
打印c,打印c完了以后,我要到后面end loop
begin
for c in 1..100 loop
dbms_output.put_line(c);
end loop;
end;
有啥疑问吗,这不就相当于JAVA里面的for,int i,i等于几啊,i等于1,第二部分,分号后边i小于等于100,
这不就是到100吗,加加,我自动的给你加加,这是循环体,就这样,这个后边可以加上一个reverse,从100到
1,就是可以反着来
begin
for c in 1..100 loop
dbms_output.put_line(c);
end loop;
end;
这个完了以后,我们写一个稍微麻烦一点的,我们在JAVA中讲过,准确来说从2开始,到100之间的质数,
不只是结构,还有小算法,加不加break,效率是不一样的,循环结构,条件判断结构,顺便考一下你的算法,
题目也不大,所以是一个挺好的题目,从JAVA当中去想,你当时声明过哪些变量,然后begin,end,我们外层
for循环定义一个i,是想从2到100,在内层又定义一个for循环,然后定义一个flag,修改flag为true,这里我们也得定义
一个变量,v_i,number类型的,冒号等于,从2开始,number类型的,冒号等于,也是从2开始,我再定义一个flag,早知道我们
不定义布尔类型了,我还定义一个number类型的,1位就够,这个用for循环实现和while循环实现是一样的,我们先用while循环
实现吧,while,while后边写的是一个条件,v_i他的小于等于100,然后loop开始执行这个循环,这个循环里边,如果v_j
这个就是那之前的一行代码,你要是不初始化的话,每次就进不去了,每次进不去他就认为你是质数了,
这个其实和我们JAVA里面,除了各式之外,就是你这个外层循环,当这个被除数,内层当除数,范围取个根号就完了,
一旦发现做除等于0的时候,你给他改个值,然后判断这个值是否被改过,说明他就不是质数,没改过,就是,记得每次
给他改成1,这个重新给他置成一个2,然后这个加加就完了,这个是我们使用while循环来实现的,实现了质数的一个输出,
现在我们给他改成使用for,使用for循环,使用for循环的话,这两你不用了,for v_i,in,从2开始到100,loop,for v_j,
in 从2开始,sqrt(v_i),然后loop,然后还是这个判断,如果mod(v_i,v_j),等于0,then,then v_flag置成0,end if,if完了
就不用再加加了,这个完了以后,判断一下,判断一下v_flag,如果他是等于1的话,then,打印一下v_i,end if,注意这个,
那两行我们就不用了,v_flag等于1,end一下
declare
v_flag number(1) := 1;
begin
for v_i in 2..100 loop
for v_j in 2 .. sqrt(v_i) loop
if mod(v_i,v_j)=0 then v_flag := 0;
end if;
end if;
if v_flag = 1 then dbms_output.put_line(v_i);
end if;
v_flag := 1;
end loop;
end;
这个我们使用for循环,显然比刚才的while要简洁,而for循环会自动的给你迭代,就是这两个好处,
我们讲JAVA的时候,说过一个观点,有些算法是可以改进的,在哪,比如8这个数,8这个数已经明显等于
0了,但是他没有终止,他又继续的比了一下4,实际上到2的时候,已经该结束了,我们开始用了一个叫continue
标签的形式,直接跳到外层,叫goto,无条件的跳到指定的标号去
跳转我在哪跳,如果一旦你发现有一个值,我就让你goto一个地,goto哪个地,goto到一个带标签的一个位置,
假设这个标签我就叫label,那你这个label是什么啊,实际上就是跳到这,一旦你这边出现等于0的时候执行过了,
进入这个语句里边,我就来判断一下,或者每执行一次我就给判断一下,如果不是1了,就已经被改了,直接就跑到
这里来了
declare
v_flag number(1) := 1;
begin
for v_i in 2..100 loop
for v_j in 2 .. sqrt(v_i) loop
if mod(v_i,v_j)=0 then v_flag := 0;
goto label;
end if;
end loop;
<
10. 综合使用 if, while 语句, 打印 1 - 100 之间的所有素数
(素数: 有且仅用两个正约数的整数, 2, 3, 5, 7, 11, 13, ...).
declare
v_flag number(1):=1;
v_i number(3):=2;
v_j number(2):=2;
begin
while (v_i<=100) loop
while v_j <= sqrt(v_i) loop
if (mod(v_i,v_j)=0) then v_flag:= 0;
end if;
v_j :=v_j +1;
end loop;
if(v_flag=1) then dbms_output.put_line(v_i);
end if;
v_flag :=1;
v_j := 2;
v_i :=v_i +1;
end loop;
end;
(法二)使用for循环实现1-100之间的素数的输出
declare
--标记值, 若为 1 则是素数, 否则不是
v_flag number(1) := 0;
begin
for i in 2 .. 100 loop
v_flag := 1;
for j in 2 .. sqrt(i) loop
if i mod j = 0 then
v_flag := 0;
end if;
end loop;
if v_flag = 1 then
dbms_output.put_line(i);
end if;
end loop;
end;
11. 使用 goto
declare
--标记值, 若为 1 则是素数, 否则不是
v_flag number(1) := 0;
begin
for i in 2 .. 100 loop
v_flag := 1;
for j in 2 .. sqrt(i) loop
if i mod j = 0 then
v_flag := 0;
goto label;
end if;
end loop;
<
这个有分号,这个不用加尖括号,比刚刚那个效率高,就相当于我们JAVA里面讲的continue,这个题就是
这样写的,这是用两种方式,相当于三种方式,while循环,for循环,还有使用goto这种格式的,goto就是这个意思,
后边这还有一个练习,就是这个
11+.打印1——100的自然数,当打印到50时,跳出循环,输出“打印结束”
(方法一)
begin
for i in 1..100 loop
dbms_output.put_line(i);
if(i = 50) then
goto label;
end if;
end loop;
<
从1打到99,使用goto标签的形式,或者呢有没有别的方式,这个我们就说完了,如果等于50,
让他exit,这个不要了,这个没法打印结束了,那就加上一个dbms_output.put_line('打印结束'),
begin
for i in 1..100 loop
if i = 50 then dbms_output.put_line('打印结束');
exit;
end if;
dbms_output.put_line(i);
end loop;
end;