当前位置: 首页 > 資訊 >

[FGL] 程式開發(4) - 查詢條件輸入(QBE: Query By Example)

這個章節中,我們探討四類查詢指令中剩下的 QBE 條件輸入指令 CONSTRUCT。做完條件的輸入後自然就是將查詢語句組裝好,傳到資料庫內開始搜尋,這個動作上也有一些需要注意的,將會在此段同時進行提醒。

CONSTRUCT 查詢條件輸入

因為 INPUT 區分兩種指令方式:輸入用的畫面欄位與變數元素可以對應的(INPUT BY NAME) 與不可對應的 (INPUT...FROM...),因此 CONSTRUCT 一樣可以區分成兩種:

  1. 可以對應元素的 CONSTRUCT BY NAME str_where ON column1, column2, column3...
  2. 不可以對應元素的 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條件到取出資料

https://ithelp.ithome.com.tw/upload/images/20210922/20051169rkOgfAwRPs.png

我們設計完一張表格畫面後,自然是希望用戶能夠在裡面看到想查詢的資料。透過讓用戶挑選欄位進行資料指定 (如果不輸入的話就是資料全選,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 來的方便些。

特別註記

  1. DECLARE-FETCH/FOREACH 可以分散在不同function中,但是『物理上』編譯到FETCH/FOREACH 段落時,一定要先『編譯過DECLARE』 (也就是說 DECLARE 所在行號要小於 FETCH/FOREACH的行號!!!)
  2. PREPARE id / DECLARE id 都屬於『模組變數』,單一4GL檔案內不可重複

希望透過本段的講解,能讓大家更理解抓取資料的方法。也完成四項交談指令的介紹。