美人松的高度2

1017 A除以B——c++实现

  返回  

PL/SQL 语言

2021/8/21 20:09:15 浏览:

PL/SQL (Procedure Language/SQL):对SQL 语言过程化的一个扩展,比如,在SQL 语言中添加逻辑分支、循环等,使SQL 语言具有过程化处理能力;

1. Hello World 输出

BEGIN
    -- 输出语句
    DBMS_OUTPUT.PUT_line('Hello world');
  
END PROCEDURE_HELLO;

执行后输出:Hello world

也可在sqlplus 中执行:

C:\Users\lenovo>sqlplus

请输入用户名:  system as sysdba
输入口令:

SQL> BEGIN
  2      -- 输出语句
  3      DBMS_OUTPUT.PUT_line('Hello world');
  4
  5  END PROCEDURE_HELLO;
  6  /

PL/SQL 过程已成功完成。

SQL> set serveroutput on
SQL> BEGIN
  2      -- 输出语句
  3      DBMS_OUTPUT.PUT_line('Hello world');
  4
  5  END PROCEDURE_HELLO;
  6  /
Hello world

PL/SQL 过程已成功完成。

注意:
在SQLPLUS 中执行时,结尾处放一个【/】,表示过程结束;
且默认输出是关闭状态,需要开启,命令:set serveroutput on

2. 变量

声明:变量名 变量类型
v_name varchar2(20)

赋值:
直接赋值:v_name := ‘chengyu’
语句赋值: select … into := 变量

2.1 普通类型

set serveroutput on;

DECLARE
    v_name VARCHAR2(20) := 'chengyu';
    v_sallary number;
    v_address VARCHAR2(200);

BEGIN
	-- 直接赋值
    v_sallary := 500;
    -- 语句赋值
    select '大连' into v_address from dual;
        
    DBMS_OUTPUT.PUT_LINE('v_name='||v_name||',v_sallary='||v_sallary||',v_address'||v_address);
End;

输出:v_name=chengyu,v_sallary=500,v_address大连

2.2 引用型变量类型

引用型变量的类型与长度,取决于表中字段的类型和长度;

语法:表名.列名%TYPE,如 v_name user_tab.username%TYPE

DECLARE
    v_name user_tab.username%TYPE;
    v_age user_tab.age%TYPE;

BEGIN
    select username,age into v_name,v_age from user_tab where uuid = '1000';
        
    DBMS_OUTPUT.PUT_LINE('v_name='||v_name||',v_age='||v_age);
End;

输出:v_name=chengyu,v_age=30

2.3 记录型变量类型

接收表中一整行记录
语法:变量名称 表名%ROWTYPE,如 v_user username%rowtype;

DECLARE
    -- 记录类型变量
    v_user user_tab%ROWTYPE;

BEGIN
    select * into v_user from user_tab where uuid = '1000';
        
    DBMS_OUTPUT.PUT_LINE('v_name='||v_user.USERNAME||',v_age='||v_user.AGE||',v_address='||v_user.ADDRESS);
End;

输出:v_name=chengyu,v_age=30,v_address=大连

3. 逻辑控制

3.1 条件分支

语法:
IF 条件1 THEN 执行1
  ELSIF 条件2 THEN 执行2
  ELSE 执行3
END IF;

DECLARE
    v_age user_tab.age%TYPE;

BEGIN

    select age into v_age from user_tab where uuid = '1000';
    
    IF v_age > 30 THEN
        DBMS_OUTPUT.PUT_LINE('不年轻啦!');
    ELSIF v_age > 10 THEN
        DBMS_OUTPUT.PUT_LINE('风华正茂!');
    ELSE 
        DBMS_OUTPUT.PUT_LINE('小屁孩!');
    END IF;
End;

输出:风华正茂!

3.2 流程控制

循环:
语法:
LOOP

  EXIT WHEN 退出循环
END LOOP;

DECLARE
    v_num number := 1;

BEGIN

    Loop
        EXIT WHEN v_num > 10;
        DBMS_OUTPUT.PUT_LINE(v_num);
        
        v_num := v_num + 1;
    END LOOP;
End;

输出1~10

4. 游标

用于临时存储一个查询返回的多行数据(类似于Java ResultSet集合),通过遍历游标,可以逐行访问处理结果;

4.1 使用方式

声明 ⇒ 打开 ⇒ 读取 ⇒ 关闭
声明:CURSOR 游标名(参数列表) IS 查询语句;
打开:OPEN 游标名;
读取:FETCH 游标名 INTO 变量列表;
关闭:CLOSE 游标名;

4.2 游标属性

属性返回值类型说明
%ROWCOUNT整型返回数据行数
%FOUND布尔型读取(FETCH )数据,返回一行为真,否则为假
%NOTFOUND布尔型与%FOUND 相反,常用于退出循环
%ISOPEN布尔型游标已打开为真,否则为假

4.3 例子(无参)

遍历人员表中人员名称及年龄

DECLARE
    -- 声明游标并赋值
    CURSOR c_users IS SELECT username,age FROM user_tab;
    -- 声明接受游标元素的变量
    v_name user_tab.username%TYPE;
    v_age user_tab.age%TYPE;
BEGIN
    -- 打开游标
    OPEN c_users;
    -- 遍历游标
    Loop
        -- 获取游标中数据(注意顺序与表中一致)
        FETCH c_users INTO v_name,v_age;
        -- 退出循环条件
        EXIT WHEN c_users%NOTFOUND;
        
        DBMS_OUTPUT.PUT_LINE('v_name='||v_name||',v_age='||v_age);
    END LOOP;
    -- 关闭游标
    CLOSE c_users;
End;

输出:
v_name=chengyu,v_age=30
v_name=chenglong,v_age=40
v_name=chengwei,v_age=20

4.4 例子(有参)

遍历人员表中年龄大于25岁的人员名称及年龄

DECLARE
    -- 声明游标(设置形参)
    CURSOR c_users(v_age user_tab.age%TYPE) IS SELECT username,age FROM user_tab where age > v_age;
    
    -- 声明接受游标元素的变量
    v_name user_tab.username%TYPE;
    v_age user_tab.age%TYPE;
BEGIN
    -- 打开游标(传入实参)
    OPEN c_users(25);
    -- 遍历游标
    Loop
        -- 获取游标中数据(注意顺序与表中一致)
        FETCH c_users INTO v_name,v_age;
        -- 退出循环条件
        EXIT WHEN c_users%NOTFOUND;
        
        DBMS_OUTPUT.PUT_LINE('v_name='||v_name||',v_age='||v_age);
    END LOOP;
    -- 关闭游标
    CLOSE c_users;
End;

输出:
v_name=chengyu,v_age=30
v_name=chenglong,v_age=40

5. 异常处理

5.1 语法

Exception
	WHEN exception1 [Or exception2...] THEN
		statement1;
	WHEN exception1 [Or exception2...] THEN
		statement2;
	WHEN OTHERS THEN
		statement3;

5.2 预定义异常

Oracle 已经定义好的异常,直接通过异常名称进行捕获
    ① NO_DATA_FOUNT:执行的sql 语句没有查询到结果
    ② TOO_MANY_ROWS:数据太多
    ③ INVALID_CURSOR:失效的游标(游标没打开等情况)
    ④ ZERO_DIVIDE:除数为 0
    ⑤ DUP_VAL_ON_INDEX:违反主键约束
    ⑥ VALUE_ERROR:赋值异常(类型不一致)

DECLARE
    CURSOR c_users IS SELECT username,age FROM user_tab;
    v_name user_tab.username%TYPE;
    v_age user_tab.age%TYPE;
BEGIN
    --没数据异常
    --SELECT username INTO V_NAME from user_tab where uuid = '1005';
    --数据太多异常
    --SELECT username INTO V_NAME from user_tab where uuid = '1000' or uuid = '1001';
    --失效游标异常
    --FETCH c_users INTO v_name,v_age;
    --除数为 0
    --v_age := 1/0;
    --违反主键约束异常
    --INSERT INTO user_tab VALUES('1000','','','',''); 
    --类型不一致
    v_age := 'a';
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        dbms_output.put_line('没数据异常!');
    WHEN TOO_MANY_ROWS THEN
        dbms_output.put_line('数据太多异常!');
    WHEN INVALID_CURSOR THEN
        dbms_output.put_line('失效游标异常!');
    WHEN ZERO_DIVIDE THEN
        dbms_output.put_line('除数为 0异常!');
    WHEN DUP_VAL_ON_INDEX THEN
        dbms_output.put_line('违反主键约束异常!');
    WHEN VALUE_ERROR THEN
        dbms_output.put_line('类型不一致异常!');
    WHEN OTHERS THEN
        dbms_output.put_line('其他异常!');
END;

※自定义异常略

6. 存储过程

PL/SQL 语言做成的业务存储起来,便于重复调用。
开发过程中,某些特定的功能,会对数据库进行多次连接、关闭(耗资源),对数据进行多次的IO读写等操作,性能比较低,使用存储过程,可以做到连接关闭一次数据库就可以实现业务需求,可以大大提高效率。

6.1 语法

注意:DECLARE 关键字省略

CREATE OR REPLACE PROCEDURE 存储过程名 AS 
BEGIN
  NULL;
END PROCEDURE1;

可带参数,可有返回值

6.2 无参存储过程

过程 ⇒ 新建过程

CREATE OR REPLACE PROCEDURE P_HELLO AS 
-- 声明变量
v_name varchar(20) := 'CHENGYU';
BEGIN
  DBMS_OUTPUT.PUT_LINE('HELLO '||v_name);
END P_HELLO;

输出:HELLO CHENGYU

① SQL工作表中调用:

BEGIN
    P_HELLO;
END;

② SQL PLUS 中调用

SQL> exec P_HELLO ;
HELLO CHENGYU

PL/SQL 过程已成功完成。

6.3 带输入参数存储过程

CREATE OR REPLACE PROCEDURE P_PARAMETER(i_id IN user_tab.uuid%TYPE) AS 

v_name user_tab.username%TYPE;
v_age user_tab.age%TYPE;

BEGIN
  select username,age into v_name,v_age from user_tab where uuid = i_id;
  
  DBMS_OUTPUT.PUT_LINE('v_name='||v_name||',v_age='||v_age);
  
END P_PARAMETER;

① SQL工作表中调用:

BEGIN
    P_PARAMETER(1001);
END;

输出:v_name=chenglong,v_age=40
② SQL PLUS 中调用

SQL> exec P_PARAMETER(1000);
v_name=chengyu,v_age=30

PL/SQL 过程已成功完成。

6.4 带输出参数存储过程(有返回值)

一般提供给第三方程序调用;

1)定义存储过程

create or replace PROCEDURE P_PARAMETER_OUT(i_id IN user_tab.uuid%TYPE,o_name OUT user_tab.username%TYPE,o_age OUT user_tab.age%TYPE) AS 

BEGIN
    select username,age into o_name,o_age from user_tab where uuid = i_id;
  
END P_PARAMETER_OUT;

① SQL工作表中调用:

DECLARE
--接受存储过程返回结果
    v_name user_tab.username%TYPE;
    v_age user_tab.username%TYPE;
BEGIN
     p_parameter_out(1001,v_name,v_age);
     DBMS_OUTPUT.PUT_LINE('v_name '||v_name||',v_age '||v_age);
END;

输出:v_name chenglong,v_age 40

6.5 Java 程序调用存储过程

创建java 项目
新建lib 文件夹,并将 ojdbc.jar 文件复制到该文件夹中,ojdbc.jar 右键Add as Library ⇒ OK

创建Class

public class test {
    @Test
    public void test() throws ClassNotFoundException, SQLException {
        // 1.加载驱动
        Class.forName("oracle.jdbc.OracleDriver");
        // 2.获取连接对象
        String url = "jdbc:oracle:thin:@localhost:1521:chengyu";
        String user = "ADMINUSER";
        String password = "Aa135007";
        Connection conn = DriverManager.getConnection(url,user,password);
        // 3. 获得语句对象
        String sql = "Call P_PARAMETER_OUT(?,?,?)";
        CallableStatement call = conn.prepareCall(sql);
        // 4.设置输入参数
        call.setInt(1,1001);
        // 5.注册输出参数
        call.registerOutParameter(2, OracleTypes.VARCHAR);
        call.registerOutParameter(3, OracleTypes.NUMBER);
        // 6. 执行存储过程
        call.execute();
        // 7.获取输出参数
        String u_name = call.getString(2);
        int u_age = call.getInt(3);

		System.out.println("u_name="+u_name+",u_age="+u_age);
        // 8.释放资源
        call.close();
        conn.close();
    }
}

输出:u_name=chenglong,u_age=40

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号