所谓动态SQL,是相对静态SQL而言的,静态SQL在编译的时候就已经知道它的全部内容了。而动态SQL脚本是在编译的时候还不完整,直到执行过程中才能确定的SQL语句。
在DB2/400中实现动态SQL的方式很多,但一般都采用PREPARE的方式来实现,下面是在SQLC中实现动态SQL的实例:
EXEC SQL BEGIN DECLARE SECTION;
DCL EMP CHAR(6);
DCL PRJ CHAR(6);
DCL SEARCH_PRJ CHAR(6); //真正的查询条件
DCL ACT BINARY FIXED(15);
DCL TIM DEC FIXED(5,2);
DCL SELECT_STMT CHAR(200) VARYING; //定义动态SQL字符串变量
EXEC SQL END DECLARE SECTION;
SELECT_STMT = .SELECT EMPNO, PROJNO, ACTNO, EMPTIME . ||
.FROM EMP_ACT . ||
.WHERE PROJNO = ?.; //动态查询SQL
.
.
.
EXEC SQL PREPARE SELECT_PRJ FROM :SELECT_STMT; //定义新的SQL Prepare Statement
EXEC SQL DECLARE C1 CURSOR FOR SELECT_PRJ;
EXEC SQL OPEN C1 USING :SEARCH_PRJ; //把SEARCH_PRJ的值赋给SELECT_STMT中的‘?’
EXEC SQL FETCH C1 INTO :EMP, :PRJT, :ACT, :TIM;
IF SQLSTATE = .02000. THEN //查询到头
CALL DATA_NOT_FOUND;
ELSE
DO WHILE (SUBSTR(SQLSTATE,1,2) = .00.
| SUBSTR(SQLSTATE,1,2) = .01.);
EXEC SQL FETCH C1 INTO :EMP, :PRJ, :ACT, :TIM; //检索CURSOR的查询内容
END;
EXEC SQL CLOSE C1;
在Store Procedure中使用SQL的一个难题就是如何把传入的变量反映到SQL语句中,这里就必须用到动态SQL。
例如:
CREATE PROCEDURE QGPL/TEST(IN file char(10),IN field char(10),INOUT max_value INTEGER)
LANGUAGE SQL
BEGIN atomic
DECLARE stmt varchar(256);
DECLARE not_found CONDITION FOR ‘02000’;
DECLARE CONTINUE HANDLER FOR not_found;
DECLARE C1 DYNAMIC SCROLL CURSOR FOR S1;
SET max_value =NULL;
SET stmt=‘SELECT '||field||' FROM '||file || ' ORDER BY 1';
PREPARE S1 FROM stmt;
OPEN C1;
FETCH LAST FROM c1 INTO :max_value;
CLOSE C1;
END
利用传入的文件名和字段名把最大的纪录值作为传出参数传出来。