Pro*C概述

Pro*C概述

一. Pro*C概述

Oracle支持在6种高级语言中嵌入SQL语句,他们分别是CFORTRANPASCALCOBOLPL/IAda。这些语言统称为宿主语言,用它们开发的应用程序叫PRO程序。如果宿主语言是C,则相应的程序就叫Pro*C

Pro*C中可以嵌入SQL语句,利用这些SQL语句可以完成动态的建立,修改和删除数据库中的表,也可以查询,插入,修改和删除数据库表中的行,还可以实现事务的提交和回滚。

二. 应用Pro*C的优缺点

1)  优点:

1.         把过程化语言和非过程语言相结合,可满足各种复杂要求的应用开发。

2.         提高应用程序的执行效率,特别是同ODBC方式的应用相比。

2)  缺点:

1.         可移植性差。

2.         需要预编译。

三. 开发环境

(ア)    OSWindows

(イ)    DBOracle

(ウ)    预编译环境:Oracle附带的Pro*C/C++以及Oracle提供的库文件

(エ)    编译环境:VCC编译器

四. 编译过程

Pro*C源代码 -----C源代码 -----〉可执行程序

                预编译       编译连接

五. Pro*C/C++使用简介

(ア)    位置:Start->Program->Oracle-OraHome81->Application Development->Pro C_C++

(イ)    界面

功能介绍:使用方法

六. Oracle预编译程序的功能和特点如下

(ア)    能用6种高级程序设计语言中的任何一种来编写程序

(イ)    嵌入的SQL语句完全符合ANSI标准

(ウ)    可采用动态SQL技术

(エ)    能开发出满足各种需求的应用程序

(オ)    自动实现内部和外部数据类型的转换

(カ)    可嵌入PL/SQL

(キ)    能在命令行和程序行上指定预编译可选项

(ク)    能分别与编译

(ケ)    能检查SQL语句和PL/SQL块的语法和语义

(コ)    可利用SQL*Net并行存取多个节点上的Oracle数据

(サ)    可使用数组SQL变量

(シ)    可用高级语言编写SQL*Forms的用户出口

(ス)    能用SQLCAORACA进行错误诊断

七. 关于书写格式的说明

(ア)    采用缩进方式编写代码

(イ)    可以使用/*…*/Pro*C的代码进行注释。

(ウ)    嵌入式SQL语句的关键字应大写。

 


Pro*C程序设计的基础知识

一. SQL变量

(ア)    Pro*C程序中含有CSQL两种语言的语句,为了解决他们之间传递信息的问题,特引入了一种变量,称为SQL变量。

(イ)    SQL变量可以在SQL语句中引用,也可以在C语句中引用,而在C代码里定义的变量则只能在C代码部分引用。同C的变量一样,SQL变量也必须在使用前进行申明。否则在预编译时会产生如下错误信息。Undeclared host variable “X” at line N in file “F”

二. 说明段

(ア)    SQL变量必须在说明段进行说明,说明段的语句由EXEC SQL BEGIN DECLARE SECTION开始,由EXEC SQL END DECLARE SECTION语句结束。

(イ)    Pro*C中允许定义局部和全局的说明段,在预编译单位内允许有多个说明段,但至少有一个全程说明段。说明段的任务是说明SQL变量的数据类型。

例:

EXEC SQL BEGIN DECLARE SECTION

       VARCHAR name[15];

       VARCHAR passwd[20];

       int emp_no;

       float salary;

       char dept_name[50];

       short ind_sal;

EXEC SQL END DECLARE SECTION;

三. 数据类型

(ア)    常用的SQL变量的数据类型

char

char[n]

int

short

long

float

double

VARCHAR[N]

这些类型实际上就是C的数据类型,其中VARCHAR可视为C数据类型的扩充。Pro*C预编译时将会把VARCHAR[N]的变量定义预编译成

struct { unsigned short len; unsigned char arr[N]; } ;

这样的C类型。

(イ)    SQL变量的等价

char,char[n],char*              VARCHAR2

char,char[n],char*              CHAR

int,int*                        INTEGER

short,short*                INTEGER

long,long*                   INTEGER

float,float*                   FLOAT

double,double*                   FLOAT

VARCHAR(N)                     VARCHAR

….请参见附录

(ウ)    SQL变量的说明和引用

        对于简单C类型只能说明一维数组,不允许说明二维或更高维数的数组。对于char username[15][50];这样的说明,ORACLE将是为一维数组。

        对标准的C数据类型,能使用一个说明语句同时说明多个SQL变量。

        Pro*C允许在说明段对SQL变量进行初始化,但是不允许对数组进行初始化,例如下面的语句是错误的。

EXEC SQL BEGIN DECLARE SECTION

       int dept_id[3] = {10,20,30};

EXEC SQL END DECLARE SECTION

实际根据我调查的结果,这样的初始化定义是被允许的,与编译是没有问题,在使用中也没有问题。可能在使用VARCHAR时会出现问题,所以才不禁止对SQL变量进行初始化。

        SQL变量定义中允许出现的存储类型

1.         auto

2.         extern

3.         static

        在说明SQL变量的数据类型时,为变量指定的数据类型必须与ORACLE的数据类型相兼容,否则会产生数据类型转换错误。

CHAR(X)              char              单字符

                     char[n]          n字节的字符

VARCHAR2(Y)      VARCHAR[n] n字节的变长字符数组

                     int          整数

                     short             短整数

                     long        长整数

                     float              单精度浮点数

                     double           双精度浮点数

NUMBER             int          整数

                     short             短整数

NUMBER(P,S)      long        长整数

                     Float             单精度浮点数

                     Double          双精度浮点数

                     Char              单字符

                     Char[n]          n字节字符数组

                     VARCHAR[n] n字节变长字符数组

DATE            char[n]          n字节字符数组

LONG           VARCHAR[n] n字节变长字符数组

RAW(X)         unsigned char[n]  n字节无符号字符数组

LONG RAW          VARCHAR[n] n字节变长字符数组

 

        SQL变量的引用

SQL语句中使用SQL变量时,必须在其之前加一个冒号(:),但在C语句中引用时,不需要加冒号。例如:

EXEC SQL BEGIN DECLARE SECTION;

       Int emp_number;

       Float salary;

       Float commission;

EXEC SQL END DECLARE SECTION;

printf(“/nEnter employee number”);

scanf(“%d”,&emp_number);

EXEC SQL SELECT SAL,COMM

       INTO :salary, :commission

       FROM EMP

       WHERE EMPNO = :emp_number;

Pay = salary + commission;

….

        指示器变量的说明和引用

1.         什么是指示器变量

指示器变量时与宿主变量相关的一类SQL变量,它被用来监督和管理与其相关联的宿主变量。每一个宿主变量都可以定义一个指示器变量。指示器变量的具体作用如下:

向数据库表列输入Null值。

检查从数据库表列中选取的数据是否是null值,或是否发生截断问题。

2.         ORACLE如何实现指示器变量的上述作用呢?其办法是赋予它不同的值:

(ア)    对于输入宿主变量:

        -1ORACLENull值存入数据库的表列中,而不考虑于该指示器变量相关联的输入宿主变量的值。

        >=0ORACLE把与该指示器变量相关联的输入宿主变量中的数据存入数据库表列中。

(イ)    对于输出宿主变量:

        -1:数据库表列的值是Null,此时,与该指示器变量相关联的输出宿主变量中的值为不确定状态。

        0:数据库表列中的值原封不动的赋给与该指示器变量相关联的输出宿主变量中。

        >0ORACLE把数据库表列中的值截断后赋给与该指示器变量相关联的输出宿主变量中,指示器变量返回一个整数值,指示该列值的原始长度,而且SQLCASQLCODE被置为0

3.         指示器变量的说明 同一般的SQL变量,类型为SHORT

4.         指示器变量的引用

EXEC SQL SELECT EMPNO

       INTO :emp_number :ind_num

       FROM EMP

       WHERE ENAME = :emp_name;

If(ind_num == -1)

       Printf(“/nEmploylee Number is Null!”);

        指针宿主变量的说明和引用

1.         指针宿主变量的说明

C语言一样,Pro*C也支持指针宿主变量。其说明格式同C语言。例:

EXEC SQL BEGIN DECLARE SECTION;

       Int *ptr;

       Char *pname;

EXEC SQL END DECLARE SECTION;

2.         引用

SQL语句中引用指针变量时,指针名字前要前缀冒号(:),而不加星号(*)。在C语句中的用法同C语言的指针变量一样。例:

EXEC SQL BEGIN DECLARE SECTION;

       Float salary;

       Char *pname;

       Int emp_number;

EXEC SQL END DECLARE SECTION;

….

EXEC SQL SELECT ENAME,SAL

       INTO :pname,:salary

       FROM EMP

WHERE EMPNO = :emp_number;

              Printf(“%s,%f”,pname,salary);

        数组SQL变量的说明和引用

1.         说明

说明格式同C语言

注意:

PRO*C不支持指针数组

PRO*C只支持一维数组,emp_name[100][15]将被视为一维字符串

数组最大维数为32767,如果超出次限制,则出现“parameter out of range”错误。

2.         数组SQL变量的引用

SQL语句中引用数组时,只需写数组名,不需要写下标。例:

EXEC SQL BEGIN DECLARE SECTION;

       Int emp_number[100];

       Char emp_name[100][15];

       Float salary[100],commission[100];

       Int dept_number;

EXEC SQL END DECLARE SECTION;

EXEC SQL SELECT EMPNO,ENAME,SAL,COMM

       INTO :emp_number,:emp_name, :salary, :commission

       FROM EMP

       WHERE DEPTNO = :dept_number;

而如下写法则是错误的

for(I=1; I<=100; I++)

       EXEC SQL SELECT EMPNO, ENAME, SAL, COMM

              INTO :emp_number[I], :emp_name[I], :salary[I], :commission[I]

       FROM EMP

       WHERE DEPTNO = :dept_number;

3.         使用数组变的好处和注意点

好处:

大大简化程序设计,省去大量不必要的变量命名及引用。

改进程序性能。如在SQL语句中,如果没有数组,就需要循环重复执行。可大大降低网络传输开销。

注意点:

当在SQL语句中引用多个数组时,这些数组的维数应当相同,否则PRO*C使用最小的数组维数,并发出警告。

VALUESSETINTOWHERE子句中,不允许把简单SQL变量与数组SQL变量混用。

UPDATEDELETE语句中,不允许把数组与CURRENT OF子句一起使用。

(エ)    通讯区的说明

        SQLCA的说明

1.         什么是SQLCASQLCA时一个结构类型的变量,它是ORACLE和应用程序的一个接口。该结构变量是为诊断错误和事件处理而设置的。在执行PRO*C程序时,ORACLE把每一个嵌入SQL语句执行的状态信息存入SQLCA中,这些信息包括错误代码、警告标志设置,诊断文本和处理行数等。每一个可执行SQL语句执行后,就可根据SQLCA中的状态信息来判断该SQL语句的执行是否成功?出现什么错误和例外?处理了多少行?等等。

2.         SQLCA的组成:参见SQLCA.H

3.         SQLCA的说明方式

EXEC SQL INCLUDE sqlca;

一个PRO*C程序可说明多个SQLCA,例如可以有一个全程SQLCA和几个局部SQLCAORACLE仅对活动的SQLCA返回信息。

PRO*C程序是由几个源文件组成时,全局SQLCA可以在一个源文件中定义,而在另一个源文件中说明为extern存储类,其说明方式是:

#define SQLCA_STORAGE_CLASS extern;

        ORACA的说明

1.         什么是ORACAORACA是一个类似于SQLCA的数据结构,可把它视为SQLCA的辅助通讯区。当需要的错误及状态信息比SQLCA提供的还要多是,就用ORACAORACA的使用时可选的,因为它会增加系统的运行开销。

2.         ORACA的声明:同SQLCA(为了能够使用ORACA,必须把ORACA与编译可选项指定为“YES”。指定方式为在程序行商编写EXEC ORACLE OPTION(ORACA=YES);


应用程序的设计方法及举例

一. PRO*C程序中嵌入的SQL语句

(ア)    PRO*C程序中能嵌入的SQL语句,见下表

语句类型

语句名

数据定义

ALTER,ANALYZE,AUDIT,

COMMENT,CREATE,DROP,

GRANT,NOAUDIT,RENAME,

REVOKE,TRUNCATE

数据操纵

DELETE,EXPLAINPLAN,INSERT,

LOCK,TABLE,SELECT,UPDATE

会话期控制

ALTER,SESSION,SET,ROLE

系统控制

ALTER,SYSTEM

事务控制

COMMIT,ROLLBACK,SAVEPOINT,SET,TRANSACTION

 

(イ)    嵌入式SQL语句的书写文法

        以关键字EXEC SQL开始

        C语言的语句终结符(分号)终结

        大多数嵌入式SQL语句与交互式SQL语句的区别仅仅是增加了一些子句活使用了一些SQL变量。例:

交互式的写法:

SELECT EMPNO,ENAME,SAL,DEPTNO

       FROM EMP

       WHERE ENAME=ALLEN;

ROLLBACK WORK;

嵌入式的写法:

EXEC SQL SELECT EMPNO,ENAME,SAL,DEPTNO

       INTO :emp_number, :emp_name, :salary, :deptno

       FROM EMP

       WHERE ENAME = ‘ALLEN’;

EXEC SQL ROLLBACK WORK;

二. 连接到数据库

(ア)    连接当前节点的缺省数据库

EXEC SQL CONNECT :username IDENTIFIED BY :password;

EXEC SQL CONNECT :usr_pwd;其中宿主变量usr_pwd内包含由字符“/”分隔的用户名和口令(即username/password

(イ)    连接到其他数据库

下面的例子是对一个远程节点上的单个非缺省数据库进行登录:

/*命名一个连接名*/

EXEC SQL DECLARE nridb DATABASE;

int ConnectDB(char *dbName, char *uid, char *pwd)

{

       EXEC SQL WHENEVER SQLERROR GOTO errexit;

       EXEC SQL CONNECT :uid IDENTIFIED BY :pwd AT nridb USING :dbName;

       return (0);

errexit:

    errrpt();

    EXEC SQL WHENEVER SQLERROR CONTINUE;

    EXEC SQL ROLLBACK WORK RELEASE;

    return(-1);

}

如果授权的话,可在给连接上执行任意的SQL语句,如:

EXEC SQL AT nridb SELECT …

EXEC SQL AT nridb INSERT…

EXEC SQL AT nridb UPDATE…

另一种方法是将连接名放在SQL变量中使用

可以是这样的用法:

EXEC SQL BEGIN DECLARE SECTION;

       Char db_link[10];

       Char unid[10];

       Char pwd[10];

       Char dbname[10];

EXEC SQL END DECLARE SECTION;

strcpy(dblink,”nridb”);

strcpy(uid,”SCOTT”);

strcpy(pwd,”TIGER”);

strcpy(dbname,”nridb”);

EXEC SQL CONNECT :uid IDENTIFIED BY :pwd

AT :dblink USING :dbname;

EXEC SQL AT :dblink SELECT …

三. 静态数据库操作(插入、更新和删除)

(ア)    数据插入

一次插入一行:

EXEC SQL INSERT

       INTO EMP(EMPNO,ENAME,JOB,SAL)

       VALUES(:emp_number,:emp_name,:job,:salary);

一次插入多行:

EXEC SQL BEGIN DECLARE SECTION;

       Char emp_name[100][20];

       Float salary[100];

       Int insert_rows;

EXEC SQL END DECLARE SECTION;

insert_rows = 50;

EXEC SQL FOR :insert_rows

       INSERT INTO EMP(ENAME,SAL)

       VALUES(:emp_name,:salary);

 

(イ)    数据更新

EXEC SQL UPDATE EMP …

(ウ)    数据删除

EXEC SQL DELETE FROM EMP …

(エ)    修正后累计修改行数在SQLCA.SQLERRD[2]中返回。如果省略WHERE子句,则在SQLCASQLWARN[4]中设置警告标志。

四. 查询应用

(ア)    简单查询

语句:EXEC SQL SELECT EMPNO,ENAME,SEX,OLD

       INTO :emp_number,:emp_name,:sex,:old

       FROM EMP

       WHERE EMPNO = 65147;

(イ)    利用数组实现返回多行的查询

EXEC SQL BEGIN DECLARE SECTION;

       Char emp_name[100][20];

       Float salary[100];

       Float commission[100];

EXEC SQL END DECLARE SECTION;

EXEC SQL SELECT ENAME,SAL,COMM

       INTO :emp_name,:salary,:commission

       FROM EMP

       WHERE SAL>500.00;

SELECT至多只能返回100行。如果满足选择条件的行不超过100行,或者用户只希望检索开始100行时,可用这种方式处理。如果超过100行,则其只返回开始的100行数据,如果再次执行该操作,仍返回开始的100行。所以对于这种情况,必须把数组说明得足够大。

使用注意:

只要INTO子句中的宿主变量其中一个是数组,则其他必须都是数组。这些数组可以有不同的维数,此时能够处理的数组元素个数由最小的数组元素个数决定。不允许在WHERE子句中使用数组。

选择的累计行数在SQLCA.SQLERRD[2]中返回。

SELECT语句中不允许使用FOR子句。

(ウ)    使用光标实现返回多行的查询

        步骤是:

1.  说明一个光标,并使他与一个SELECT语句或PL/SQL块相关联。

2.  打开该光标,把满足查询条件的行(或记录)都检索到该光标缓冲区中。

3.  提取:从光标缓冲区中一次一行或多行的取出数据,进行处理,直至取完。

4.  关闭光标,释放缓冲区等。

        相关的四条语句:

1.  DECLARE CURSOR:命名一个光标,并使它与一个SELECT语句或PL/SQL块相关联。

2.  OPEN:打开光标,把满足条件的行都检索到该光标缓冲区中,使光标指向该缓冲区中的第一行。

3.  FETCH:从光标缓冲区中提取行。

4.  CLOSE:关闭光标,释放空间。

        例:

EXEC SQL DECLARE emp_cursor CURSOR FOR

       SELECT EMPNO,ENAME,JOB,SAL,COMM

              FROM EMP

              WHERE DEPTNO = 1010;

EXEC SQL OPEN emp_cursor;

for(;;){

       EXEC SQL WHENEVER NOTFOUND DO break;

       EXEC SQL FETCH emp_cursor

              INTO :emp_number,:emp_name,:job,:salary,:commission;

}

EXEC SQL CLOSE emp_cursor;

五. PRO*C程序中嵌入PL/SQL

(ア)    嵌入PL/SQL块的优点

        改进性能

使用嵌入SQL语句系统一次只能传送一个SQL语句给服务器。使用PL/SQL块,则一次可以传送一个完整的块给服务器。可以大大提高程序运行的效率。

        ORACLE紧密集成

大多数PL/SQL数据类型对ORACLE数据字典来说都是其自身的数据类型。可以提供数据的相对独立性,降低维护代价,并使程序适应数据库的变化。

        等等优点,由于这些属于PL/SQL的范畴,在此不做过多的讨论。着重讨论如何在PRO*C中嵌入PL/SQL块的方法。

(イ)    嵌入PL/SQL块的方法

ORACLE预编译程序处理PL/SQL块的方法类似于处理单个SQL语句。因此,在PRO*C程序中凡是能放置SQL语句的地方都能放置PL/SQL块。但是,PL/SQL块必须用关键词EXEC SQL EXECUTE END_EXEC括住。注意EXEC SQL EXECUTE后不要有“;”最后END_EXEC结束后必须有“;”

(ウ)    使用宿主变量

        PL/SQL块内,把宿主变量作为整个块的全程变量来处理,凡是能允许PL/SQL变量的地方都能使用宿主变量。

        VARCHAR变量的引用:在嵌入是PL/SQL块中也可以使VARCHAR变长字符串,其方法类似嵌入SQL语句,但维一不同点是:当VARCHAR变量是一个输出宿主变量时,在进入该块之前应初始化其长度字段,即把长度字段设置为VARCHAR变量的说明长度。如下例所示:

EXEC SQL BEGIN DECLARE SECTION;

       Int dept_number;

       VARCHAR dept_name[50];

      

EXEC SQL END DECLARE SECTION;

dept_name.len = 50;

EXEC SQL EXECUTE

       BEGIN

              SELECT DNAME

                     INTO :dept_name

                     FROM DEPT

                     WHERE DEPTNO = :dept_number;

             

       END;

END_EXEC;

六. 错误处理

(ア)    使用WHENEVER语句进行错误处理

WHENEVER语句是说明性语句。当执行SQL语句发生错误、警告或找不到等情况时,可用它来指出应采取的动作。使用该语句来诊断SQL错误是最简单、最常用和最有效的方法。

WHENEVER语句的格式

EXEC SQL WHENEVER {SQLERROR | NOTFOUND | SQLWARNING}

       {CONTINUE | DO function call | DO break | GOTO lable_name | STOP};

注意STOP时仅停止程序运行,但不提交和回滚事务。

(イ)    显示测试SQLCA

显式测试SQLCA,就是可在每一个可执行SQL语句后编写一段代码,来测试SQLCA,以确定该SQL语句的执行是否发生错误,发生什么错误,并进行相应的处理。例如:

EXEC SQL INSERT ….

If(sqlca.sqlcode < 0){

       Printf(“Insert Error!!!/n”);

      

}


事务处理

一. 提交事务

(ア)    COMMIT语句常用的书写格式如下:

EXEC SQL COMMIT WORK RELEASE;

EXEC SQL AT :db_link_name COMMIT WORK;

二. 回滚事务

(ア)    事务保留点:

EXEC SQL AT :db_link_name SAVEPOINT savepoint_name;

EXEC SQL SAVEPOINT savepoint_name;

(イ)    事务回滚

事务级回滚

EXEC SQL ROLLBACK WORK RELEASE;

EXEC SQL AT :db_link_name ROLLBACK WORK RELEASE;

部分事务回滚

EXEC SQL ROLLBACK WORK TO SAVEPOINT savepoint_name;

EXEC SQL AT :db_link_name ROLLBACK WORK

TO SAVEPOINT savepoint_name;

(ウ)    表封锁

EXEC SQL LOCK TABLE EMP IN ROW SHARE MODE NOWAIT;

(エ)     

 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值