您的位置:首页 > 数据库 > Oracle

ESQL调oracle存储过程

2020-06-07 04:26 337 查看

ESQL采用的是预编译的模式,写sql相关的代码要用c风格的,c++风格的预编译过不了。

百度百科存储过程:“存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。”

首先你的有个oracle数据库以及装个oracle客户端,然后下载个sqldbx(免费)连数据库

先建一个测试用的表:

CREATE TABLE student(id INTEGER, name VARCHAR2(20), sex CHAR(1), math NUMBER, english NUMBER);

INSERT INTO student VALUES(1, '张三', 'm',80,90);
INSERT INTO student VALUES(2, '小红', 'f',90,90);
COMMIT;
View Code

SELECT * FROM STUDENT;

查到2条数据,接下来写一个插入一条数据的存储过程

 

CREATE OR REPLACE PROCEDURE  STD_PROC_INS  IS
BEGIN
INSERT INTO STUDENT VALUES(3, '王五', 'm', 60, 60);
COMMIT;
END STD_PROC_INS;
View Code

这个存储过程的名称就是STD_PROC_INS,接下来写c代码去调用。

EXEC SQL EXECUTE
BEGIN
STD_PROC_INS();
END;
END-EXEC;
View Code

一开始我忘记在END后面加;了,导致预编译一直报错。每调一次这个存储过程,表中就多一条记录。

接下来做一个查询返回一条记录的存储过程。

CREATE OR REPLACE PROCEDURE STD_PROC_QUERY(tmp_name IN VARCHAR2,
tmp_math OUT NUMBER,
tmp_eng OUT NUMBER) IS
num_math NUMBER;
num_eng NUMBER;

BEGIN
SELECT MATH, ENGLISH
INTO    num_math, num_eng
FROM KS.STUDENT
WHERE NAME = tmp_name;

tmp_math := num_math;
tmp_eng := num_eng;
END;
View Code

对应的c代码:

void test_query(char *name, ST_ERR_MSG *err_msg, int *math, int *eng)
{
EXEC SQL BEGIN DECLARE SECTION;
char mi_name[21] = {0};
int mo_math = 0;
int mo_eng = 0;
EXEC SQL END DECLARE SECTION;

strncpy(mi_name, name, sizeof(mi_name));

EXEC SQL EXECUTE
BEGIN
STD_PROC_QUERY (:mi_name, :mo_math, :mo_eng);
END;
END-EXEC;

*math = mo_math;
*eng = mo_eng;
// TODO处理下SQLCODE
}
View Code

调用这个函数,参数1是入参,输入要查询的人名,参数3和4就是查询出的结果值。

这表没有主键,所以同一个名字可以插入多条记录进去,当用名字查数据的时候,就会有多条数据。这个时候上面的存储过程执行就会报错,那么对返回结果是多条的,就得利用游标了。

 那么就得先声明一个游标my_cursor

1 CREATE OR REPLACE PACKAGE MYPACKAGE AS
2   TYPE my_cursor IS REF CURSOR;
3 END MYPACKAGE;
View Code

接下来在存储过程中使用这个游标

1 CREATE OR REPLACE PROCEDURE STD_PROC_QUERYS(tmp_name IN VARCHAR2,
2                                            P_CURSOR OUT mypackage.my_cursor) IS
3   num_1 NUMBER;
4   num_2 NUMBER;
5
6 BEGIN
7   num_1 := 0;
8   num_2 := 0;
9   OPEN P_CURSOR FOR
10     SELECT MATH, ENGLISH
11     INTO    num_1, num_2
12     FROM STUDENT
13     WHERE NAME = tmp_name;
14
15
16 END STD_PROC_QUERYS;
View Code

 写三个函数,一个取存储过程的值赋值给游标,一个是循环从游标内取值,一个是关闭游标

EXEC SQL BEGIN DECLARE SECTION;
// 输入参数
SQL_CURSOR emp_cursor;
EXEC SQL END DECLARE SECTION;
void b_test_querys_open(char *name, ST_ERR_MSG *pstruerr_msg)
{

EXEC SQL BEGIN DECLARE SECTION;
// 输入参数
char mi_name[12] = {0};
EXEC SQL END DECLARE SECTION;

/* allocate cursor variable */
EXEC SQL ALLOCATE :emp_cursor;

// 读输入参数
strncpy(mi_name, name, sizeof(mi_name));

EXEC SQL EXECUTE
BEGIN
STD_PROC_QUERYS(:mi_name, :emp_cursor);
END;
END-EXEC;

//TODO打开游标执行结果处理;
}
View Code
1 void b_test_querys_fetch(ST_ERR_MSG *pstruerr_msg, int *i, int *j)
2 {
3     EXEC SQL BEGIN DECLARE SECTION;
4         int num_math = 0;
5         int num_eng = 0;
6     EXEC SQL END DECLARE SECTION;
7
8     EXEC SQL FETCH :emp_cursor
9         INTO
10             :num_math, :num_eng;
11     // 取出游标数据执行结果处理
12     if(SQLCODE == FOUND)
13     {
14         //TODO BSQL_OK_DEAL_STD;
15     }
16     else if(SQLCODE == NOTFOUND)
17     {
18         //TODO BSQL_ERR_DEAL_STD("");
19         return;
20     }
21     else
22     {
23         //TODO BSQL_ERR_DEAL_STD("FETCH游标失败");
24         return;
25     }
26
27     *i = num_math;
28     *j = num_eng;
29 }
View Code
1 void b_test_querys_close()
2 {
3     // 关闭游标
4     EXEC SQL CLOSE :emp_cursor;
5     EXEC SQL FREE :emp_cursor;
6 }
View Code

以上代码的验证是在项目工程中,如果想从0开始写demo测试,需要做连接数据库的事情,可以参考以下两位作者的博文

http://www.cnblogs.com/liliu/archive/2011/06/22/2087546.html

http://blog.csdn.net/smallboy_5/article/details/3044255

转载于:https://www.cnblogs.com/ikel/p/7573710.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: