加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

通过一个示例学习oracle proc

发布时间:2020-12-12 15:43:11 所属栏目:百科 来源:网络整理
导读:我的系统环境: cent os6.5,本机装oralce 11g,数据库的某个用户下中有张表叫TFB_PHONE_CODE,存放手机号和验证码 从一个简单程序开始学习。 程序示例 程序名为test.pc,注意后缀。 #include stdio.h #include stdlib.h #include string.h #include sqlca.h EXE

我的系统环境:

cent os6.5,本机装oralce 11g,数据库的某个用户下中有张表叫TFB_PHONE_CODE,存放手机号和验证码

从一个简单程序开始学习。

程序示例

程序名为test.pc,注意后缀。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlca.h>
EXEC SQL INCLUDE SQLCA;
int main()
{
    EXEC SQL BEGIN DECLARE SECTION;
    char phone_str[13];
    char userid[9]="in***";
    char passwd[19]="in***";
    EXEC SQL END DECLARE SECTION;
    EXEC SQL CONNECT:userid IDENTIFIED BY :passwd;
    EXEC SQL SELECT PHONE INTO :phone_str
    FROM TFB_PHONE_CODE
    WHERE CODE = '6401';
    printf("phone = %sn",phone_str);
    EXEC SQL COMMIT WORK RELEASE;
    return 0;
}

代码分析

程序很简单。

EXEC SQL INCLUDE SQLCA;语句定义并描述了SQLCA的结构。SQLCA用于应用程序和数据库之间的通讯,其中的SQLCODE返回SQL语句执行后的结果状态。


在BEGIN DECLARE SECTION

END DECLARE SECTION
之间定义了宿主变量。宿主变量可被SQL语句引用,也可以被C语言语句引用。它用于将程序中的数据通过SQL语句传给数据库管理器,或从数据库管理器接收查询的结果。在SQL语句中,主变量前均有“:”标志以示区别。


访问数据库之前必须做CONNECT操作,以连接到某一个数据库上。用户名和密码的方式连接。注意宿主变量冒号的使用。


EXEC SQL SELECT PHONE INTO :firstname FROM TFB_PHONE_CODE WHERE CODE = '6401';

是一条选择语句。它将表TFB_PHONE_CODE中的code为“6401”的行数据的PHONE查出,并将它放在phone_str变量中。该语句返回一个结果。可以通过游标返回多个结果


EXEC SQL COMMIT WORK RELEASE;
是提交并释放数据库连接,当然select语句也可以不用提交。

编译运行

[**@localhost proc]$ proc test.pc
[**@localhost proc]$ ls
test.c  test.lis  test.pc

proc命令生成.c和.lis两个文件,我们要用到*.c文件来继续生成执行文件。

[**@localhost proc]$ gcc test.c
test.c:146:19: 错误:sqlca.h:没有那个文件或目录

这一步报错,说找不到sqlca.h文件,但是我用find查找了下,在$ORACLE_HOME/public/目录下找到了这个文件,但是gcc不能默认找到,那就手动加上路径再次编译。

[**@localhost proc]$ gcc -o test test.c -I $ORACLE_HOME/precomp/public
/tmp/ccfPShLN.o: In function `main':
test.c:(.text+0x23e): undefined reference to `sqlcxt'
test.c:(.text+0x3d9): undefined reference to `sqlcxt'
test.c:(.text+0x479): undefined reference to `sqlcxt'

前面的错误解决了,又有新的错误,谷歌了下,找到解决方案,继续编译。

[**@localhost proc]$ gcc -o test test.c -I $ORACLE_HOME/precomp/public -L $ORACLE_HOME/lib -l clntsh  
[**@localhost proc]$ ls
test  test.c  test.lis  test.pc

成功了!

[**@localhost proc]$ ./test 
./test: error while loading shared libraries: libclntsh.so.11.1: cannot open shared object file: No such file or directory

额,出错,找不到动态库。继续谷歌,说是要配置

LD_LIBRARY_PATH包含$ORALCE_HOME/lib,但是我看了下自己的.bash_profile,已经配置了,又执行了下
source命令,再次运行,成功。

[**@localhost proc]$ ./test 
phone = 138*********

游标的使用

什么是游标

我理解游标的作用是快速定位,像个标尺一样把检索的数据结果保存在内存中,并做好标记,读取时就很快。

使用示例

还是基于上面的代码修改

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlca.h>
EXEC SQL INCLUDE SQLCA;
int main()
{
    EXEC SQL BEGIN DECLARE SECTION;
    char phone_str[13];
    char userid[9]="in***";
    char passwd[19]="in***";
    char sql_str[256] = "select phone from TFB_PHONE_CODE where code ='6401'";
    EXEC SQL END DECLARE SECTION;
    EXEC SQL CONNECT:userid IDENTIFIED BY :passwd;

    EXEC SQL PREPARE sql_find_phone from :sql_str;
    EXEC SQL DECLARE CurPhone CURSOR FOR sql_find_phone;

    EXEC SQL OPEN CurPhone;

   for(;;)
   {
       if(sqlca.sqlcode == 1403)
                break;

        EXEC SQL FETCH CurPhone INTO:phone_str;
        printf("phone = %sn",phone_str);
        printf("sqlca.sqlcode = %dn",sqlca.sqlcode);
   }

   printf("sqlca.sqlerrd[2] = %dn",sqlca.sqlerrd[2]);
    EXEC SQL CLOSE CurPhone;
    EXEC SQL COMMIT WORK RELEASE;
    return 0;
}

EXEC SQL DECLARE CurPhone CURSOR FOR sql_find_phone
这句是对一个检索语句申请游标

EXEC SQL OPEN CurPhone;
打开游标。

EXEC SQL FETCH CurPhone INTO:phone_str;
循环体中,把检索的结果放进phone_str这个变量。

sqlca.sqlerrd[2]
当sql语句成功时,保存当前sql语句处理的行数,它要在fetch后才会生效。这个示例中符合条件的记录是两条,所以sqlca.sqlerrd[2]的值是2。

输出结果:

phone = 138******* 
sqlca.sqlcode = 0

phone = 159******
sqlca.sqlcode = 0

phone = 159******
sqlca.sqlcode = 1403

sqlca.sqlerrd[2] = 2

注意第三笔记录读取的号码其实还是第二笔的,因为已经没有记录了,没取到还是缓存的上次的值。

其实还可以换一种写法,这样输出就比较清晰了:

int main()
{
    EXEC SQL BEGIN DECLARE SECTION;
    char phone_str[13];
    char userid[9]="in***";
    char passwd[19]="in***";
    char sql_str[256] = "select phone from TFB_PHONE_CODE where code ='6401'";
    EXEC SQL END DECLARE SECTION;
    EXEC SQL CONNECT:userid IDENTIFIED BY :passwd;

    EXEC SQL PREPARE sql_find_phone from :sql_str;
    EXEC SQL DECLARE CurPhone CURSOR FOR sql_find_phone;

    EXEC SQL OPEN CurPhone;

   EXEC SQL WHENEVER NOT FOUND DO BREAK;

   for(;;)
   {   

        EXEC SQL FETCH CurPhone INTO:phone_str;
        printf("phone = %sn",sqlca.sqlerrd[2]);
    EXEC SQL CLOSE CurPhone;
    EXEC SQL COMMIT WORK RELEASE;
    return 0;
}

输出

phone = 138***** 
sqlca.sqlcode = 0
phone = 159****
sqlca.sqlcode = 0
sqlca.sqlerrd[2] = 2

EXEC SQL WHENEVER NOT FOUND DO BREAK; 相当于给循环设置了一个条件,如果没有记录了,就退出。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读