Proc、宿主變量、指示變量、數組變量、通信區sqlca,oraca ---(day07)


PROC
主要內容:
1) proc簡介
2) proc程序的開發過程
3) 宿主變量和指示變量
4) 嵌入sql語句
5) 連接數據庫
6) 錯誤處理
7) 數據的存取更新操作
8) 動態sql
-----------------------------
1.什么是pro程序?
  1.1 概念
    在過程化的編程語言中嵌入sql語句而開發出的應用程序,叫pro程序。
    在通用的編程語言中嵌入的sql語句稱為嵌入式sql
    被嵌入了sql語句的編程語言稱為宿主語言    
    
  
  1.2 proc/c++
    在c/c++語言中嵌入sql語句而開發出的應用程序,稱為proc/c++程序
    目的:是C/C++這種高效的語言成為訪問oracle數據庫的工具   
  

2. proc中嵌入的sql語句
   #include .....
   ...
   /* 包含一個名為sqlca的結構 */
   exec sql include sqlca;
   變量的聲明
   函數的聲明

   int main(void)
   {
       /* 連接數據庫 */
       exec sql connect:用戶名/密碼;

      /* 操作數據庫:比如查詢 */
      exec sql select 字段列表 into 變量列表 from 表名
          where 條件;

       /* 關閉並釋放連接資源 */
       exec sql commit work release;
       exec sql rollbakc work release;
   }

3.C程序的開發步驟
   1) 編寫源程序
       vi xxx.c
   2) 編譯、鏈接
       gcc xxx.c -lxxxxx
   3) 運行
       ./a.out
4.proc程序的開發步驟
   1) 編寫源程序
       vi xxxx.pc
   2) 預編譯   

       proc xxx.pc    ----->  xxx.c
   3) 編譯、鏈接
       gcc xxx.c  -lclntsh              -- linux
       gcc xxx.c  -lorasql10(11)   -- windows
   4) 運行
       ./a.out

    案例:first.pc
    vi first.pc
    proc first.pc
    gcc first.c -lclntsh
    ./a.out

5. 宿主變量
  5.1 概念
    proc中C語言稱為宿主語言
    在宿主語言中定義,即可以在宿主語言中使用,也可以在sql語句中使用的變量,稱為宿主變量。
  5.2 宿主變量的數據類型
    char                         字符型
    char   var[n]             定長字符串
    short
    int                            整型
    long
    float
    double                     浮點型
    varchar var[n]          變長字符串
  
   5.3 定長字符串和變長字符串
    5.3.1 定長字符串
      字符串的長度不足時用空格補齊
      
      案例:charn.pc
    
    5.3.2 變長字符串
      案例:varcharn.pc

      char name[25] ----> varchar name[25]
      預編譯時,varchar類型的數組被翻譯成了同名的結構:
      struct{
         unsigned short len;
         unsigned char arr[25];
      } name;
      
      varchar類型的數組在sql語句中使用時,和char型數組一樣
      在宿主語言中使用時,按照結構的用法:
      提取字符串的值:name.arr
      獲取字符串的長度:name.len

      使用varchar類型的數組時,可以會產生垃圾數據,解決方式:
      1) 字符串進行初始化,把數組的所有元素初始化為'\0'
          varchar name[25] = {0};
      2) 手動為字符串添加結束標志
          name.arr[name.len] = '\0';

     5.3.3 使用預編譯選項解決變長字符串的問題
       oname   相當於 gcc 的 -o
       
       char_map  = charz: 處理成定長,空格補齊,'\0'結尾
                         = varchar2|charf: 處理成定長,空格補齊,不以'\0'結尾
                         = string: 處理成變長,以'\0'結尾
      
       proc charn.pc char_map=string
       gcc charn.c -lclntsh
       ./a.out

   
   5.4 宿主變量使用時的注意事項
      1) 在sql語句中使用宿主變量時,最好在變量名前加:
          ...
          int id=2;
          ...
          exec sql select first_name into name from s_emp
              where id=id;
          ...
       2) DDL語句中不允許使用宿主變量
          案例:droptable.pc
            .....
            char tablename[20]="testdsql_zsm_00";
            .....
            /* 刪除名為 tablename 的表 */
            exec sql drop table tablename;
            /* 預編譯錯誤:宿主變量不能在ddl語句中使用 */
            exec sql drop table :tablename;
       3) 宿主變量可以使用指針,但是不推薦
       4) 宿主變量的定義,強烈建議放入聲明區
           (C++語言、windows平台要求宿主變量的聲明必須在聲明區)
           exec sql begin declare section;
               /* 聲明區 */
           exec sql end declare section;
       
     練習:定義合適的變量,接收s_dept中id=43的部門的信息,並輸出。  
    
     案例:searchdeptbyid.pc
#include <stdio.h>
exec sql include sqlca;
int main(void)
{
    exec sql begin declare section;
        char userpasswd[30]="openlab/open123";
        int id=43;
        char name[25];
        int rid;
    exec sql end declare section;
    exec sql connect :userpasswd;
    exec sql select id,name,region_id
        into :id,:name,:rid from s_dept
        where id=:id;
    exec sql commit work release;
    printf("%d %s %d\n",id,name,rid);
    return 0;
}
 
         

 

6.指示變量
  6.1 指示變量的作用
    當數據庫中的字段的值,賦值給宿主變量時,賦值的狀態了一通過指示變量獲取。
    指示變量的值:
            0          代表正常賦值
            -1        代表數據庫中對應字段的值為null
           >0        代表截斷賦值 盡量避免(編譯沒問題,執行時在賦值階段不會出現錯誤,引起的后續的問題 時機不確定)

  6.2 語法
    指示變量的數據類型必須是short
    short indid;
    short indname;
    
    exec sql select id,first_name into :id,:name
          from s_emp where id=1;

    exec sq    l select 字段1,字段2 into
         :宿主變量1 [indicator] :指示變量 , 宿主變量2
       from 表名 where 條件;
    
    exec sql select id,first_name into :id:indid,:name:indname
          from s_emp where id=1;

  6.3 案例:把s_emp表中id=1的員工的id,first_name,manager_id查詢出來,保存到相應的宿主變量,同時使用指示變量指示賦值狀態。
    
   案例: indvar.pc

7.數組變量
  7.1 數組變量使用的注意事項
    1) 除了字符型外,其他類型的數組只能使用一維的
        int ids[50];
        char name[50][25];
    2) 不支持數組指針
    3) 最大元素個數 32767
    4) 在select語句中使用數組變量時,只能給出數組的名字,不能使用下標
    5) 如果要指示多個變量的賦值狀態,可以使用指示變量數組

  7.2 把s_emp表中的所有員工的id,first_name和manager_id查詢出來,使用合適的數組接收查詢結果,並使用指示變量數組指示manager_id的賦值狀態
    
     案例:arr_var.pc
#include <stdio.h>
exec sql include sqlca;
int main(void)
{
    exec sql begin declare section;
      char userpasswd[30]="openlab/open123";
      int ids[50]={0};
      char names[50][25]={0};
      int mids[50]={0};
      short indmids[50]={-2};
    exec sql end declare section;
    exec sql connect:userpasswd;
    exec sql select id,first_name,manager_id into
        :ids,:names,:mids:indmids from s_emp;
    exec sql commit work release;
    int i=0;
    for(;i<50;i++)
    {
        printf("%d %s %d %hd\n",ids[i],names[i],
                mids[i],indmids[i]);
    }
    return 0;
}
 
         

 

8.sqlca通信區
  8.1 通信區的概念 
    通信區:為了取得每個sql語句執行后的相關狀態說明,以便進行錯誤的后續操作或跟蹤
    oracle中提供了兩個通信區:
    SQL通信區:sqlca
    Oracle通信區:oraca

  8.2 sqlca通信區
   執行proc程序時,oracle把每一條sql中狀態信息存入sqlca中,包括錯誤代碼、警告標志設置、診斷文本和處理行數等。
   本質上,sqlca是一個結構體
   proc每執行一條sql語句,都會把相關信息寫入到sqlca,覆蓋上一條sql語句的執行的結果信息,所以需要獲取執行結果信息的話,要執行完馬上獲取。
   
    sqlca.sqlerrd[2]:    sql語句執行后影響的行數
    sqlca.sqlcode:       sql執行的狀態
                       0:     執行正常
                    >0:      執行出錯(出現異常)
                    <0 :        數據庫系統錯誤 或者網絡錯誤
     sqlca.sqlerrm.sqlerrmc: 錯誤信息

     案例:sqlca.pc
#include <stdio.h>
exec sql include sqlca;
int main(void)
{
    exec sql begin declare section;
      char userpasswd[30]="openlab/open123";
      int ids[50]={0};
      char names[50][25]={0};
      int mids[50]={0};
      short indmids[50]={-2};
    exec sql end declare section;
    exec sql connect:userpasswd;
    if(sqlca.sqlcode){
        printf("%s\n",sqlca.sqlerrm.sqlerrmc);    
    }
    exec sql select id,first_name,manager_id into
        :ids,:names,:mids:indmids from s_emp;
    if(sqlca.sqlcode){
        printf("%s\n",sqlca.sqlerrm.sqlerrmc);    
    }
    exec sql commit work release;
    int i=0;
    for(;i<sqlca.sqlerrd[2];i++)
    {
        printf("%d %s %d %hd\n",ids[i],names[i],
                mids[i],indmids[i]);
    }
    return 0;
}
 
         

 

9. oraca通信區
  一個類似於sqlca的結構,可以作為sqlca通信區的補充。當需要獲取更為詳細的狀態信息,可以使用oraca.
  oraca通信區對sqlca的補充 
  可以使用oraca獲取執行的sql語句的文本

  oraca的使用步驟:
  1) 包含oraca
       exec sql include oraca;
  2) 打開oraca option
      exec oracle option(oraca=yes);
  3) 設置sql文本的保存標志
      oraca.orastxtf 
                     0: 默認值    不保存 
                     1: sql語句出錯時保存
                     2: sql語句出現錯誤或警告時保存
                     3: 都保存
  4) 獲取sql文本
      oraca.orastxt.orastxtc

   案例:oraca.pc
#include <stdio.h>
exec sql include sqlca;
exec sql include oraca;
exec oracle option(oraca=yes);
int main(void)
{
    exec sql begin declare section;
       char  userpasswd[30]="openlab/open123";
       char name[25];
       int id=1;
    exec sql end declare section;
    exec sql connect:userpasswd;
    oraca.orastxtf = 1;
    exec sql select first_name into :name from s_emp
        where id=:id;
    exec sql commit work release;
    printf("%s\n",name);
    printf("%s\n",oraca.orastxt.orastxtc);
    return 0;
}
 
         

 

10. proc中如何使用sql語句
  1) select語句
      在語句前加exec sql,配合into使用
      exec sql select 字段列表 into 宿主變量列表 from 表名
          where 條件;
  2) dml語句(inert  delete update)
       ddl語句(create   drop  alter)
       tcl語句(commit   rollback  savepoint)
       直接在語句前加exec sql
       注意:ddl語句中不能使用宿主變量

    綜合案例:sql.pc
#include <stdio.h>
#include <stdlib.h>
exec sql include sqlca;
int connect();
void createtable();
void insert();
void search();
void update();
void delete();
int main(void)
{
    if(connect())
    {
        printf("連接錯誤\n");
        return -1;
    }
    int option;
    printf("歡迎使用學生管理系統\n");
    while(1)
    {
        printf("1.創建學生表\n");
        printf("2.注冊\n");
        printf("3.查看\n");
        printf("4.修改\n");
        printf("5.刪除\n");
        printf("0.退出\n");
        printf("請選擇:");
        scanf("%d",&option);
        switch(option)
        {
            case 1:
                printf("學生管理系統---- 創建表\n\n");
                createtable();
                break;
            case 2:
                printf("學生管理系統---- 注冊\n");
                insert();
                break;
            case 3:
                printf("學生管理系統---- 查看\n");
                break;
            case 4:
                printf("學生管理系統---- 修改\n");
                break;
            case 5:
                printf("學生管理系統---- 刪除\n");
                break;
            case 0:
                printf("謝謝使用!\n");
                exit(0);
            default:
                printf("沒有此功能!\n");
                break;
        }
    }
    return 0;
}
int connect()
{
    exec sql begin declare section;
      char username[20];
      char passwd[20];
    exec sql end declare section;
    printf("請輸入用戶名:");
    scanf("%s",username);
    printf("請輸入密碼:");
    scanf("%s",passwd);
    exec sql connect:username identified by :passwd;
    return  sqlca.sqlcode;
}
void createtable()
{
    exec sql create table student_zsm_00(
            stuno number(7),
            stuname varchar2(20),
            birth date);
}
void insert()
{
    exec sql begin declare section;
       int stuno;
       char name[25];
       char birth[20];
    exec sql end declare section;
    printf("請輸入學號:");
    scanf("%d",&stuno);
    printf("請輸入姓名:");
    scanf("%s",name);
    printf("請輸入出生日期:(yyyy-mm-dd)");
    scanf("%s",birth);
    exec sql insert into student_zsm_00 values(
            :stuno,:name,to_date(:birth,'yyyy-mm-dd'));
    exec sql commit;
}
 
         

 


    開發一個超小型的學生管理系統,完成以下功能:
         創建學生信息表
         添加學生信息
         顯示學生信息列表
         根據學號更改信息
         根據學號刪除信息
    
      循環菜單:
      學生管理系統,請選擇:
       1.創建表
       2.學生注冊
       3.查看
       4.修改信息
       5.刪除信息
       0.退出

練習:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM