Oracle学习笔记 part2

在Oracle中有一个很重要的语言PL/SQL,在这一部分里,我们主要聊聊这个语言

DECLARE
    --声明部分: 在此声明PL/SQL用到的变量,类型及游标,以及局部的存储过程和函数
  BEGIN
    -- 执行部分:  过程及SQL 语句  , 即程序的主要部分
  EXCEPTION
    -- 执行异常部分: 错误处理
  END;

 

 

我们通过这个PL/SQL结构的语法来写一个小例子

declare
    --声明一个名字叫V_MyName的变量并把其赋值为'Sora',变量的类型为varchar(20) 其中 := 代表赋值语句
    V_MyName varchar(20) := 'Sora' ;
    --声明一个名字叫V_InsertName的变量,并指定类型为hls_test_sora表中的test_name列类型
    V_InsertName hls_test_sora.test_name%type;
begin
    --通过dbms输出V_MyName的值,其中||表示连接字符串,相当于System.out.println(V_MyName)
    dbms_output.put_line('V_MyName的值为'||V_MyName);
    
    --插入一条数据,其中vw_test_sora为自定义视图(注意这里没有写分号,这个语句还没有完毕)
    insert into vw_test_sora  values ('Venti', 17, 'male', sysdate)
    
    --将插入的值中的test_name列中的值注入到V_InsertName变量中
    returning test_name into V_InsertName;
    
    --输出V_InsertName的值
    dbms_output.put_line('插入值后V_InsertName的值为'||V_InsertName);
end;

 

以上这个小例子实现了数据插入并显示到dbms上 ,当然这个使用了returning这个关键词,这个关键词只能用在DML语句中,如果希望在DQL中使用则直接将into写在DQL语句中,如下所示

declare
    v_name varchar2(20);
    v_age number;
begin
    select test_name, test_age into v_name, v_age from hls_test_sora where test_id = 5;
    
    dbms_output.put_line(v_name)
    dbms_output.put_line(v_age)
end;

 

上面的Demo是不是很容易?接下来,我们把他们几个步骤拆开逐步分析

 

Declare

用来声明变量的,上面也说了,%type可以指定关键词,或者自己定义,也可以初值赋值。接下来我们聊聊一些别的类型的数据

记录类型

declare
    --声明一个自定义record类型,命名为my_record
    type my_record is record(
        v_name varchar2(20),
        v_age number,
        v_gender varchar2(10)
    );
    --声明一个类型为my_record类型的变量,命名为v_my_record
    v_my_record my_record;
begin
    --将查询到的数据注入到v_my_record变量中,由于是注入,只能查询一条数据
    select test_name, test_age, test_gender into v_my_record 
    from hls_test_sora where test_id = 5;
    dbms_output.put_line(v_my_record.v_name || v_my_record.v_age || v_my_record.v_gender);
end;

 

行类型

--此处表示v_bx_app_notice_list变量继承了表bx_app_notice_list中的所有字段
v_bx_app_notice_list bx_app_notice_list%rowtype

Begin

if语句

其实这个和一般的if语句一样,同case...when...then,下面举个例子,一看就会的(当然后面也可以加elif,这点有点像python)

declare
    v_age hls_test_sora.TEST_AGE%type;
begin 
    select test_age into v_age from hls_test_sora where test_id = 5;
    --如果大于10就输出age>10,如果不是就输出v_age<=10
    if v_age > 10 then dbms_output.put_line(v_age||'>10');
    else dbms_output.put_line(v_age||'<=10');
    end if;
end;

 

小Tips:if每个语句后需要加分号,when...then不能加分号

关于循环

废话不多说直接上例子,三种利用循环输出1-100的方法

--loop循环
declare
    v_num number := 1;
begin
    loop
        dbms_output.put_line(v_num);
        v_num := v_num + 1;
        exit when v_num > 100;
    end loop;
end;
--while+loop循环
declare
    v_num number := 1;
begin
    while v_num <= 100 loop
        dbms_output.put_line(v_num);
        v_num := v_num + 1;
    end loop;
end;
--for循环
begin
    --..表示范围运算符,承接两个参数,表示100-1的参数,reverse表示倒置,即从1-100
    for num in reverse 100..1 loop
        dbms_output.put_line(num);
    end loop;
end;

 

看到上面三种循环的方式,选哪个就不用我多说了吧?那肯定是for循环写的最少啊,不过对于那种不知道循环几次的需求就不要用for循环了。说起来for循环的操作方式真有点像python中的for i in range(100)。我感觉for循环最大的优势在于不需要自变量就可以循环,而且条件也写的比较方便(也可能是因为我这个例子比较简单)

下面是一些复杂的循环(算法)


--输出100以内的所有质数
-- 首先我们创建个函数... -我不会函数啊我靠! -函数也就那样的,早点用函数早点少敲代码(笑)

--create or replace 英文字面意思,后面就是函数名以及函数参数的定义
CREATE OR REPLACE function IsPrime(v_num number)
--返回值的定义,返回值不需要写长度
return number is
--这里本来是可以自定义声明变量的,但是因为我们这个例子过于简单就不需要了。(在这里就可以看出函数和一般的pl/sql结构是一样的)
    
begin
    --循环2到目标开根范围以内的值,如果该数能整除循环的数,就返回0,如果循环完了都没有返回,就返回1
    --需要注意的就是打分号,这个没提示的太不人性,基本上看半天才看出来(也可能是js敲多了不习惯敲分号)
    for i in 2..(sqrt(v_num)) loop
        if v_num mod i = 0 
            then return(0);
        end if;
    end loop;
    return(1);
end IsPrime;
​
--接下来就很简单了,调用这个函数即可,应该不需要注释吧?
begin
    for i in 2..100 loop
        if IsPrime(i) = 1
            then dbms_output.put_line(i);
        end if;
    end loop;
end;

 

 

关于goto,这里只是提一嘴,感觉不大能用的上,例子如下

--判断是否为合数
CREATE OR REPLACE function IsTotal(v_num number)
return number is
begin
    for i in 2..(sqrt(v_num)) loop
        if v_num mod i = 0 
            then goto total;
        end if;
    end loop;
    return (0);
    <<total>>
    return (1);
end;

 

跳出循环的一些关键词

--EXIT:跳出本循环转而执行本循环的上一级循环的下一次循环。
--CONTINUE:本次循环后面的代码部分不再执行,转而执行本循环的下一次循环。

 

posted @ 2021-12-08 11:00  二色莲华  阅读(56)  评论(0)    收藏  举报