动态SQL与静态SQL

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
错误写法: sprintf(temp_sql, "insert into wChg%d(id_no,total_date,login_accept,sm_code,belong_code,phone_no,org_code,\
login_no,op_code,op_time,machine_code,cash_pay,check_pay,sim_fee,machine_fee,innet_ fee,choice_fee,\
字段的个数,变量占位符,变量类型在编译时必须是已知的.例如: 'SELECT DEPTNO, MIN(SAL), MAX(SAL) FROM EMP GROUP BY
DEPTNO' 'SELECT ENAME, EMPNO FROM EMP WHERE DEPTNO = :dept_number' 4. 方法四 这种方法可以在运行时确定 select 个数,变量个数,变量数据类型.例如: 'INSERT INTO EMP (<unknown>) VALUES (<unknown>)' 'SELECT <unknown> FROM EMP WHERE DEPTNO = 20'
printf("insert wLoginOpr%s' sql_str = [%s]\n",sV_YYYYMM,sql_str); EXEC SQL PREPARE ins_stmt From :sql_str; EXEC SQL EXECUTE ins_stmt using :sV_Total_date,:sV_LoginAccept,:sIn_Op_code,:sIn_Cust_id,:sIn_Org_code,:sIn_W ork_no,:sIn_Op_note,:sIn_Ip_Addr;
FETCH 根据 select 列表对应 into 语句返回一行记录,然后将游标指向下一行记录.
如果没有记录了,就返回 1403 CLOSE 关闭游标,如果游标被关闭了,就不能再使用了.
2.8.4. 方法四
需要另外一个文档描述了.
2.9. 总结
通过上面的分析对比,如果在可遇见的范围内,sql 不会重复执行,那么使用静 态和动态的第一种方法,如果有其他情况可以按照图示选择.
DECLARE cursor_name SCROLL CURSOR FOR statement_name;
OPEN cursor_name [USING host_variable_list];
FETCH [ FIRST| PRIOR|NEXT|LAST|CURRENT | RELATIVE fetch_offset
动态 sql 与静态
1. 动态 vs 静态
大多数应用程序在设计时都使用静态 sql 和 fixed 事务.这样,在运行之前就已 经知道要运行的 sql;这也就是说你已经知道哪些 sql 要执行,需要操作哪些表,要更 新哪些数据等等.
然而,有些程序需要在运行时处理所有 sql.所以你有可能在运行时才能知道 这些 sql,和需要用到的列名和表名.动态 sql 是一种可以让你的程序在运行时处理 或者生成动态 sql 的一种高级编程技巧,并且还可以进行显式的数据转换.
'000',0,0,0 ,0,0,0,0,0,0,'0','0','%s', '%s', '0','0')", atoi(total_date)/100,
vIdNo, total_date, login_accept, sm_code, belong_code, iPhoneNo, belong_code, login_no, op_code, op_time, vRetMsg, vRetMsg);
2.2. 动态 sql 的优点
程序使用动态 sql 要比使用静态 sql 灵活很多.动态 sql 可以实现交互.这样的 动态 sql 可以实现高灵活性的编码.
2.3. 动态 sql 缺点
但是动态 sql 又需要高复杂度的编码,,并且需要用到特殊的数据结构,同时增 加程序运行时的处理量.
增加程序运行时间,提高编写难度.
\
and a.offer_id=b.offer_id
\
and b.offer_type=10 \
and a.exp_date>sysdate");
EXEC SQL PREPARE SqlStmt FROM :SqlStr; EXEC SQL declare curSql cursor for SqlStmt; EXEC SQL OPEN curSql; if(SQLCODE!=0) {
2. ORACLE 动态 sql
2.1. 什么是动态 sql
大部分程序在编译时已经知道更新哪个表,哪个字段,和字段的数据类型. 但是,还有一些程序必须处理不确定的 sql,例如通用报表必须使用不同的 select 语句.这样的话 sql 只有到运行的时候才能确定,这样的语句就叫做动态 sql. 和静态 sql 不一样,动态语句可以存储在字符串里,也可以从文件中读取,还能在运 行的时候通过用户输入拼装出来.
sprintf(SqlStr,"SELECT a.SERV_ID,a.OFFER_ID,TO_CHAR(a.EFF_DATE,'YYYYMMDD')
\
FROM PRODUCT_OFFER_INSTANCE a,PRODUCT_OFFER b \
WHERE
TO_CHAR(a.EFF_DATE,'YYYYMMDD')=TO_CHAR(SYSDATE,'YYYYMMDD')
values(to_number(:sV_Total_date),to_number(:sV_LoginAccept),:sIn_Op_code,'0',0,\ 'ZZ',to_number(:sIn_Cust_id),'Z',:sIn_Org_code,\ :sIn_Work_no,sysdate,:sIn_Op_note,:sIn_Ip_Addr)",sV_YYYYMM);
|ABSOLUTE fetch_offset ]
cursor_name INTO
host_variable_list;
CLOSE cursor_name;
PREPARE:
分析一个 sql 语句并且给他命名.
DECLபைடு நூலகம்RE
声明一个游标变量,并给他一个名字,最后把他和一个查询语句关联起来..
OPEN
分配一个游标变量,然后把所有的输入变量和他绑定,最后执行查询语句.
2.4. 何时需要用到动态 sql
静态 sql 可以满足大部分的需求,当你需要无限扩展的灵活性时需要用到动 态 sql.
在以下其中之一不确定的时候需要用到动态 sql: 1. sql 语句 2. 变量个数 3. 变量类型 4. 对象
2.5. 动态 sql 如何工作
首先检查语法.然后将变量绑定到 sql 上,oracle 将得到变量的地址这样就可以 读写了.
EXEC SQL PREPARE stm_shortaddmode1 FROM :temp_sql; EXEC SQL EXECUTE stm_shortaddmode1;
/* dyn_stmt now contains the text of a SQL statement */ EXEC SQL EXECUTE IMMEDIATE :dyn_stmt; } ... 上面就是方法一,也可以使用下面的代替: EXEC SQL EXECUTE IMMEDIATE 'REVOKE RESOURCE FROM MILLER'; 但是 EXECUTE IMMEDIATE 在每次执行之前都要进行解析,所以方法一最 适用的是一次性 sql.一般用来执行 DDL
other_fee,hand_fee,deposit,back_flag,encrypt_fee,system_note,op_note,group_id,org_i d)\
values(%s,'%s',%d,'%s','%s','%s','%s','%s','%s',to_date('%s','yyyymmdd hh24:mi:ss'),\
2.8.2. 方法二
语法:EXEC SQL PREPARE statement_name FROM { :host_string | string_literal };
Prepare 一次,但是可以循环执行很多次.
2.8.3. 方法三
语法: PREPARE statement_name FROM { :host_string | string_literal };
动态 sql 在执行效率上,对于重复的 sql 确实要高于静态,但是会带来编码上的 难度.
例子:
正确写法: init(TmpSqlStr); sprintf(TmpSqlStr,"select nvl(sum(pay_money),0) from wpay%6d where contract_no=:v1 ", in_year_month); EXEC SQL EXECUTE
个数和数据类型必须是已知的.例如: 'INSERT INTO EMP (ENAME, JOB) VALUES (:emp_name, :job_title)' 'DELETE FROM EMP WHERE EMPNO = :emp_number'
3. 方法三 使用 DECLARE, OPEN, FETCH, CLOSE cursor 可以使用 select,并且 select
然后,执行这些 sql,根据 sql 更新,删除.这些 sql 可以用不同的新值替换,然后重 复执行.
2.6. 使用动态 sql 的方法
1. 方法一 使用 EXECUTE IMMEDIATE,不能包含 select,不能包含带有变量的占位
符.例如: 'DELETE FROM EMP WHERE DEPTNO = 20' 'GRANT SELECT ON EMP TO scott' 2. 方法二 使用 PREPARE 和 EXECUTE,sql 不能包含 select,在编译的时候变量的
printf("查询销售品更换用户出错,查找出错原因,并重新执行!"); goto end_change; } for(;;)
{ EXEC SQL fetch curSql INTO :serv_id, :offer_id,:eff_date;
if (SQLCODE!=OK) {
if (SQLCODE==NOTFOUND) break; EXEC SQL CLOSE curSql; printf("取销售品更换的用户出错! [SQLCODE=%d][SQLERRMSG=%s]\n",SQLCODE,SQLERRMSG); goto end_change; }
2.7. 如何选择动态 sql
2.8. 方法举例和分析
2.8.1. 方法一
char dyn_stmt[132]; ... for (;;) {
printf("Enter SQL statement: "); gets(dyn_stmt); if (*dyn_stmt == '\0')
break;
BEGIN EXECUTE IMMEDIATE :TmpSqlStr INTO :value_money using :in_contract_no;
END; END-EXEC;
sprintf(sql_str,"insert into wLoginOpr%s( \ total_date,login_accept,op_code,pay_type,pay_money, \ sm_code,id_no,phone_no,org_code,login_no,op_time,op_note,IP_ADDR) \
相关文档
最新文档