
# DWS存储过程基本语句
#### 定义变量
介绍PL/SQL中变量的声明，以及该变量在代码中的作用域。
**变量声明**
变量声明语法请参见[图1]。
图1declare_variable::=   
![](https://support.huaweicloud.com/devg-dws/figure/zh-cn_image_0000002040329244.png "点击放大")
对以上语法格式的解释如下：
- variable_name，为变量名。
- type，为变量类型。
- value，是该变量的初始值（如果不给定初始值，则初始为NULL）。value也可以是表达式。
**示** **例**
```
DECLARE
    emp_id  INTEGER := 7788;  --定义变量并赋值
BEGIN
    emp_id := 5*7784;  --变量赋值
END;
/
```
变量类型除了支持基本类型，还可使用%TYPE和%ROWTYPE去声明一些与其他表字段或表结构本身相关的变量。
**%TYPE属性**
%TYPE主要用于声明某个与其他变量类型（例如，表中某列的类型）相同的变量。假如想定义一个my_name变量，它的变量类型与employee的firstname类型相同，可使用如下定义：
```
my_name employee.firstname%TYPE
```
这样定义可以带来两个好处，首先，不用预先知道employee 表的firstname类型具体是什么。其次，即使之后firstname类型有了变化，也不需要再次修改my_name的类型。
**%ROWTYPE属性**
%ROWTYPE属性主要用于对一组数据的类型声明，用于存储表中的一行数据，或从游标匹配的结果。假如需要一组数据，该组数据的字段名称与字段类型都与employee表相同。可以通过如下定义：
```
my_employee employee%ROWTYPE
```
![](https://support.huaweicloud.com/devg-dws/public_sys-resources/notice_3.0-zh-cn.png)
多个CN的环境下，存储过程中无法声明临时表的%ROWTYPE及%TYPE属性。因为临时表仅在当前session有效，在编译阶段其他CN无法看到当前CN的临时表。故多个CN的环境下，会提示该临时表不存在。
**变量作用域**
变量的作用域表示变量在代码块中的可访问性和可用性。只有在它的作用域内，变量才有效。
- 变量必须在declare部分声明，即必须建立BEGIN-END块。块结构也强制变量必须先声明后使用，即变量在过程内有不同作用域、不同的生存期。
- 同一变量可以在不同的作用域内定义多次，内层的定义会覆盖外层的定义。
- 在外部块定义的变量，可以在嵌套块中使用。但外部块不能访问嵌套块中的变量。
**示例**
```
DECLARE
    emp_id  INTEGER :=7788;  --定义变量并赋值
    outer_var  INTEGER :=6688;  --定义变量并赋值
BEGIN
    DECLARE        
        emp_id INTEGER :=7799;  --定义变量并赋值
        inner_var  INTEGER :=6688;  --定义变量并赋值
    BEGIN
        dbms_output.put_line('inner emp_id ='||emp_id);  --显示值为7799
        dbms_output.put_line('outer_var ='||outer_var);  --引用外部块的变量
    END;
    dbms_output.put_line('outer emp_id ='||emp_id);  --显示值为7788
END;
/
```
#### 赋值语句
**语法**
给变量赋值的语法请参见[图2]。
图2assignment_value::=   
![](https://support.huaweicloud.com/devg-dws/figure/zh-cn_image_0000002040170940.png "点击放大")
对以上语法格式的解释如下：
- variable_name，为变量名。
- value，可以是值或表达式。值value的类型需要和变量variable_name的类型兼容才能正确赋值。
**示例**
```
DECLARE
    emp_id  INTEGER := 7788;--赋值
BEGIN
    emp_id := 5;--赋值
    emp_id := 5*7784;
END;
/
```
#### 调用语句
**语法**
调用一个语句的语法请参见[图3]。
图3call_clause::=   
![](https://support.huaweicloud.com/devg-dws/figure/zh-cn_image_0000002076330085.png "点击放大")
对以上语法格式的解释如下：
- procedure_name，为存储过程名。
- parameter，为存储过程的参数，可以没有或者有多个参数。
**示例**
```
--创建存储过程proc_staffs
CREATE OR REPLACE PROCEDURE proc_staffs
(
section     NUMBER(6),
salary_sum out NUMBER(8,2),
staffs_count out INTEGER
)
IS
BEGIN
SELECT sum(salary), count(*) INTO salary_sum, staffs_count FROM staffs where section_id = section;
END;
/
--创建存储过程proc_return.
CREATE OR REPLACE PROCEDURE proc_return
AS
v_num NUMBER(8,2);
v_sum INTEGER;
BEGIN
proc_staffs(30, v_sum, v_num);  --调用语句
dbms_output.put_line(v_sum||'#'||v_num);
RETURN;  --返回语句
END;
/
--调用存储过程proc_return.
CALL proc_return();
--清除存储过程
DROP PROCEDURE proc_staffs;
DROP PROCEDURE proc_return;
--创建函数func_return.
CREATE OR REPLACE FUNCTION func_return returns void
language plpgsql
AS $$
DECLARE
v_num INTEGER := 1;
BEGIN
dbms_output.put_line(v_num);
RETURN;  --返回语句
END $$;
-- 调用函数func_return
CALL func_return();
1
-- 清除函数
DROP FUNCTION func_return;
```
