zoukankan      html  css  js  c++  java
  • [转]Oracle学习记录 九 Prc C学习

            经过前面的了解,现在想用C语言来编程了,搜索了很多东西,后来决定先用Pro C来进行学习

    在安装完Oracle数据库后就可以进行编程了,里面有一个命令proc就是对程序进行预编译的。

    在这记一下,这是一个学习PL/SQL的网站,挺好的

    http://www.cnblogs.com/huyong/archive/2012/07/30/2614563.html

    创建用户是

    create user xx identified by xx account unlock;

    grant connect, resource to xx;

    第一句是创建用户xx,并且密码是xx,并且解锁用户

    下面那句是给用户连接权限和一般操作自己用户下的表的权限等。

    写一个test.pc然后

    proc iname=test.pc oname=test.c

    但是我这怎么也不行,一直出问题

    后来我用

    proc PARSE=NONE CODE=KR_C LINE=YES INAME=test.pc MODE=ORACLE DBMS=V8 UNSAFE_NULL=YES

    后来补充:之后我大概看了一下这些编译指令,我得记录一下:

    1. UNSAFE_NULL=YES    这是避免这个错误:3.6.121405 错误(Fetch column values is null)

    也就是允许应用程序从数据库中检索出NULL到宿主变量而不产生错误。

    2. CODE=KR_C  这是指代码风格吧,可以是CPP、ANSI_C、KR_C

    其中ANSI_C和KR_C都是C语言风格,CPP是C++的

    3. 命令行参数MAXLITERAL 指定了其预编译成C/C++语言源
    文件时所转换的最长单行代码长度,默认为1024 字

    4. 在Pro*C/C++预编译器的参数中如果AUTO_CONNECT=true,则可以在源程序中
    不显视的连接数据库  ------- 书里是这么说的,但是我没有连接成功,应该是设置有问题,等着以后解决。

    5. 如果在一个应用程序中,需要同时使用大量游标,应该调整 proc 命令行参数
    MAXOPENCURSORS

    6. CLOSE_ON_COMMIT 预编译选项决定了是否在COMMIT 语句时自动关闭事务中的游
    标,当MODE=ansi 时,CLOSE_ON_COMMIT 默认为yes。明确的指定CLOSE_ON_COMMIT
    为no,则COMMIT 时不关闭游标,游标不需要重新打开,可以提升应用程序性能

    这下才生成了test.c文件

    之后用gcc编译

    gcc test.c -L${ORACLE_HOME}/lib -lclntsh -lecpg

    这里我明明把-L的路径配置了,但是为什么还是要在这里写上呢

    遇到的问题还需要进一步处理。

    1. test.pc

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *userid="scott"; 
    char *passwd="xx";
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        EXEC SQL CONNECT :userid IDENTIFIED BY :passwd;
        if (sqlca.sqlcode == 0) {
            printf("ok
    ");
        } else {
            printf("false
    ");
            exit(1);
        }
        EXEC SQL SELECT * FROM EMP;
        return 0;
    }

    这里的变量声明在

    EXEC SQL BEGIN DECLARE SECTION;

    ...在这里

    EXEC SQL END DECLARE SECTION;

    执行SQL语句前面用EXEC SQL

    执行PL/SQL前面用

    EXEC SQL EXECUTE  开始

    END-EXEC  结束

    如果要根据条件进行预编译,就像c中的#ifdef这样的

    EXEC ORACLE DEFINE xx;

    EXEC ORACLE IFDEF xx;

    EXEC ORACLE IFNDEF xx;

    EXEC ORACLE ELSE;

    EXEC ORACLE ENDIF;

    并且这个定义可以在proc预处理时加上:proc 命令行加入参数DEFINE=xx

    在里面还有一个指示变量概念,INDICATOR 表示,下面是指示变量相应值代表的含义。

    0 操作成功
    -1 该指示变量对应的宿主变量返回了或插入、更新成了NULL 值
    -2 从数据库存放数据到对应的宿主变量时,数据超长,并且不能推断出截断了多
    少字节的长度
    >0 在FETHC 或SELECT 语句时,因数据超长而被截断存放在了对应的宿主变量
    中,指示变量存放对应列的长度

    这里我还用了select这句,要怎么显示结果呢?

    经过了一会的琢磨,看了看相关文章,总算是弄出个差不多的了,直接贴上代码来看看。

    2. connect.pc

    #include <stdio.h> 
    #include <stdlib.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *username = "scott";
    char *passwd = "xx";
    char name[14][10];
    int sal[14];
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        int i;
        EXEC SQL CONNECT :username IDENTIFIED BY :passwd;
        EXEC SQL SELECT ename, sal INTO :name, :sal
            FROM EMP;
        for (i = 0; i < 14; i ++) {
            printf("%s	%d
    ", name[i], sal[i]);
        }
        return 0;
    }

    我定义的变量name是一个二维数组,每个都是10的大小,这个和表emp中ename的是一致的,这样才可以用来接收ename

    的值,类型必须保存一致。

    用INTO把相应的值弄入相应变量,然后打印输出。

    这里我还没有解决那个proc编译选项的问题,还是需要那个长的那么来编译。

    3. insert.pc

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *username = "scott";
    char *passwd = "xx";
    int emp_number;
    char emp_name[10];
    int emp_sal;
    int dept_number;
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        EXEC SQL CONNECT :username IDENTIFIED BY :passwd;
        strcpy(emp_name, "bxx");
        int emp_number = 8888;
        int emp_sal = 8888;
        int dept_number = 40;
        EXEC SQL INSERT INTO EMP (empno, ename, sal, deptno)
            VALUES (:emp_number, :emp_name, :emp_sal, :dept_number);
        EXEC SQL COMMIT WORK RELEASE; 
        return 0;
    }

    这里是调用 INSERT来写入数据,并且写入后要COMMIT,这样数据库才有变化。

    其实因为我SQL语句也是刚学一两天,这个更是今天才开始学习,所以,我每一个命令就建一个.pc文件来练习,

    熟能生巧,现在不求巧,只求先用熟。

    4. update.pc

    #include <stdio.h>
    #include <stdlib.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *username = "scott";
    char *passwd = "xx";
    char *emp_job = "MANAGER";
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        EXEC SQL CONNECT :username IDENTIFIED BY :passwd;
        EXEC SQL UPDATE emp SET job=:emp_job
            WHERE ename='bxx';
        EXEC SQL COMMIT WORK RELEASE;
        return 0;
    }

    5. delete.pc

    #include <stdio.h>
    #include <stdlib.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *username = "scott";
    char *passwd = "xx";
    char *emp_name = "bxx";
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        EXEC SQL CONNECT :username IDENTIFIED BY :passwd;
        if (sqlca.sqlcode == 0) {
            printf("Connected to user: %s
    ", username);
        } else {
            printf("Connect to user %s failed
    ", username);
            exit(1);
        }
        EXEC SQL DELETE FROM emp
            WHERE ename=:emp_name;
        EXEC SQL COMMIT WORK RELEASE;
        return 0;
    }

    6. 下面是游标的,上面用过一次二维数组,如果用游标就不用二维数组了

    cursor.pc

    #include <stdio.h>
    #include <stdlib.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *username = "scott";
    char *passwd = "xx";
    char emp_name[10];
    int sal;
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        EXEC SQL CONNECT :username IDENTIFIED BY :passwd;
        EXEC SQL DECLARE emp_cursor CURSOR FOR
            SELECT ename, sal
            FROM emp;
        EXEC SQL OPEN emp_cursor;
        int i;
        for (i = 0; i < 14; i ++) {
            EXEC SQL FETCH emp_cursor
                INTO :emp_name, :sal;
            printf("%s	%d
    ", emp_name, sal);
        }
        EXEC SQL CLOSE emp_cursor;
        return 0;
    }

    原本我没有用for里面记14次的,而是用的while(1),

    然后用了那个NOT FOUND,但是怎么就不行呢,一直循环下去了。也用了if (sqlca.sqlcode == 1403)

    都是无限循环,根本停不下来,还需要进一步学习,怎么用这块,错误的代码我也贴一下。

    问题算是解决了一半,可以跳出来了,原因是:那个头文件#inclucde <sqlca.h>,我把它改成

    EXEC SQL INCLUDE sqlca

    用这样的就可以结束循环了,并且那个sqlca.sqlcode也是1403了。

    但是关键是这个到底是怎么回事呢?我想应该和proc预编译有关,那个PARSE=NONE,但是如果改成别的,

    一直编译不过去。新人就是会遇到各种问题。

    #include <stdio.h>
    #include <stdlib.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *username = "scott";
    char *passwd = "xx";
    char emp_name[10];
    int sal;
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        EXEC SQL CONNECT :username IDENTIFIED BY :passwd;
        EXEC SQL DECLARE emp_cursor CURSOR FOR
            SELECT ename, sal
            FROM emp;
        EXEC SQL OPEN emp_cursor;
        EXEC SQL WHENEVER NOT FOUND GOTO zheli;
        int i;
        while (1) {
            EXEC SQL FETCH emp_cursor
                INTO :emp_name, :sal;
            if (sqlca.sqlcode == 1403)
                break;
            printf("%s	%d
    ", emp_name, sal);
        }
    zheli:
        EXEC SQL CLOSE emp_cursor;
        return 0;
    }

    两种我都用上了,就是不行,还是无限循环。下面有一个例子用的是break,这个我也用过了就是不行

    #include <stdio.h>
    #include <stdlib.h>
    #include <sqlca.h>
    EXEC SQL BEGIN DECLARE SECTION;
    char *username = "scott";
    char *passwd = "xx";
    char emp_name[10];
    int sal;
    EXEC SQL END DECLARE SECTION;
    int main(int argc, char *argv[])
    {
        EXEC SQL CONNECT :username IDENTIFIED BY :passwd;
        EXEC SQL DECLARE emp_cursor CURSOR FOR
            SELECT ename, sal
            FROM emp;
        EXEC SQL OPEN emp_cursor;
        EXEC SQL WHENEVER NOT FOUND DO break;
        int i;
        while (1) {
            EXEC SQL FETCH emp_cursor
                INTO :emp_name, :sal;
            printf("%s	%d
    ", emp_name, sal);
        }
        EXEC SQL CLOSE emp_cursor;
        return 0;
    }
    原文地址:http://my.oschina.net/bxxfighting/blog/383247
  • 相关阅读:
    Mysql:Group Replication & Replication
    使用winsw包装服务将nginx包装为Windows服务
    Nginx的一些常用配置
    在ASP.NET Core 2.0中使用Facebook进行身份验证
    展现层实现增删改查
    ABP创建应用服务
    ABP领域层定义仓储并实现
    ABP领域层创建实体
    通过模板创建一个ABP项目
    Android UI组件:布局管理器
  • 原文地址:https://www.cnblogs.com/schowen/p/5579110.html
Copyright © 2011-2022 走看看