文章来自:iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)
[day21] FGL 程序开发(4) – 查询条件输入(QBE: Query By Example)
这个章节中,我们探讨四类查询指令中剩下的 QBE 条件输入指令 CONSTRUCT。做完条件的输入后自然就是将查询语句组装好,传到数据库内开始搜寻,这个动作上也有一些需要注意的,将会在此段同时进行提醒。
CONSTRUCT 查询条件输入
因为 INPUT 区分两种指令方式:输入用的画面字段与变量元素可以对应的(INPUT BY NAME) 与不可对应的 (INPUT…FROM…),因此 CONSTRUCT 一样可以区分成两种:
- 可以对应元素的 CONSTRUCT BY NAME str_where ON column1, column2, column3…
- 不可以对应元素的 CONSTRUCT str_where ON column1, column2, column3… WHERE scr1, scr2, scr3…
这两种指令,最后得到的都会是经过 FGL 协助组装后的 WHERE 字符串。
为什么不用 INPUT 来做一样的事情?如果能控制到特殊符号的使用 (例如 :转换为 BETWEEN 等),或是全部没输入时自动改为 1=1 输出;若做得来这件事,可以自行改用 INPUT。
控制区块(Conteol Block)
CONSTRUCT指令并不理会是否为 ARRAY 的数据,因为他的目的只是在询问用户『要查询哪些字段的哪些数据』,因此碰到 TABLE 的时候,只需要指定一排 (通常是第一排,应该不会指定第 4518排吧?) 让用户进行查询数据的指定就可以。
所以整体的控制区块,与 INPUT 指令相同,基本的控制 ON ACTION/ ON IDLE/ ON TIMER 与字段控制 BEFORE FIELD a / AFTER FIELD a / ON CHANGE a 之类的区块。
取得 WHERE条件到取出资料
我们设计完一张表格画面后,自然是希望用户能够在里面看到想查询的数据。透过让用户挑选字段进行数据指定 (如果不输入的话就是数据全选,WHERE条件则是 1=1),接下来要做的就是组合条件、执行SQL、抓取数据三步骤。
PREPARE
依照需求进行 SQL指令的撰写,这道基本题就让各位自行研究。我们透过
LET ls_sql=”SELECT ….WHERE “,where_condiction
的方式可以将字符串组装起来。当然,并不限定说只能将 CONSTRUCT 的结果放在此处,而是有需要的都可以拿来这里进行组装。组装后,请记得拿到的是『** SQL字符串 **』而不是 SQL指令。此时就要透过 PREPARE 协助转换为 PREPARE ID,这才是可以交付执行的部分。
PREPARE query_prepare FROM ls_sql
DECLARE
宣告,也就是告知数据库要执行的指令为何。以数据库的角度来说,即是通知数据库将要执行的SQL指令,让数据库开始进行『语法检查、硬解析hard parse』。在 CURSOR 中,必须告诉数据库,稍后是一笔一笔输出还是连续不断的输出。
DECLARE query_declare CURSOR [WITH HOLD] FOR query_declare
上述范例,如果加上 WITH HOLD就会是一笔一笔的输出。
退回到上一段 PREPARE,如果整个 SQL指令并没有一堆变量组装,而是一个直接撰写的 SQL 指令,可以省略 PREPARE直接做 DECLARE 吗?可以的,将 FOR prepare id 改为 FROM sql_statement 就可以了。
FETCH/FOREACH
最终透过 FETCH/FOREACH 就可以取得数据。对了,若有参数是在 SQL指令订定时所不知道的,可以使用 ? 传递。
其实最该用 ? 传递的是『日期/时间』,因为如果用组字符串的方式传入,必须保证在执行当下取得的变量呈现格式与 db 需求格式是相符的,这并不容易且不好除错,因此日期数据的传入,多建议使用 ? 进行
完整的 QBE转查询范例
https://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_result_sets_DECLARE.html
SQL BLOCK
在 DECLARE 段落中,有谈到使用DECLARE 时,会将 『SQL字符串』传入数据库内做硬解析。所以,这个字符串想必『需要符合数据库能看懂的语法』 !!
举例来说,Genero默认使用INFORMIX语法时,而又我们环境链接的是 ORACLE数据库,那在做 DECLARE 的时候,就要用 ORACLE的语法写、用ORACLE的 function、变量等。否则 ORACLE 看到 INFORMIX专用的语法,一定会因为认不得而出错。
又,除了 DECLARE 之外,另外在 FGL中,为了和 i4GL 兼容,还支持下列语法
SQL
SELECT COUNT(1) INTO $变数 FROM test
END SQL
中间的变量就是 FGL的变量。透过这样的方式,会比到处要做 DECLARE 来的方便些。
特别注记
- DECLARE-FETCH/FOREACH 可以分散在不同function中,但是『物理上』编译到FETCH/FOREACH 段落时,一定要先『编译过DECLARE』 (也就是说 DECLARE 所在行号要小于 FETCH/FOREACH的行号!!!)
- PREPARE id / DECLARE id 都属于『模块变量』,单一4GL档案内不可重复
希望透过本段的讲解,能让大家更理解抓取数据的方法。也完成四项交谈指令的介绍。
转载请注明:赫非域 » [day21] FGL 程序开发(4) – 查询条件输入(QBE: Query By Example)