静态SQL和动态SQL的区别和测试实例
来源:互联网 发布:阿里巴巴用的数据库 编辑:程序博客网 时间:2024/05/21 00:20
由于近期工作比较悠闲,所以就继续学习了数据库SQL的使用,实际工作中接触最多的是SQL编程,那么本博文就主要介绍动态sql和静态sql的使用方法和区别,方便自己以后回忆和学习,如果本博文有幸被浏览者看到,如有瑕疵和错误还请帮忙指正,共同学习和进步。
所谓SQL的动态和静态,是指SQL语句在何时被编译和执行,二者都是用在SQL嵌入式编程中的。
静态SQL:在高级语言中,如果嵌入了SQL语句,而这个SQL语句的主体结构已经明确,例如在c的一段代码中有一个待执行的SQL“select * from t1 where c1>5”,在编译阶段,就可以将这段SQL交给数据库管理系统去分析,数据库软件可以对这段SQL进行语法解析,生成数据库方面的可执行代码,这样的SQL称为静态SQL,即在编译阶段就可以确定数据库要做什么事情。
动态SQL:如果嵌入的SQL没有明确给出,如在c中定义了一个字符数组类型的变量name:char name[32];,然后采用prepared Statement对象的execute方法去执行这个sql,该sql的值可能等于从文本框中读取的一个SQL或者从键盘输入的SQL,但具体是什么,在编译时无法确定,只有等到程序运行起来,在执行的过程中才能确定,这种SQL叫做动态SQL。例如每一种数据库软件都有能够执行SQL语句的界面,那个界面接收的SQL就是动态SQL,因为数据库厂商在做这个界面时,并不知道用户会输入哪些SQL,只有在该界面执行后,接收了用户的实际输入,才知道SQL是什么。
注意:在SQL中如果某些参数没有确定,如”select * from t1 where c1>? and c2
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>EXEC SQL INCLUDE SQLCA;EXEC SQL INCLUDE SQLDA;/*此函数属于静态SQL编程*/int DBSelect_static(){ EXEC SQL BEGIN DECLARE SECTION; char _typename[32]; short _length; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT typename,length INTO :_typename,:_length FROM syscat.columns WHERE tabname='SYSCOLUMNS' and colname='DEFAULT'; printf("【typename:%s】【length:%d】\n",_typename,_length); }/*此函数属于静态SQL编程:指定函数参数作为SQL语句的变量*/int DBSelect_static_param(char *tbl_str,char *col_str){ EXEC SQL BEGIN DECLARE SECTION; char _typename1[32]; short _length1; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT typename,length INTO :_typename1,:_length1 FROM syscat.columns WHERE tabname='tbl_str' and colname='col_str'; printf("【typename:%s】【length:%d】\n",_typename1,_length1); }/*此函数属于动态SQL编程:SQL语句的结构是不确定的,需要根据用户的输入补全SQL语句*/int DBUpdate_dynamic(){ EXEC SQL BEGIN DECLARE SECTION; char _address1[32]; char _tablename[32]; char _tmp[32]; char buf[256]; EXEC SQL END DECLARE SECTION; EXEC SQL SELECT count(address1) INTO :_tmp FROM cisaddressinfo WHERE customid='100000100000000000178'; if(0==_tmp) {printf("Not Found!\n");return -1;} memset(buf,0x00,sizeof(buf)); sprintf(buf,"update "); printf("Pls input : tablename ->"); scanf("%s",&_tablename); strcat(buf,_tablename); strcat(buf," set address1=? where customid='100000100000000000178'"); EXEC SQL PREPARE project FROM :buf; if(sqlca.sqlcode) perror("PREPARE"); printf("Pls input : address1 ->"); scanf("%s",&_address1); EXEC SQL EXECUTE project USING :_address1; if(sqlca.sqlcode) perror("EXECUTE"); EXEC SQL COMMIT WORK; if(sqlca.sqlcode) perror("COMMIT"); }/*此函数属于动态SQL编程:使用sqlda数据结构组装复杂多变的动态SQL*/int DBSelect_dynamic(){ EXEC SQL BEGIN DECLARE SECTION; char hostVarStmt[256]; EXEC SQL END DECLARE SECTION; // 声明两个 SQLDA 指针,minsqlda 将是一个最小的 SQLDA 结构,用于 PREPARE 语句, // 此时结果集的字段数量未知,所以只需一个最小的 SQLDA,即包含 HEADER 和一个 SQLVAR struct sqlda * minsqlda = (struct sqlda*)malloc(SQLDASIZE(1)); struct sqlda * fulsqlda = NULL; strcpy(hostVarStmt, "select WUID from workprocess where muid = '185001'"); // PREPARE 将填写 minsqlda 的 header,sqldabc 为 SQLDA 总长度,sqln 为 SQLVAR 数量,即字段数量 EXEC SQL PREPARE STMT INTO :*minsqlda FROM :hostVarStmt; // 根据从 minsqlda 中获取的长度,分配完整的 SQLDA 结构 fulsqlda,其中将包括合适数量的 SQLVAR 结构 //结构sqlda的成员变量sqld返回select查询语句的字段的数目,可以根据此变量分配内存 fulsqlda = (struct sqlda *)malloc(SQLDASIZE(minsqlda->sqld)); // 使用 DESCRIBE 语句,获取结果集中每个字段的描述信息,包括各字段的类型 (sqltype) 和长度 (sqllen) EXEC SQL DESCRIBE STMT INTO :*fulsqlda; int i; for(i=0;i<minsqlda->sqld;i++) { // 根据每个字段的长度,分配内存,将地址存储在对应 SQLVAR 的 sqldata 中// fulsqlda->sqlvar[i].sqldata=malloc(fulsqlda->sqlvar[i].sqllen); fulsqlda->sqlvar[i].sqldata=malloc(32); fulsqlda->sqlvar[i].sqlind=malloc(sizeof(short)); } // 声明游标 EXEC SQL DECLARE c1 CURSOR FOR STMT; EXEC SQL OPEN c1; EXEC SQL WHENEVER not found goto no_more_data; // 读取记录,记录中每个字段的内容将写入 fulsqlda 中对应 SQLVAR 结构的 sqldata 指向的内存 // EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda; // 循环读取所有记录 for (;;) { EXEC SQL FETCH c1 USING DESCRIPTOR :*fulsqlda; for(i=0;i<minsqlda->sqld;i++){ printf("%d %s\n",fulsqlda->sqlvar[i].sqltype,fulsqlda->sqlvar[i].sqldata); usleep(10000); } } return 0; no_more_data: printf("\nEND of Data\n"); free(minsqlda); free(fulsqlda); EXEC SQL CLOSE c1; return 0;}int main(){ /*连接数据库*/ EXEC SQL CONNECT TO ezeelink USER ezeelink USING EA704075ezeelink; DBSelect_static(); DBSelect_static_param("SYSCOLUMNS","DEFAULT"); DBUpdate_dynamic(); DBSelect_dynamic(); no_more_data: ; return 0; }
案例输出结果如下:
【typename:VARCHAR】【length:254】
【typename:VARCHAR】【length:254】
Pls input : tablename ->cisaddressinfo
Pls input : address1 ->ShangHai
452 cis505
452 cis506
452 pub806
452 ips007
452 ips032
452 dps302
END of Data
注意:
如果使用动态SQL编程编写select查询语句并保存结果,需要使用sqlda数据结构的,同时使用SQL的特性和功能,如:PREPARE ,EXECUTE ,DESCRIBE , DECLARE CURSE C1 FOR … , OPEN CURSE , CLOSE CURSE ….等等
建议:
动态SQL适用于表名及查询字段名未知的情况。在已知查询字段名及表名的情况下,使用动态SQL(字符串拼接方式)会增加硬解析的开销,在这种情况下,建议使用静态SQL,这样可以提高执行效率。在过程过程用拼凑的动态sql效率并不高,有时候还不如程序直接传递sql.静态SQL是前置编译绑定,动态SQL是后期执行时才编译绑定
- 静态SQL和动态SQL的区别和测试实例
- 静态SQL和动态SQL
- sql语句 静态sql和动态sql
- 静态sql与动态sql的区别
- DB2静态SQL和动态SQL 的比较与实践
- DB2 静态 SQL 和动态 SQL 的比较与实践
- 动态sql 和静态sql 上篇
- 动态sql 和静态sql 下篇
- Oracle动态SQL和静态SQL比较
- MySQL-静态SQL 和动态SQL
- 动态sql 和静态sql 上篇
- 动态sql 和静态sql 下篇
- 动态SQL和静态SQL及绑定变量性能对比
- 动态SQL与静态SQL区别
- 静态测试和动态测试
- 静态测试和动态测试
- 扩展SQL的灵活性——静态T_SQL和动态SQL
- Mybatis下动态sql中##和$$区别
- 安装Ubuntu13.10 必做的事情 - Saucy Salamander(活泼的蝾螈)
- 万年历
- 第十一周 项目1-验证算法(1)
- 什么才是好代码—10条戒律
- 金山词霸2007专业版 破解补丁
- 静态SQL和动态SQL的区别和测试实例
- 黑马程序员_MRC
- C2000上电引导模式解析------【TI FAE 经验分享】
- SQL中的字符串函数
- 2.c/c++程序员面试宝典-操作符
- 获取接口的泛型类型
- Optiwave OptiSystem v7.0
- Cygwin安装与配置
- SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)