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'; //用来缓存数据库端返回的结果集

原文地址:https://www.cnblogs.com/yyx1-1/p/5901797.html