Pro*C基础

SQL变量的申明:

EXEC SQL BEGIN DECLARE SECTION;

    类型  变量名【长度】
    varchar2  serv_number[11];
    其中可以定义C变量
EXEC SQL END DECLARE SECTION;

EXEC SQL INCLUDE Slqca;

说明SQL的通讯区,记录执行每一个SQL语句的状态。

错误信息处理

EXEC SQL WHENEVER SQLERROR DO sqlerror(); 指出执行SQL语句时,如果发生错误应如何处理。


连接数据库

EXEC SQL CONNECT :username IDENTIFIED BY :password;



嵌入式SQL语句或pl/sql块中的关键字应大写。



SQL变量

在变量的申明中定义,只允许包含下列语句:
(一)SQL变量的类型说明语句
(二)EXEC SQL INCLUDE 
(三)EXEC SQL VAR
(四)EXEC SQL TYPE


EXEC SQL VAR 和EXEC SQL TYPE 分别用于将sql变量和外部的变量等价。用法如下:

EXEC SQL VAR host_variable IS type_name[(length)];

可以用户定义类型和等价:

struct screen {
  
     short len;
     char buff[100];
}
typedef struct screen graphics;

EXEC SQL BEGIN DECLARE SECTION;

EXEC SQL TYPE graphics IS VARRAW(4000);

EXEC SQL END DECLARE SECTION;

可以将一个用户说明的类型定义为显示的或隐式的指针,然后使用新的类型。必须使用Reference;

如:
    EXEC SQL TYPE graphics varraw(4000) Reference;
    graphics my_raw;

可以使用如下的修饰符来说明变量的性质:

auto 
static
extern 
const   定义的常量
volatile 有一个程序不知道的方法(如 通过设备)来改变值


VARCHAR变量的说明和应用:

C中没有这种类型,特别引入的这种类型,称为伪类型。

EXEC SQL BEGIN DECLARE SECTION;

VARCHAR  user_name(11);

EXEC SQL END DECLARE SECTION;

在预编译时,该变量被翻译成:

struct {

unsigned short len;
unsigned char arr[20];
} user_name;



通讯区的说明:

Oracle提供了两个通讯区SQL通讯区(sqlca)和Oracle通讯区(oraca)

sqlca是一个结构类型的标量,是Oracle和应用程序的接口,执行Pro*C时,Oracle把每一个嵌入的SQL执行的状态存入sqlca;

sqlca的结构:

struct sqlca{

char sqlcaid[8];     //标识一个sql通讯区
long sqlbc;          //通讯区的长度
long sqlcode;       
 /*
  最近执行Sql后的状态码
 有三中可能的值:
 0  正确结束
 >0 Oracle执行了该语句,但遇到了例外
 <0 Oracle未执行该语句,当出现这类错误时,应该回滚该事务。
 */
struct {

  unsigned short sqlerrml;   //保存sqlerrmc中的文本的长度
  unsigned char  sqlerrmc[70]; //保存sqlcode编码对于的错误信息,只有当sqlcode的值为负时,才应用sqlerrmc,只有70个字符,如果要应用超过70个字符的信息,必须使用SQLGLM()函数。如果sqlcode执行为0时,sqlerrmc为最近sql的信息。
}sqlerrm;

char sqlerrp[8];
long sqlerrd[6];
char sqlwarn[8];
char sqlext[8];
} sqlca;


通讯区的应用方式:

EXEC SQL INCLUDE sqlca;

或将上述编码拷贝到C代码中。

SQLGLM的应用,sqlglm(message_buffer,&buffer_size,&message_length);

message_buffer: 文本缓冲区,将错误的信息保留中这里,用空格补充后面的空间。
buffer_size : 缓冲区的长度。
message_length: Oracle错误信息的实际的长度。

oraca

类似与sqlca,但比sqlca提供的信息更多。

INCLUDE 语句

作用将一个文件拷贝到程序中,类似于#include

定义:  EXEC SQL INCLUDE filename; 程序中使用的是filename的副本。


断开数据库连接

EXEC SQL COMMIT WORK RELEASE;

错误处理的方法:

EXEC SQL WHENERVE SQLERROR GOTO sqlerror;

sqlerror:

    EXEC SQL WHENERVER SQLERROR CONTINUE;

    EXEC SQL ROLLBACK;
   
    exit(1);

也可以使用方法: sqlerror();

void sqlerror;

EXEC SQL WHENEVER SQLERROR DO sqlerror();

void sqlerror()
{
   EXEC SQL WHENERVER SQLERROR CONTINUE;

    EXEC SQL ROLLBACK;
   
    exit(1);
 
}

数据未找到信息的处理方法:

EXEC SQL WHENEVER  NOT FOUND GOTO notfound;

notfound :

   printf("not found");

SQLCA.SQLERRD[2]  //记录处理的行数

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

select返回的多行确定时,可以使用数组,但必须有MODE={ANSI|ANSI13|ORACLE};

当select返回的行不确定时,可以使用光标。

光标的思想:

    使用光标时,开辟了一个缓冲区,将SELECT的查询结果存放在缓冲区中,并将指针指向第一条记录。

光标语句的使用:

(一)说明一个游标

     使用declare cursor

     EXEC SQL DECLARE emp_cursor CURSOR FOR

          SELECT BRAND_ID,BRAND_DESC 
          FROM TB_DET_BRAND
          WHERE BRAND_ALL_ID=:emp_number;

注意:光标的全程必须在一个编译区内。

(二)打开光标

     EXEC SQL OPEN emp_cursor;
 
    OPEN语句的作用:
 
     1. 定义一个光标缓冲区
     2. 把满足条件的行检索到缓冲区中
     3. 将光标指向第一行
     4. 行计算器sqlca.sqlerrd[2]清0;

(三)提取

     EXEC SQL FETCH emp_cursor INTO :brand,:brand_name;

(四)关闭光标

     EXEC SQL CLOSE emp_cursor;


技巧: Oracle中的字符串以NULL结尾。因而,可以使用类型等价实现。

typedef char aciz;

aciz name;
aciz brand;

EXEC SQL TYPE aciz IS SRTING(20);

这样,aciz是以NULL为结束符。

光标使用的例子:

main()
{
     .......

 EXEC SQL WHENEVER SQLERROR DO sqlerror();

     //连接数据库
        EXEC SQL DECLARE emp_cursor CURSOR FOR

          SELECT BRAND_ID,BRAND_DESC 
          FROM TB_DET_BRAND
          WHERE BRAND_ALL_ID=:emp_number;

     EXEC SQL OPEN emp_cursor;

     for(;;)
     {
        EXEC SQL WHENEVER NOT FOUND DO break;

        EXEC SQL FECTH emp_cursor INTO  :brand,:brand_name;

         //处理信息 
        }
 
    EXEC SQL CLOSE emp_cursor;
    
    exit(0);
}

Pro*C嵌入PL/SQL块

认为特色的地方:

可以使用RECODE类型

TYPE test_type IS RECODE
      ( brand_id varchar2(4) not null,
        brand_desc varchar2(80));

嵌入PL/SQL的方法

EXEC SQL EXECUTE 
     DECLARE    ---pl/SQL
     BEGIN
     END;
END_EXEC;

指示器变量:

作用:
  从宿主程序接收NULL值存入数据库表中
  把NUll或截断的值输出给宿主变量

使用方法:  如 :emp_name:ind_emp

过程:
    当进入PL/SQL块时,如果指示器的值为-1,则PL/SQL自动把NULL值赋给相应的宿主变量。
    退出该块时,如果宿主变量的值为NULL,则把-1赋给相应的指示器变量。

PL/SQL块中只使用数组的一部分时,可以指定最小的数组的大小:

方法:  
      EXEC SQL ARRAYLEN host_array (array_integer);

EXEC SQL BEGIN DECLARE SECTION;

   float salary[100];
   int m;
   EXEC SQL ARRAYLEN salary(m);
EXEC SQL END DECLARE SECTION;

指定数据的维数   m=30;
上例中只有30个元素被传递到PL/SQL块中。

方法:
(一)启动oracle通讯区

     EXEC ORACLE OPTION (ORACA=YES);

(二)指定RELEASE_CURSOR=YES,用于释放Pro*C执行后SQL的资源,这将保证数据操作后,oracle不保持表分析锁,后续的数据定义操作不会导致分析锁错误。

    EXEC ORACLE OPTION (RELEASE_CURSOR=YES);

错误处理


动态SQL技术

 动态sql方法1:  用于非select语句,方法: execute immedite ‘insert into ....’;不允许输入宿主变量;
  
  动态sql方法2:(用于非SELECT)

 PREPARE语句:(分析和命名一个动态SQL语句)

EXEC SQL PREPARE [statement_name][block_name] FROM [:host_string][string_literal];

例:
     strcpy(sql_t1,"DELETE FROM EMP WHERE EMP_NAME=:V");

     EXEC SQL PREPARE p1 FROM :sql_t1;

EXECUTE 语句:
            
例 EXEC SQL EXECUTE p1 USING :ind_emp;

方法1和方法2区别: 方法1每执行一次分析一次,而方法二分析一次,多次执行。


 动态SQL方法3:(只用于select语句)

例:
      EXEC SQL BEGIN DECLARE SECTION;

              VARCHAR sqlstmt[80];
              int imp;
              int brand;
              int brand_a;
      EXEC SQL END DECLARE SECTION;

....
     main()
{
         //构造动态SQL
         sqlstmt.len=sprintf(sqlstmt.arr,"select brand_id,brand_all_id from tb_det_brand where brand_all_id=:v");

       //分析动态的SQL
       EXEC SQL PREPARE p1 FROM :sqlstmt;
        
       //说明光标
       EXEC SQL DECLARE c1 CURSOR FOR p1;

       imp=1001;
       ......
       //打开光标
       
       EXEC SQL OPEN c1 USING :imp;

       EXEC SQL WHENEVER  NOT FOUND DO break;

       while(true)
       {
             //提取数据
            EXEC SQL FETCH c1 INTO :brand,:brand_a;
            ................

         }
    
       //关闭光标
       EXEC SQL CLOSE c1;

}

动态方法四:

特点: 在执行SQL之前,表项、宿主变量个数、类型直到执行前仍然不知道。因而,不能在预编译时产生完整的Oracle调用。

对于方法四,要求提供如下的信息:

    选择表项和实宿主变量的个数。
    每一个表项和实宿主变量的长途。
    每一个表项和实宿主变量的类型。
    每一个输出宿主变量(存储选择表项的值)和实输入宿主变量的内存单元地址。

提供信息的方法:

oracle提供的SQL的描述区来说明,它提供了一个sqlda 的数据结构。
具体的过程如下:

     将选择表项和虚拟输入宿主变量分别保存在选择SQLDA和结合SQLDA中。选择表项的值和名字被存储在输出缓冲区,而实输入宿主变量的值和名字被存储在输入缓冲区。输出缓冲区的地址存储在选择SQLDA中,而输入缓冲区的地址存储在结合SQLDA中。

SQLDA写入信息的方法:

(一)sqlald()函数
    
     在分配描述区和缓冲区时,还把SLI(选择表项)或P(虚拟输入宿主变量)的名字在缓冲区中的地址和长度写入SQLDA中。

(二)应用程序

     通过程序把存放SLI或BV(结合变量或实输入宿主标量)的值的缓冲区的地址、长度及数据类型写入SQLDA中。

(三)DESCRIBE

     DESCRIBE SELECT LIST 检查每一个选择表项的信息将信息存储在选择SQLDA及输出缓冲区中。
     
     DESCRIBE BIND VARIABLES 检查每一个虚拟输入宿主变量的信息将信息存储在结合SQLDA及输入缓冲区中。

SQLDA的说明和应用

1. 使用INCLUDE 

    EXEC SQL INCLUDE sqlda;

2. 使用指针

    EXEC SQL INCLUDE sqlda;
    sqlda *bind_dp;
    sqlda *select_dp;
    bind_dp=sqlald(....);
    select_dp=sqlald(....);

SQLDA的应用

    对于每一个动态的SQL都应该说明一个SQLDA.

库函数sqlprc()分离精度和定标。


用户出口(SQL*Forms)

EXEC IAF GET
EXEC IAF PUT

EXEC IAF GET 将form中的值取出赋给宿主变量

例 EXEC IAF GET brand_id INTO :brand; //将brand_id的值取出赋给宿主变量brand

EXEC IAF PUT 将常量或宿主变量的值放入forms中

例 EXEC IAF PUT brand VALUES(:brand_id);


用户出口的引用

 方法:  定义触发器,在触发器中,用USER_EXIT(user_exit_string[,error_string])引用出口。



错误处理

whenever 子句

EXEC SQL WHENEVER {SQLERROR|NOT FOUND|SQLWARNING}
           {CONTINUE|DO function call|DO break|GOTO table|STOP};

 

posted @ 2015-12-23 09:46  开心玩数据  阅读(1192)  评论(0编辑  收藏  举报