通过一个示例学习oracle proc

前端之家收集整理的这篇文章主要介绍了通过一个示例学习oracle proc前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我的系统环境:

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 = %s\n",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 = %s\n",phone_str);
        printf("sqlca.sqlcode = %d\n",sqlca.sqlcode);
   }

   printf("sqlca.sqlerrd[2] = %d\n",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 = %s\n",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; 相当于给循环设置了一个条件,如果没有记录了,就退出

猜你在找的Oracle相关文章