zoukankan      html  css  js  c++  java
  • ANSI实现动态 sql

      1  
      2 /* 包含C头文件 */  
      3 #include <stdio.h>  
      4 #include <stdlib.h> 
      5 #include <string.h>  
      6   
      7 /* 包含SQLCA头文件 */  
      8 #include <sqlca.h>  
      9 
     10 /* 定义绑定变量值和 选择列表项值的最大长度 
     11  * 绑定变量:即在SQL语句中输入的“&”占位符。
     12  */ 
     13 #define MAX_VAR_LEN     30 
     14 
     15 /* 定义选择列表项名的最大长度 */  
     16 #define MAX_NAME_LEN    31  
     17   
     18 
     19 /* 定义宿主变量 */  
     20 exec sql begin declare section; 
     21     char     *usrname = "scott";
     22     char     *passwd = "11";
     23     char     *serverid = "orcl"; 
     24   char sql_stat[100];  
     25   char current_date[20];  
     26 exec sql end declare section;  
     27   
     28 void sql_error(void);  
     29 void connet(void);
     30 void process_input(void);  
     31 void process_output(void);  
     32   
     33 int main(void)  
     34 {  
     35     /* 安装错误处理句柄 */  
     36     exec sql whenever sqlerror do sql_error();  
     37   
     38     /* 连接到数据库 */  
     39     connet();  
     40   
     41     /* 
     42      * 分配输入描述区和输出描述区 
     43      * Ansi定义了该套标准,proc程序开发者按标准实现了它
     44      * 这两条语句在proc编译的时候会开辟对应大小的存储空间
     45      */  
     46     exec sql allocate descriptor 'input_descriptor';            //用来存储输入的宿主变量
     47     exec sql allocate descriptor 'output_descriptor';         //用来缓存数据库端返回的结果集 
     48   
     49     for( ; ; )  
     50     {  
     51         printf("
    请输入动态SQL语句(EXIT:退出):
    ");  
     52         gets(sql_stat);  
     53   
     54         /* EXIT(exit)->退出 */  
     55         if(0 == strncmp(sql_stat , "EXIT" , 4) || 0 == strncmp(sql_stat , "exit" , 4))  
     56             break;  
     57   
     58         /* 准备动态SQL语句 */  
     59         exec sql prepare s from :sql_stat;  
     60   
     61         /* 定义游标 */  
     62         exec sql declare c cursor for s;  
     63   
     64         /* 处理绑定变量 , 即处理占位符 “&” */  
     65         process_input();  
     66   
     67         /* 
     68          * 打开游标成功 意寓着结果已经被保存到输出描述区了。
     69          * select语句:处理查询结果 
     70          * 其他SQL语句:执行 
     71          */  
     72         exec sql open c using descriptor 'input_descriptor';  
     73         if(0 == strncmp(sql_stat , "SELECT" , 6) , 0 == strncmp(sql_stat , "select" , 6))  
     74         {  
     75                 process_output();
     76         }  
     77         /* 关闭游标 */  
     78         exec sql close c;  
     79     }  
     80   
     81     /* 释放输入描述区和输出描述区 */  
     82     exec sql deallocate descriptor 'input_descriptor';  
     83     exec sql deallocate descriptor 'output_descriptor';  
     84   
     85     /* 提交事务,断开连接 */  
     86     exec sql commit work release;  
     87     puts("谢谢使用ANSI动态SQL!
    ");  
     88   
     89     return 0;  
     90 }  
     91   
     92 void sql_error(void)  
     93 {  
     94     /* 显示SQL错误号、错误描述 */  
     95     printf("%.*s
    " , sqlca.sqlerrm.sqlerrml , sqlca.sqlerrm.sqlerrmc);  
     96     exit(1);
     97 }  
     98   
     99 void process_input(void)  
    100 {  
    101     int i;  
    102   
    103     /* 定义宿主变量 */  
    104     exec sql begin declare section;  
    105         int input_count;  
    106         int input_type ;  
    107         int input_len;  
    108         char input_buffer[MAX_VAR_LEN];  
    109         char name[MAX_NAME_LEN];  
    110         int occurs;  
    111     exec sql end declare section;  
    112   
    113     /* 绑定变量->输入描述区 */  
    114     exec sql describe input s using descriptor 'input_descriptor';  
    115   
    116     /* 取得绑定变量个数 */  
    117     exec sql get descriptor 'input_descriptor' :input_count = count;  
    118   
    119     /* 循环处理绑定变量名 */  
    120     for(i = 0 ; i != input_count ; ++i)  
    121     {  
    122         occurs = i + 1;  
    123   
    124         /* 取得绑定变量名 */  
    125         exec sql get descriptor 'input_descriptor' value :occurs :name = name;  
    126         printf("请输入%s的值:" , name);  
    127         gets(input_buffer);  
    128   
    129         /* 以NULL结尾 */  
    130         input_len = strlen(input_buffer);  
    131         input_buffer[input_len] = '';  
    132   
    133         /* 设置绑定变量类型、长度和值 */  
    134         input_type = 1;  
    135         exec sql set descriptor 'input_descriptor' value :occurs   
    136             type = :input_type , length = :input_len , data = :input_buffer;  
    137     }  
    138 }  
    139   
    140 void process_output(void)  
    141 {  
    142     int i;  
    143   
    144     // 定义宿主变量  
    145     EXEC SQL BEGIN DECLARE SECTION ;  
    146         int output_count;  
    147         int output_type;  
    148         int output_len;  
    149         char output_buffer[MAX_VAR_LEN];
    150         short  output_indicator;  
    151         char name[MAX_NAME_LEN];  
    152         int occurs;  
    153     EXEC SQL END DECLARE SECTION ;  
    154   
    155     // 选择列表项->输出描述区 
    156     exec sql describe output s using descriptor 'output_descriptor';  
    157   
    158     //取得选择列表项个数  
    159     exec sql get descriptor 'output_descriptor' :output_count = count;  
    160   
    161     //循环处理选择列表项(即列名,或者叫表头) 
    162     
    163     output_type = 12;  //设置类型为变长字符串varchar
    164      
    165     for(i = 0 ; i != output_count ; ++i)  
    166     {  
    167         occurs = i + 1;  
    168         
    169         output_len = MAX_VAR_LEN;  
    170       
    171         // 设置选择列表项的类型和长度(设置每一列,按照varchar类型进行显示) 
    172         exec sql set descriptor 'output_descriptor' value :occurs   
    173                         type = :output_type , length = :output_len;  
    174   
    175         //取得选择列表项的名称并输出 
    176         exec sql get descriptor 'output_descriptor' value :occurs :name = name;  
    177             
    178         //显示选择列表项名称  
    179         printf("	%s" , name);  
    180     }  
    181     printf("
    ");  
    182   
    183     // 提取数据完毕->退出循环  
    184     exec sql whenever not found do break;  
    185   
    186     // 循环处理选择列表项数据  
    187     for( ; ; )  
    188     {  
    189         // 行数据-> fetch into 利用游标从输出描述区读取数据。 
    190         exec sql fetch c into descriptor 'output_descriptor';  
    191            
    192         // 循环处理每列数据  
    193         for(i = 0 ; i < output_count ; ++i)  
    194         {  
    195             occurs = i + 1;  
    196            
    197             // 取得列数据和指示变量值  
    198             exec sql get descriptor 'output_descriptor' VALUE :occurs  
    199                 :output_buffer = DATA , :output_indicator = INDICATOR;  
    200   
    201             //输出列数据   
    202             if(-1 == output_indicator)  
    203                printf("	%s", "   ");         
    204             else  
    205                printf("	%s" , output_buffer);        
    206         }   
    207         printf("
    "); 
    208     }  
    209 }
    210 
    211 void connet(void)
    212 {
    213     int ret = 0;
    214     //连接数据库
    215     EXEC SQL CONNECT:usrname IDENTIFIED BY:passwd USING:serverid ;
    216     if (sqlca.sqlcode != 0)
    217     {
    218         ret = sqlca.sqlcode;
    219         printf("sqlca.sqlcode: err:%d 
    ", sqlca.sqlcode);
    220         return ;
    221     } else {
    222         printf("connect ok...
    ");
    223     }
    224 }

    1.ASNI 与 ORACLE 实现动态sql的最大区别就在于不用关心描述区的动态扩容,因为ASNI已经封装好了接口,直接调用就成。

    2.也是主要分为两部分:输出描述区和输入描述区。两个区的作用同ORACLE 功能一样。

    * 分配输入描述区和输出描述区
    * Ansi 定义了该套标准,proc 程序开发者按标准实现了它
    * 这两条语句在 proc 编译的时候会开辟对应大小的存储空间
    */
    exec sql allocate descriptor 'input_descriptor'; //用来存储输入的宿主变量
    exec sql allocate descriptor 'output_descriptor'; //用来缓存数据库端返回的结果集

  • 相关阅读:
    web api 初体验之 GET和POST传参
    清除系统日志及数据库(sql server)日志最佳实践
    大家好啊!
    [oc学习笔记]多态
    [oc学习笔记]便利构造器无法被继承
    [oc学习笔记]字符串
    antd异步加载的树
    react新建页面步骤(新手必看)
    ECharts 经常会修改到的一些样式配置
    关于数组的一些常用方法
  • 原文地址:https://www.cnblogs.com/yyx1-1/p/5901797.html
Copyright © 2011-2022 走看看