当前位置: 首页 > 工具软件 > Pro*C > 使用案例 >

proc/c++

籍辰沛
2023-12-01
一.什么是pro程序
   通过在过程化编程语言中 嵌入sql语句开发出的
   应用程序叫pro程序。
   
   宿主语言:sql 语句所嵌入的语言。
   sql语句是寄生在这些语言上的。
   
二.proc/c++  
   希望通过c或者c++ 成为访问oracle数据库的工具
三.一个proc程序 涉及到内容
   定义变量
   定义函数
   导入头文件
   
   和数据操作相关的
   连接数据库:
   exec sql connect:userpasswd;
   exec sql connect:username identified
       by userpasswd;
   查询数据库:
   exec sql select  first_name into :变量
       from s_emp where 条件;
   断开数据库连接:
   exec sql commit work release;
   exec sql rollback work release;
       
四.如何写一个c程序?
   1.编写源代码
   vi   ***.c
   2.编译
   gcc  -c  ***.c
   3.链接
   gcc   ***.o   -l库名
   4.执行
   ./a.out
五.如何写一个proc程序?   
   1.编写源代码
     vi  ***.pc
   2.预编译  得到c文件
     proc  ***.pc       
   3.编译 链接
     gcc  ***.c  -lclntsh
     gcc  ***.c  -lorasql10 -L (windows)
   4.执行
     ./a.out           
       
 
 上传文件
     1.找到要上传的文件
     2.ftp  IP
       openlab
       open123
     3.切换服务器的目录
       cd  目录
     4.放入文件
       put  文件名;
       
    find  /  -name  clntsh*  2>/dev/null   
    find  /  -name  stddef.h  2>/dev/null
    proc  first.pc  include="头文件的路径"  
            
 六. 宿主变量
    6.1  概念
    既能在sql语句中使用的变量 又能在宿主语言中
    使用的变量。
    6.2  类型限制
    char  
    char   var[n]  定长字符串
    int  
    short
    long
    float
    double
    varchar   var[n]   变长字符串
    
    定长字符串   char  var[n]
    变长字符串   varchar var[n]
        在select语句中 要和正常的变量一样去使用
        在宿主语言中需要使用 变量名.arr 取得
        数据。数据的长度可以使用.len 获得。
        要注意垃圾数据的问题。
            给变长字符串数组 进行初始化
            varchar  var_name[30]={0};
            var_name.arr[var_name.len]='\0';
 七.proc 的预编译选项
    proc   ***.pc    include="头文件路径"
    
    char_map=charz  默认的 定长  空格补齐 \0
             charf  varchar2 定长 空格补齐
             string  变长    \0结尾
    和c++ 相关的选项
    oname   输出文件名 默认以.c结尾
            c++ 一般以点cpp 结尾
    parse   默认是c的full方式
            partia  严格的c++检查 不建议使用
            none    c++ 推荐使用
    code    默认是 ansi_c  
            cpp 则必须把宿主变量放入申明区
            exec sql begin declare section;
            exec sql end   declare section;                                             
   (c++ 程序的编译器是g++ )
   proc  ***.pc   oname=***.cpp  parse=none
       code=cpp
   g++   ***.cpp   -lclntsh
   
   和PLSQL调用相关的选项
   sqlcheck=semantics  
   userid=用户名/密码
   #include <sys/types.h>
   include="/usr/include/i386"    
 八.宿主变量 使用的注意事项
    宿主变量名前 要加冒号
        exec sql select  first_name into :var_name
            from s_emp where id=:id;
    宿主变量 推荐放入申明区
        不同系统 不同语言对宿主变量的定义不同
        加上申明区 可以避免这些差异。
        exec sql begin  declare section;
        exec sql end    declare section;
    宿主变量的类型 可以是指针类型  但必须分配
        内存空间.(字符串尽量不要用堆分配)
    DDL 中不能使用宿主变量
        char  table_name[30]="s_emp";
        exec sql  drop table  table_name;
        exec sql  drop table  :table_name;
 九.指示变量
    9.1 作用
    当数据库中的字段的值 赋值给宿主变量时  赋值的
    状态可以通过指示变量得到。
    ==0   赋值正常
    ==-1  数据库中的字段值是NULL值
    >0    截断赋值  尽量避免
    
    9.2  语法
    指示变量 必须是short类型
    short   indmid=88;
    exec sql  select  manager_id  
        into :mid:indmid from s_emp where id=1;
    exec sql  select  manager_id  
        into :mid indicator :indmid
            from s_emp where id=1;     
    9.3  把id=1 的manager_id 赋值给宿主变量 mid
    并且指示mid的赋值状态。
 十.数组变量
    10.1 数组变量的使用注意事项
        proc只支持一维数组 字符除外
            char  var_name[30];
            char  var_names[50][30];
        select语句中使用数组只能数组名 不能
            出现下标。
        proc 不支持数组指针。
        数组元素个数 32767
    10.2  举例
        int   mids[50];
        char  var_names[50][30];
        short indmids[50];
    把s_emp  表中所有的manager_id 和first_name
    数据 分别放入上面的数组中。并且指示
    manager_id 赋值状态。
    
十一.sqlca 通信区
    sqlca 通信区 本质上就是一个结构体
    每执行一次sql 都会把sqlca中的字段
    更新一遍。所以得到一条sql语句的状态
    要执行完sql时立即判断。否则会被下一次
    sql覆盖掉。
    sqlca.sqlerrd[2] 最近一次sql语句影响的行数
    sqlca.sqlcode    得到sql语句执行状态
        ==0    执行正常
        >0     sql执行出错
        <0     数据库本身出错 或者网络错误
    sqlca.sqlerrm.sqlerrmc   sql出错的消息内容

      
    
一.数据库的连接:
   本地连接
   exec sql  connect:usernameandpasswd;
   exec sql  connect:username identified by
       userpasswd;
   echo  $ORACLE_SID (得到数据库服务名)
   远程连接
   $ORACLE_HOME/network/admin/tnsnames.ora
 CAH_192.168.0.26 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.26)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = tarena)
    )
  )
 
  第二种远程数据库连接方式:
  database  link
 
  create database link 链接名  
     connect  to 用户名 identified by
     密码  using '数据库描述';

  drop   database link  mydb26dblink;
  create database link  mydb26dblink
     connect  to  openlab identified by
     open123  using
     'CAH_192.168.0.26';

  select id,first_name from
     s_emp@mydb26dblink  where id=1;

  drop   database link  mydb20dblink;
  create database link  mydb20dblink
     connect  to  openlab identified by
     open123  using
     '(DESCRIPTION =
  (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.20)(PORT = 1521))
  )
  (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = tarena)
  )
)';

  select id,first_name from
     s_emp@mydb20dblink  where id=1;
  select * from
     tang1_sql@mydb20dblink;

  update s_emp set
      salary=salary+2000 where id=1;
  update s_emp@mydb26dblink set
      salary=salary+2000 where id=25;
  select  id,salary
      from s_emp@mydb26dblink where id=25;
 
  两种远程数据库连接:
  $ORACLE_HOME/network/admin/tnsnames.ora
  host     service_name
  exec sql connect:userpasswd at:标签名
      using '远程数据库描述';
  exec sql connect:userpasswd at:标签名;
  exec sql at:标签名 select ...;
  exec sql at:标签名 update ...;

  使用database  link
  在数据库中建立database link
  create  database link 链接名 connect to
      用户名 identified by 密码
      using '远程数据库描述';
  在proc代码中使用链接 必须先登录本地
  数据库。
  使用时只要在操作表名后加上@链接名
  exec sql connect:userpasswd;
  exec sql select salary into :salary
     from s_emp where id=25;
  exec sql select salary into :salary
     from s_emp@mydb26dblink where id=25;
  exec sql update s_emp@mydb26dblink
     set salary=salary+200 where id=25;
  exec sql commit;

二.sqlca与错误处理
  /* 局部错误处理 */
  exec sql  update account set money=
      money-20000 where id='001';
  if(sqlca.sqlcode==0){
     a=1;
  }else{
     a=0;  
  }
  exec sql  update account set money=
      money+20000 where id='002';
  if(sqlca.sqlcode==0){
     b=1;
  }else{
     b=0;  
  }
  if(a&&b){
     commit;
  }else{
     rollback;
  }
  /* 全局错误处理 */  
  exec sql whenever  条件 动作;
  条件:sqlerror  notfound sqlwarning
  动作:do 函数;
       do break;
       continue;
       stop;
       goto 标签;
  当程序出现问题时  程序就会向上找一个
  合适的处理。如果没有找到相应的处理 则
  采用默认的处理方式。
  如果进行了sql语句的执行结果判断,会
  先进行全局处理 后进行局部处理。

三.数据的操作
   3.1 一个变量 一次只能操作单行单列
   exec sql select first_name into
      :var_name from s_emp where id=1;
   3.2 多个变量一次 操作单行 多列
   exec sql select id,first_name,salary
   into :id,:var_name,:salary
   from s_emp where id=1;
   3.3 使用结构体操作单行多列
   struct{
       int  id;
       char name[30];
       double salary;
   }emp;
   struct emp{
       int  id;
       char name[30];
       double salary;
   };
   typedef struct emp{
       int  id;
       char name[30];
       double salary;
   }emp;

  3.4 结构体数组 可以操作多行 多列
   定义一个结构体数组 把s_emp 表中
   所有的 id ,first_name,salary
   放入数组。再把数组中的所有数据
   放入一个提前建立好的表中。
  3.5 使用游标 操作多行多列
    3.5.1 非滚动游标的使用步骤
    定义游标
        exec sql  declare 游标名 cursor
        for select 语句;
    打开游标
        exec sql  open    游标名;
    提取数据
        exec sql  fetch   游标名 into
        :宿主变量;
    关闭游标
        exec sql  close   游标名;
    3.5.2 例子
    把s_emp 表中的id  first_name salary
    放入一个游标中。然后输出这个游标的
    前两条数据。
    
    3.5.3 滚动游标(了解)
    scroll   不按照顺序提取数据
    fetch  last
           first
       prior  当前行的前一个
       next   当前行的后一个
       current  当前行
       relative  n  n是正数向后
                n是负数向前
           absolute  n  绝对的第几行

四. 动态sql
   在程序运行的过程中 sql语句可以根据
   条件发生改变。
   4.1  只能是非select语句
        不能有占位符号
        (执行次数不多)
    exec sql execute immediate
       :sqlstr;
   4.2  只能是非select语句
        可以有占位符
        "insert into testdsql values(
    100,'test100')"
        "insert into testdsql values(
    101,'test101')"
        "insert into testdsql values(
    :b0,:b1)"
    适合批量数据的处理
        
    exec sql prepare s from :sqlstr;
    exec sql execute s using :id,
       :name;
   4.3  能且只能是select
        可以有占位符
    "select id,first_name,salary
    from s_emp  where id>:b0"
    动态sql2 和 游标的结合    
    
    
    
          
                               
        
        
        
                                
           
    
            


  
 类似资料: