
# 存储过程（Procedure）
#### 简介
存储过程是预编译并存储在数据库中的程序，由一组SQL语句组成，用于执行一系列数据库操作。存储过程可以被多个应用程序调用，从而提高代码的复用性和维护性。
存储过程的特点：
- 复杂数据操作简化：执行需要多步操作的复杂业务逻辑，如批量数据处理、数据转换等。
- 性能优化：通过预编译和减少网络通信，提高数据库操作的执行效率。
- 安全性增强：将业务逻辑封装在存储过程中，可以限制直接访问数据库表，增强数据安全性。
- 简化开发和维护：将业务逻辑集中在数据库中，简化应用程序的开发和维护。
 
#### 示例
如下示例中：存储过程prc_test的作用是将表tb_test1中数据插入到表tb_test2中，如果插入失败，将调用时间、错误信息、和数据插入到tb_test_err中。
```
--环境准备：建表和插入数据。
gaussdb=# CREATE TABLE tb_test1(id int,info text);
CREATE TABLE
gaussdb=# CREATE TABLE tb_test2(id int PRIMARY KEY, info text);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tb_test2_pkey" for table "tb_test2"
CREATE TABLE
gaussdb=# INSERT INTO tb_test1 VALUES (generate_series(1,5),'AAA');
INSERT 0 5
gaussdb=# INSERT INTO tb_test2 VALUES (generate_series(1,2),'aaa');
INSERT 0 2
gaussdb=# CREATE TABLE tb_test_err(
    err_time text,
    err_info text,
    id int,
    info text
);
CREATE TABLE
--创建存储过程prc_test。
gaussdb=# CREATE OR REPLACE PROCEDURE prc_test(v_time IN text) AS 
    --定义游标。
    CURSOR v_cur IS SELECT * FROM tb_test1;
    v_id int;
    v_info text;
BEGIN
    --打开游标。
    OPEN v_cur;
    LOOP
        --使用游标。
        FETCH v_cur INTO v_id,v_info; 
        --退出循环条件：游标取不到数据时退出循环。
        EXIT WHEN v_cur %notfound;
        BEGIN
            --将tb_test1表中数据插入到tb_test2中。
            INSERT INTO tb_test2 VALUES (v_id,v_info);        
        --异常处理：执行失败时将错误信息插入到tb_test_err表中。
        EXCEPTION 
            WHEN OTHERS THEN
                INSERT INTO tb_test_err VALUES (v_time,sqlerrm,v_id,v_info);
        END;
    END LOOP; 
    --关闭游标。
    CLOSE v_cur;      
END;
/
CREATE PROCEDURE
--调用存储过程传入字符串2019-01-31。
gaussdb=# CALL prc_test('2019-01-30');
--查看结果。
gaussdb=# SELECT * FROM tb_test2;
 id | info 
----+------
  1 | aaa
  2 | aaa
  3 | AAA
  4 | AAA
  5 | AAA
(5 rows)
--查看插入失败的数据信息。
gaussdb=# SELECT * FROM tb_test_err;
  err_time  |                            err_info                             | id | info 
------------+-----------------------------------------------------------------+----+------
 2019-01-30 | Duplicate key value violates unique constraint "tb_test2_pkey". |  1 | AAA
 2019-01-30 | Duplicate key value violates unique constraint "tb_test2_pkey". |  2 | AAA
(2 rows)
--删除表和存储过程。
gaussdb=# DROP PROCEDURE prc_test;
DROP PROCEDURE
gaussdb=# DROP TABLE tb_test1,tb_test2,tb_test_err;
DROP TABLE
```
