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
  • 相关阅读:
    韩式英语
    Daily dictation 听课笔记
    words with same pronunciation
    you will need to restart eclipse for the changes to take effect. would you like to restart now?
    glottal stop(britain fountain mountain)
    education 的发音
    第一次用Matlab 的lamada语句
    SVN的switch命令
    String的split
    SVN模型仓库中的资源从一个地方移动到另一个地方的办法(很久才解决)
  • 原文地址:https://www.cnblogs.com/schowen/p/5579110.html
Copyright © 2011-2022 走看看