-
示例 gaussdb=# DROP SCHEMA IF EXISTS hr CASCADE;
gaussdb=# CREATE SCHEMA hr;
CREATE SCHEMA
gaussdb=# SET CURRENT_SCHEMA = hr;
SET
gaussdb=# CREATE TABLE staffs
(
staff_id NUMBER,
first_name VARCHAR2,
salary NUMBER
);
CREATE TABLE
gaussdb=# INSERT INTO staffs VALUES (200, 'mike', 5800);
INSERT 0 1
gaussdb=# INSERT INTO staffs VALUES (201, 'lily', 3000);
INSERT 0 1
gaussdb=# INSERT INTO staffs VALUES (202, 'john', 4400);
INSERT 0 1
--创建重载函数
gaussdb=# CREATE OR REPLACE PACKAGE pkg1
IS
PROCEDURE plus(var1 in int, var2 int, var3 out int);
PROCEDURE plus(var1 in out int);
END pkg1;
/
CREATE PACKAGE
gaussdb=# CREATE OR REPLACE PACKAGE BODY pkg1 IS
PROCEDURE plus(var1 in int, var2 int, var3 out int)
AS
BEGIN
var3 = var1 + var2 + 1;
END;
PROCEDURE plus(var1 in out int)
AS
BEGIN
var1 = var1 + 1;
END;
END pkg1;
/
CREATE PACKAGE BODY
--创建存储过程dynamic_proc
gaussdb=# CREATE OR REPLACE PROCEDURE dynamic_proc
AS
staff_id NUMBER(6) := 200;
first_name VARCHAR2(20);
salary NUMBER(8,2);
BEGIN
--执行匿名块
EXECUTE IMMEDIATE 'begin select first_name, salary into :first_name, :salary from hr.staffs where staff_id= :dno; end;'
USING OUT first_name, OUT salary, IN staff_id;
dbe_output.print_line(first_name|| ' ' || salary);
END;
/
CREATE PROCEDURE
--创建存储过程调用重载函数
gaussdb=# CREATE OR REPLACE PROCEDURE dynamic_proc1
AS
v_sql VARCHAR2(200);
var1 NUMBER(6) := 1;
var2 NUMBER(6) := 2;
var3 NUMBER(6);
BEGIN
v_sql := 'begin pkg1.plus(:1, :2, :3); end;';
EXECUTE IMMEDIATE v_sql USING var1, var2, out var3;
dbe_output.print_line('var3: ' || var3);
END;
/
CREATE PROCEDURE
--调用存储过程
gaussdb=# CALL dynamic_proc();
mike 5800.00
dynamic_proc
--------------
(1 row)
gaussdb=# CALL dynamic_proc1();
var3: 4
dynamic_proc1
---------------
(1 row)
--删除存储过程
gaussdb=# DROP PROCEDURE dynamic_proc;
DROP PROCEDURE
gaussdb=# DROP PROCEDURE dynamic_proc1;
DROP PROCEDURE
--开启dynamic_sql_check时报错示例
gaussdb=# SET behavior_compat_options = 'dynamic_sql_check';
SET
gaussdb=# CREATE OR REPLACE PROCEDURE test_proc_exception001(a out integer, b inout integer, c integer)
as
BEGIN
a := 1;
begin b := 1/0; end;
EXCEPTION
WHEN others THEN
b := 2;
END;
/
CREATE PROCEDURE
gaussdb=#
DECLARE
a integer := 1;
c integer;
BEGIN
execute immediate 'begin test_proc_exception001(:1,:2,:1); end;' using in out a, out c, a;
END;
/
ERROR: argnum not match in Dynamic SQL, using args num : 3 , actual sql args num : 2
CONTEXT: PL/pgSQL function inline_code_block line 4 at EXECUTE statement
--修改同名占位符
gaussdb=#
DECLARE
a integer := 1;
c integer;
BEGIN
execute immediate 'begin test_proc_exception001(:1,:2,:3); end;' using in out a, out c, a;
END;
/
ANONYMOUS BLOCK EXECUTE
gaussdb=# DROP PROCEDURE test_proc_exception001;
DROP PROCEDURE
-
语法 语法请参见图1。 图1 call_anonymous_block::= using_clause子句的语法参见图2。 图2 using_clause::= 对以上语法格式的解释如下: 匿名块程序实施部分,以BEGIN语句开始,以END语句停顿,以一个分号结束。 USING [IN|OUT|IN OUT] bind_argument,用于指定存放传递给存储过程参数值的变量。bind_argument前的修饰符与对应参数的修饰符一致。 匿名块中间的输入输出参数使用占位符来指明,要求占位符个数与参数个数相同,并且占位符所对应参数的顺序和USING中参数的顺序一致。 仅支持匿名块中调用SQL语句和存储过程时绑定参数,其余绑定参数场景皆不支持。例如:匿名块中使用表达式以及cursor等、匿名块中嵌套调用动态语句。 不支持匿名块中SELECT INTO语句调用含有出参的FUNCTION/PROCEDURE时,绑定出参。 不支持同一条语句同时使用匿名块内声明的变量和绑定参数。 不支持绑定参数时使用PERFORM关键字调用存储过程。 调用存储过程时,仅支持绑定参数直接作为出入参,不支持表达式形式(如“1+:va”)作为出入参,并且占位符名不能使用带引号的数字、字符或字符串。 绑定入参类型为refcursor时,存储过程内的修改与入参相互隔离。 打开dynamic_sql_check参数时,占位符个数与参数个数一致时使用同名占位符作为匿名块参数会报错,需修改为不同名参数,详见示例。
-
示例 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 --创建表
gaussdb=# CREATE TABLE sections_t1
(
section NUMBER(4) ,
section_name VARCHAR2(30),
manager_id NUMBER(6),
place_id NUMBER(4)
);
CREATE TABLE
--声明变量
gaussdb=# DECLARE
section NUMBER(4) := 280;
section_name VARCHAR2(30) := 'Info support';
manager_id NUMBER(6) := 103;
place_id NUMBER(4) := 1400;
new_colname VARCHAR2(10) := 'sec_name';
BEGIN
--执行查询
EXECUTE IMMEDIATE 'insert into sections_t1 values(:1, :2, :3, :4)'
USING section, section_name, manager_id,place_id;
--执行查询(重复占位符)
EXECUTE IMMEDIATE 'insert into sections_t1 values(:1, :2, :3, :1)'
USING section, section_name, manager_id;
--执行ALTER语句(建议采用“||”拼接数据库对象构造DDL语句)
EXECUTE IMMEDIATE 'alter table sections_t1 rename section_name to ' || new_colname;
END;
/
ANONYMOUS BLOCK EXECUTE
--查询数据
gaussdb=# SELECT * FROM sections_t1;
section | sec_name | manager_id | place_id
---------+--------------+------------+----------
280 | Info support | 103 | 1400
280 | Info support | 103 | 280
(2 rows)
--删除表
gaussdb=# DROP TABLE sections_t1;
DROP TABLE
-
语法 语法请参见图1。 图1 noselect::= using_clause子句的语法参见图2。 图2 using_clause::= 对以上语法格式的解释如下: USING IN bind_argument用于指定存放传递给动态SQL值的变量,在dynamic_noselect_string中存在占位符时使用,即动态SQL语句执行时,bind_argument将替换相对应的占位符。要注意的是,bind_argument只能是值、变量或表达式,不能是表名、列名和数据类型等数据库对象。如果存储过程需要通过声明参数传递数据库对象来构造动态SQL语句(常见于执行DDL语句时),建议采用连接运算符“||”拼接dynamic_select_clause。另外,动态语句允许出现重复的占位符,相同占位符只能与唯一一个bind_argument按位置一一对应。当设置GUC参数behavior_compat_options值为dynamic_sql_compat时,会按照占位符的顺序依次匹配USING子句bind_argument,重复的占位符不会再识别为同一个占位符(占位符名不能使用带引号的数字、字符或字符串)。
-
OPEN FOR 动态查询语句还可以使用OPEN FOR打开动态游标来执行。 语法参见图3。 图3 open_for::= 参数说明: cursor_name:要打开的游标名。 dynamic_string:动态查询语句。 USING value:在dynamic_string中存在占位符时使用。 游标的使用请参考游标。 示例 gaussdb=# CREATE SCHEMA hr;
CREATE SCHEMA
gaussdb=# SET CURRENT_SCHEMA = hr;
SET
gaussdb=# CREATE TABLE staffs
(
section_id NUMBER,
first_name VARCHAR2,
phone_number VARCHAR2,
salary NUMBER
);
CREATE TABLE
gaussdb=# INSERT INTO staffs VALUES (30, 'mike', '13567829252', 5800);
INSERT 0 1
gaussdb=# INSERT INTO staffs VALUES (40, 'john', '17896354637', 4000);
INSERT 0 1
gaussdb=# DECLARE
name VARCHAR2(20);
phone_number VARCHAR2(20);
salary NUMBER(8,2);
sqlstr VARCHAR2(1024);
TYPE app_ref_cur_type IS REF CURSOR; --定义游标类型
my_cur app_ref_cur_type; --定义游标变量
BEGIN
sqlstr := 'select first_name,phone_number,salary from hr.staffs
where section_id = :1';
OPEN my_cur FOR sqlstr USING '30'; --打开游标, using是可选的
FETCH my_cur INTO name, phone_number, salary; --获取数据
WHILE my_cur%FOUND LOOP
dbe_output.print_line(name||'#'||phone_number||'#'||salary);
FETCH my_cur INTO name, phone_number, salary;
END LOOP;
CLOSE my_cur; --关闭游标
END;
/
mike#13567829252#5800.00
ANONYMOUS BLOCK EXECUTE
-
EXECUTE IMMEDIATE 语法图请参见图1。 图1 EXECUTE IMMEDIATE dynamic_select_clause::= using_clause子句的语法图参见图2。 图2 using_clause::= 对以上语法格式的解释如下: define_variable:用于指定存放查询结果的变量。 USING IN bind_argument:用于指定存放传递给动态SQL值的变量,即在dynamic_select_string中存在占位符时使用。 USING OUT bind_argument:用于指定存放动态SQL返回值的变量。 查询语句中,into和out不能同时存在; 占位符命名以“:”开始,后面可跟数字、字符或字符串(不能使用带引号的数字、字符或字符串),与USING子句的bind_argument一一对应; bind_argument只能是值、变量或表达式,不能是表名、列名和数据类型等数据库对象,即不支持使用bind_argument为动态SQL语句传递模式对象。如果存储过程需要通过声明参数传递数据库对象来构造动态SQL语句(常见于执行DDL语句时),建议采用连接运算符“||”拼接dynamic_select_clause; 动态PL/SQL块允许出现重复的占位符,即相同占位符只能与USING子句的一个bind_argument按位置对应。当设置GUC参数behavior_compat_options值为dynamic_sql_compat时,会按照占位符的顺序依次匹配USING子句bind_argument,重复的占位符不会再识别为同一个占位符。 IMMEDIATE关键字仅用作语法兼容,无实际意义。 示例 gaussdb=# DROP SCHEMA IF EXISTS hr CASCADE;
NOTICE: drop cascades to table staffs
DROP SCHEMA
gaussdb=# CREATE SCHEMA hr;
CREATE SCHEMA
gaussdb=# SET CURRENT_SCHEMA = hr;
SET
gaussdb=# CREATE TABLE staffs
(
staff_id NUMBER,
first_name VARCHAR2,
salary NUMBER
);
CREATE TABLE
gaussdb=# INSERT INTO staffs VALUES (200, 'mike', 5800);
INSERT 0 1
gaussdb=# INSERT INTO staffs VALUES (201, 'lily', 3000);
INSERT 0 1
gaussdb=# INSERT INTO staffs VALUES (202, 'john', 4400);
INSERT 0 1
--从动态语句检索值(INTO 子句):
gaussdb=# DECLARE
staff_count VARCHAR2(20);
BEGIN
EXECUTE IMMEDIATE 'select count(*) from hr.staffs'
INTO staff_count;
dbe_output.print_line(staff_count);
END;
/
3
ANONYMOUS BLOCK EXECUTE
--传递并检索值(INTO子句用在USING子句前):
gaussdb=# CREATE OR REPLACE PROCEDURE dynamic_proc
AS
staff_id NUMBER(6) := 200;
first_name VARCHAR2(20);
salary NUMBER(8,2);
BEGIN
EXECUTE IMMEDIATE 'select first_name, salary from hr.staffs where staff_id = :1'
INTO first_name, salary
USING IN staff_id;
dbe_output.print_line(first_name || ' ' || salary);
END;
/
CREATE PROCEDURE
--调用存储过程
gaussdb=# CALL dynamic_proc();
mike 5800.00
dynamic_proc
--------------
(1 row)
--删除存储过程
gaussdb=# DROP PROCEDURE dynamic_proc;
DROP PROCEDURE
-
示例 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 --创建存储过程proc_add。
gaussdb=# CREATE OR REPLACE PROCEDURE proc_add
(
param1 in INTEGER,
param2 out INTEGER,
param3 in INTEGER
)
AS
BEGIN
param2:= param1 + param3;
END;
/
gaussdb=# DECLARE
input1 INTEGER:=1;
input2 INTEGER:=2;
statement VARCHAR2(200);
param2 INTEGER;
BEGIN
--声明调用语句
statement := 'call proc_add(:col_1, :col_2, :col_3)';
--执行语句
EXECUTE IMMEDIATE statement
USING IN input1, OUT param2, IN input2;
dbe_output.print_line('result is: '||to_char(param2));
END;
/
result is: 3
ANONYMOUS BLOCK EXECUTE
--删除存储过程
gaussdb=# DROP PROCEDURE proc_add;
-
OPEN FOR 动态查询语句还可以使用OPEN FOR打开动态游标来执行。 语法参见图3。 图3 open_for::= 参数说明: cursor_name:要打开的游标名。 dynamic_string:动态查询语句。 USING value:在dynamic_string中存在占位符时使用。 游标的使用请参考游标。 示例 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 gaussdb=# CREATE SCHEMA hr;
gaussdb=# SET CURRENT_SCHEMA = hr;
gaussdb=# DROP TABLE IF EXISTS staffs;
gaussdb=# CREATE TABLE staffs
(
section_id NUMBER,
first_name VARCHAR2,
phone_number VARCHAR2,
salary NUMBER
);
gaussdb=# INSERT INTO staffs VALUES (30, 'mike', '13567829252', 5800);
gaussdb=# INSERT INTO staffs VALUES (40, 'john', '17896354637', 4000);
gaussdb=# DECLARE
name VARCHAR2(20);
phone_number VARCHAR2(20);
salary NUMBER(8,2);
sqlstr VARCHAR2(1024);
TYPE app_ref_cur_type IS REF CURSOR; --定义游标类型
my_cur app_ref_cur_type; --定义游标变量
BEGIN
sqlstr := 'select first_name,phone_number,salary from hr.staffs
where section_id = :1';
OPEN my_cur FOR sqlstr USING '30'; --打开游标, using是可选的
FETCH my_cur INTO name, phone_number, salary; --获取数据
WHILE my_cur%FOUND LOOP
dbe_output.print_line(name||'#'||phone_number||'#'||salary);
FETCH my_cur INTO name, phone_number, salary;
END LOOP;
CLOSE my_cur; --关闭游标
END;
/
mike#13567829252#5800.00
ANONYMOUS BLOCK EXECUTE
gaussdb=# DROP TABLE staffs;
-
EXECUTE IMMEDIATE 语法图请参见图1。 图1 EXECUTE IMMEDIATE dynamic_select_clause::= using_clause子句的语法图参见图2。 图2 using_clause::= 对以上语法格式的解释如下: define_variable,用于指定存放查询结果的变量。 USING IN bind_argument,用于指定存放传递给动态SQL值的变量,即在dynamic_select_string中存在占位符时使用。 USING OUT bind_argument,用于指定存放动态SQL返回值的变量。 查询语句中,into和out不能同时存在; 占位符命名以“:”开始,后面可跟数字、字符或字符串(不能使用带引号的数字、字符或字符串),与USING子句的bind_argument一一对应; bind_argument只能是值、变量或表达式,不能是表名、列名、数据类型等数据库对象,即不支持使用bind_argument为动态SQL语句传递模式对象。如果存储过程需要通过声明参数传递数据库对象来构造动态SQL语句(常见于执行DDL语句时),建议采用连接运算符“||”拼接dynamic_select_clause; 动态PL/SQL块允许出现重复的占位符,即相同占位符只能与USING子句的一个bind_argument按位置对应。当设置GUC参数behavior_compat_options值为dynamic_sql_compat时,会按照占位符的顺序依次匹配USING子句bind_argument,重复的占位符不会再识别为同一个占位符。 IMMEDIATE关键字仅用作语法兼容,无实际意义。 示例 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 gaussdb=# DROP SCHEMA IF EXISTS hr CASCADE;
gaussdb=# CREATE SCHEMA hr;
gaussdb=# SET CURRENT_SCHEMA = hr;
gaussdb=# CREATE TABLE staffs
(
staff_id NUMBER,
first_name VARCHAR2,
salary NUMBER
);
gaussdb=# INSERT INTO staffs VALUES (200, 'mike', 5800);
gaussdb=# INSERT INTO staffs VALUES (201, 'lily', 3000);
gaussdb=# INSERT INTO staffs VALUES (202, 'john', 4400);
--从动态语句检索值(INTO 子句):
gaussdb=# DECLARE
staff_count VARCHAR2(20);
BEGIN
EXECUTE IMMEDIATE 'select count(*) from hr.staffs'
INTO staff_count;
dbe_output.print_line(staff_count);
END;
/
3
ANONYMOUS BLOCK EXECUTE
--传递并检索值(INTO子句用在USING子句前):
gaussdb=# CREATE OR REPLACE PROCEDURE dynamic_proc
AS
staff_id NUMBER(6) := 200;
first_name VARCHAR2(20);
salary NUMBER(8,2);
BEGIN
EXECUTE IMMEDIATE 'select first_name, salary from hr.staffs where staff_id = :1'
INTO first_name, salary
USING IN staff_id;
dbe_output.print_line(first_name || ' ' || salary);
END;
/
CREATE PROCEDURE
--调用存储过程
gaussdb=# CALL dynamic_proc();
mike 5800.00
dynamic_proc
--------------
(1 row)
--删除存储过程
gaussdb=# DROP PROCEDURE dynamic_proc;
-
语法 动态调用匿名块语法如图1所示。 图1 call_anonymous_block::= using_clause子句的语法如图2所示。 图2 using_clause::= 对以上语法格式的解释如下: 匿名块程序实施部分,以BEGIN语句开始,以END语句停顿,以一个分号结束。 USING [IN|OUT|IN OUT] bind_argument,用于指定存放传递给存储过程参数值的变量。bind_argument前的修饰符与对应参数的修饰符一致。 匿名块中间的输入输出参数使用占位符来指明,要求占位符个数与参数个数相同,并且占位符所对应参数的顺序和USING中参数的顺序一致。 仅支持匿名块中调用SQL语句和存储过程时绑定参数,其余绑定参数场景皆不支持。例如:匿名块中使用表达式以及cursor等、匿名块中嵌套调用动态语句。 不支持匿名块中SELECT INTO语句调用含有出参的FUNCTION/PROCEDURE时,绑定出参。 不支持同一条语句同时使用匿名块内声明的变量和绑定参数。 不支持绑定参数时使用PERFORM关键字调用存储过程。 调用存储过程时,仅支持绑定参数直接作为出入参,不支持表达式形式(如“1+:va”)作为出入参,并且占位符名不能使用带引号的数字、字符或字符串。 IMMEDIATE关键字仅用作语法兼容,无实际意义。 绑定入参类型为refcursor时,存储过程内的修改与入参相互隔离。 打开dynamic_sql_check参数时,占位符个数与参数个数一致时使用同名占位符作为匿名块参数会报错,需修改为不同名参数,详见示例。
-
示例 gaussdb=# DROP SCHEMA IF EXISTS hr CASCADE;
gaussdb=# CREATE SCHEMA hr;
CREATE SCHEMA
gaussdb=# SET CURRENT_SCHEMA = hr;
SET
gaussdb=# CREATE TABLE staffs
(
staff_id NUMBER,
first_name VARCHAR2,
salary NUMBER
);
CREATE TABLE
gaussdb=# INSERT INTO staffs VALUES (200, 'mike', 5800);
INSERT 0 1
gaussdb=# INSERT INTO staffs VALUES (201, 'lily', 3000);
INSERT 0 1
gaussdb=# INSERT INTO staffs VALUES (202, 'john', 4400);
INSERT 0 1
--创建重载函数
gaussdb=# CREATE OR REPLACE PACKAGE pkg1
IS
PROCEDURE plus(var1 in int, var2 int, var3 out int);
PROCEDURE plus(var1 in out int);
END pkg1;
/
CREATE PACKAGE
gaussdb=# CREATE OR REPLACE PACKAGE BODY pkg1 IS
PROCEDURE plus(var1 in int, var2 int, var3 out int)
AS
BEGIN
var3 = var1 + var2 + 1;
END;
PROCEDURE plus(var1 in out int)
AS
BEGIN
var1 = var1 + 1;
END;
END pkg1;
/
CREATE PACKAGE BODY
--创建存储过程dynamic_proc
gaussdb=# CREATE OR REPLACE PROCEDURE dynamic_proc
AS
staff_id NUMBER(6) := 200;
first_name VARCHAR2(20);
salary NUMBER(8,2);
BEGIN
--执行匿名块
EXECUTE IMMEDIATE 'begin select first_name, salary into :first_name, :salary from hr.staffs where staff_id= :dno; end;'
USING OUT first_name, OUT salary, IN staff_id;
dbe_output.print_line(first_name|| ' ' || salary);
END;
/
CREATE PROCEDURE
--创建存储过程调用重载函数
gaussdb=# CREATE OR REPLACE PROCEDURE dynamic_proc1
AS
v_sql VARCHAR2(200);
var1 NUMBER(6) := 1;
var2 NUMBER(6) := 2;
var3 NUMBER(6);
BEGIN
v_sql := 'begin pkg1.plus(:1, :2, :3); end;';
EXECUTE IMMEDIATE v_sql USING var1, var2, out var3;
dbe_output.print_line('var3: ' || var3);
END;
/
CREATE PROCEDURE
--调用存储过程
gaussdb=# CALL dynamic_proc();
mike 5800.00
dynamic_proc
--------------
(1 row)
gaussdb=# CALL dynamic_proc1();
var3: 4
dynamic_proc1
---------------
(1 row)
--删除存储过程
gaussdb=# DROP PROCEDURE dynamic_proc;
DROP PROCEDURE
gaussdb=# DROP PROCEDURE dynamic_proc1;
DROP PROCEDURE
--开启dynamic_sql_check时报错示例
gaussdb=# SET behavior_compat_options = 'dynamic_sql_check';
SET
gaussdb=# CREATE OR REPLACE PROCEDURE test_proc_exception001(a out integer, b inout integer, c integer)
as
BEGIN
a := 1;
begin b := 1/0; end;
EXCEPTION
WHEN others THEN
b := 2;
END;
/
CREATE PROCEDURE
gaussdb=#
DECLARE
a integer := 1;
c integer;
BEGIN
execute immediate 'begin test_proc_exception001(:1,:2,:1); end;' using in out a, out c, a;
END;
/
ERROR: argnum not match in Dynamic SQL, using args num : 3 , actual sql args num : 2
CONTEXT: PL/pgSQL function inline_code_block line 4 at EXECUTE statement
--修改同名占位符
gaussdb=#
DECLARE
a integer := 1;
c integer;
BEGIN
execute immediate 'begin test_proc_exception001(:1,:2,:3); end;' using in out a, out c, a;
END;
/
ANONYMOUS BLOCK EXECUTE
gaussdb=# DROP PROCEDURE test_proc_exception001;
DROP PROCEDURE
-
EXECUTE IMMEDIATE 语法图请参见图1。 图1 EXECUTE IMMEDIATE dynamic_select_clause::= using_clause子句的语法图参见图2。 图2 using_clause-1 对以上语法格式的解释如下: define_variable,用于指定存放单行查询结果的变量。 USING IN bind_argument,用于指定存放传递给动态SQL值的变量,即在dynamic_select_string中存在占位符时使用。 USING OUT bind_argument,用于指定存放动态SQL返回值的变量。 查询语句中,into和out不能同时存在; 占位符命名以“:”开始,后面可跟数字、字符或字符串,与USING子句的bind_argument一一对应; bind_argument只能是值、变量或表达式,不能是表名、列名、数据类型等数据库对象,即不支持使用bind_argument为动态SQL语句传递模式对象。如果存储过程需要通过声明参数传递数据库对象来构造动态SQL语句(常见于执行DDL语句时),建议采用连接运算符“||”拼接dynamic_select_clause; 动态PL/SQL块允许出现重复的占位符,即相同占位符只能与USING子句的一个bind_argument按位置对应。 示例 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 --从动态语句检索值(INTO 子句):
DECLARE
staff_count VARCHAR2(20);
BEGIN
EXECUTE IMMEDIATE 'select count(*) from staffs'
INTO staff_count;
dbms_output.put_line(staff_count);
END;
/
--传递并检索值(INTO子句用在USING子句前):
CREATE OR REPLACE PROCEDURE dynamic_proc
AS
staff_id NUMBER(6) := 200;
first_name VARCHAR2(20);
salary NUMBER(8,2);
BEGIN
EXECUTE IMMEDIATE 'select first_name, salary from staffs where staff_id = :1'
INTO first_name, salary
USING IN staff_id;
dbms_output.put_line(first_name || ' ' || salary);
END;
/
--调用存储过程
CALL dynamic_proc();
--删除存储过程
DROP PROCEDURE dynamic_proc;
-
OPEN FOR 动态查询语句还可以使用OPEN FOR打开动态游标来执行。 语法参见图3。 图3 open_for::= 参数说明: cursor_name:要打开的游标名。 dynamic_string:动态查询语句。 USING value:在dynamic_string中存在占位符时使用。 游标的使用请参考
GaussDB (DWS)存储过程游标。 示例 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 DECLARE
name VARCHAR2(20);
phone_number VARCHAR2(20);
salary NUMBER(8,2);
sqlstr VARCHAR2(1024);
TYPE app_ref_cur_type IS REF CURSOR; --定义游标类型
my_cur app_ref_cur_type; --定义游标变量
BEGIN
sqlstr := 'select first_name,phone_number,salary from staffs
where section_id = :1';
OPEN my_cur FOR sqlstr USING '30'; --打开游标, using是可选的
FETCH my_cur INTO name, phone_number, salary; --获取数据
WHILE my_cur%FOUND LOOP
dbms_output.put_line(name||'#'||phone_number||'#'||salary);
FETCH my_cur INTO name, phone_number, salary;
END LOOP;
CLOSE my_cur; --关闭游标
END;
/
-
示例 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 --创建存储过程proc_add。
gaussdb=# CREATE OR REPLACE PROCEDURE proc_add
(
param1 in INTEGER,
param2 out INTEGER,
param3 in INTEGER
)
AS
BEGIN
param2:= param1 + param3;
END;
/
gaussdb=# DECLARE
input1 INTEGER:=1;
input2 INTEGER:=2;
statement VARCHAR2(200);
param2 INTEGER;
BEGIN
--声明调用语句
statement := 'call proc_add(:col_1, :col_2, :col_3)';
--执行语句
EXECUTE IMMEDIATE statement
USING IN input1, OUT param2, IN input2;
dbe_output.print_line('result is: '||to_char(param2));
END;
/
result is: 3
ANONYMOUS BLOCK EXECUTE
--删除存储过程。
gaussdb=# DROP PROCEDURE proc_add;
-
语法 语法请参见图1。 图1 call_procedure::= using_clause子句的语法参见图2。 图2 using_clause::= 对以上语法格式的解释如下: CALL procedure_name,调用存储过程。 [:placeholder1,:placeholder2,…],存储过程参数占位符列表,占位符名不能使用带引号的数字、字符或字符串。占位符个数与参数个数相同。 USING [IN|OUT|IN OUT] bind_argument,用于指定存放传递给存储过程参数值的变量。bind_argument前的修饰符与对应参数的修饰符一致。 不支持调用带有占位符的重载函数或者存储过程。