zoukankan      html  css  js  c++  java
  • ESQL调oracle存储过程

    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

  • 相关阅读:
    DOS命令大全 1 attrib,delete等 外部 内部 命令都有
    css图像映射
    简单的css样式控制分页效果
    (转)AjaxPro实现机制探讨——Ajax是如何调用服务器端C#方法?
    学习笔记ADO.Net方面
    一个挺好用的数据库操作类
    .net开发人员应该知道(二)
    js与C#之间相互调用的一些方法
    JS 事件大全
    .net开发人员应该知道(一)
  • 原文地址:https://www.cnblogs.com/ikel/p/7573710.html
Copyright © 2011-2022 走看看