文章目录

  • 前言
  • Genero FGL
    • 是什么?
    • 优点
    • 组成部分
    • 编译
    • 连接
      • 连接语法
    • 运行
    • 其他GDC命令
    • Hello Wold程序
      • 编译前处理
  • Genero FGL 语法
    • 定义变量
    • 变量类型
      • STRING类型的METHOD
    • Genero 的预定义变量
    • 定义变量集合(Records)
    • 使用数据结构(TYPE)
    • 变量赋值
      • 语法
    • 变量值初始化(INITIALIZE)
    • 预定义常数(PRE-DEFINED Constant)
    • 定义常数
    • 运算符
      • 比较运算符
      • 逻辑运算符
      • 数值运算符
      • 字符串运算符
      • 关联运算符
      • 日期运算符
      • 对话框处理运算符(Dialog handling)运算符
    • 设置全局变量(GLOBALS)
    • 变量的生命周期
    • USING
      • 数值
      • 日期
  • 流程控制
    • Moudle架构
      • 前端的设定:
        • 导入外部程序
        • 声明参照数据库
        • 全局或模组变量
      • 函数
        • MAIN函数
          • OPTIONS设置(图)
          • 套件
            • os.Path
            • dirname / basename / rootname及extension的比较
            • util.Math
        • 一般FUNCTION函数
        • 报表结构函数REPORT
        • 函数相关的内容
          • CALL
          • RETURN
            • 函数相关的练习
        • 常用内置函数 built-in-functions
    • 4GL注解
    • IF
    • CASE
    • FOR
    • WHILE
    • CONTINUE
    • EXIT
    • TRY CATCH
    • SLEEP
    • LABEL
    • GOTO
  • 基本输入输出 Channel
  • 输入(INPUT)
    • 语法:
    • INPUT架构(生命周期)
      • 控制区间执行顺序(时间触发之后,函数执行顺序)
      • INPUT 控制点(触发的事件)
      • WITHOUT DEFAULTS
  • PROMPT
  • 指标(CURSOR)
    • CONSTRUCT
    • PREPARE
    • FREE
    • CURSOR两个值
      • SCROLLING CURSOR
        • 组成部分
          • DECLARE
          • OPEN
          • FETCH
          • CLOSE
          • SCROLLING CURSOR eg:
      • NON-SCROLLING CURRSOR
        • DECLARE 声明
        • FOREACH 声明
        • FOREACH 与 FETCH的不同
        • NON-SCROLLING CURSOR eg:
  • 数据的锁定(LOCK)
    • LOCKING CURSOR
      • LOCKING CURSOR组成部分
        • DECLARE
        • OPEN
        • FETCH
        • CLOSE
          • LOCKING CURSOR eg:
  • USING
  • 事务(TRANSACTION)
  • 大量执行同一Sql(EXECUTE)
  • 大量执行INSERT(PUT...FLUSH)
  • 阵列(ARRAY)
    • 固定阵列
    • 动态阵列
    • 阵列可使用的方法
    • 阵列相关练习
    • DISPLAY ARRAY
      • 控制属性
      • 事件触发后执行的控制段
      • DISPLAY ARRAY eg1(ARRAY显示到TABLE):
      • DISPLAY ARRAY eg2(ARRAY显示到TREE):
    • CLEAR SCREEN ARRAY
  • 对话框(DIALOG)
    • DIALOG封装的指令
    • 语法
    • ui.Dialog方法
  • 总结

前言

  1. 负责的说如果你是刚接触T100,可以不用通读全文,看看目录,大概知道有什么就可以了,后期使用的时候来搜索,节省时间。
  2. 关于内容方面,如果发现有什么问题,如果你愿意,可以联系我修改,谢谢。

Genero FGL

是什么?

由Four j's基于INFORMIX数据开发的的数据库管理语言

优点

  1. 分为client与server端,加快执行效率
  2. 通过XML在client与server端传递数据
  3. 支持不同的操作系统与数据库平台
  4. 引入基本对象的概念
  5. 可以在执行阶段控制输出的格式

组成部分

  1. 页面(Form)与程序(Moudle)组成程序作业(Program)
  2. 程序(Moudle)由函数(Function)与 (Report)组成
  3. 作业(Program)必须指明执行的入口

编译

Moudle编译语法(4gl ==》42m):fglcomp [編譯參數] 待編譯檔檔名[.4gl]Form编译:文字格式(per档):语法(per ==》 42f):fglform [編譯參數] 待編譯檔檔名[.per]XML格式(4fd档)语法(4fd ==》 42f)gsform [編譯參數] 待編譯檔檔名[.4fd]

连接

首先,如果不需要使用外部的4gl可以忽略连接(link)直接执行(execute)作业


其次,如果该作业有子程序或副程序(如上图),可以将不含MAIN的子程序打包为动态连接库(42x),最后再与主程序共同连接生成作业执行档(42r)。

连接语法

fgllink -o 連結完成的完整檔名 待連結檔案 1 [待連結檔案 2] ….
eg: fgllink -o test.42x text1.42m text2.42m text13.42m fgllink -o program.42r text.42x main.42m other.42m

页面不需要连接,直接通过OPEN WINDOW…WITH FORM 指令直接呼叫 42f

运行

运行前需要开启GDC(Genero Desktop Client)并占用的6400端口
运行语法:fglrun [執行參數] 執行檔檔名[.42r]

其他GDC命令

1. fglrun -V 查看GDC版本

Hello Wold程序

1. 编写hello.4gl文件MAINDISPLAY "HELLO, WORLD!"END MAIN
2. 编译4gl文件fglcomp hello
3. 没有使用外部4gl,所以可以跳过连接直接运行fglrun hello

编译前处理

1. &includeeg: &include "common_action.4gl"会将导入的文件一起编译
2. &defineeg: &define MAX_VALUE 12等同于constant,在程序内均可以使用该常量
3. &ifdef、&else、&endifeg:&defineIS_DEFINED&ifdef IS_DEFINED DISPLAY "defind!" &endif

Genero FGL 语法

定义变量

语法:1. DEFINE 变量名 变量类型2. DEFINE 变量名 LIKE 数据库表名.字段名
eg:1. DEFINE employee_no CHAR(20)2. DEFINE p_employee_no LIKE employee_file.employee_no,p_team_no SMAILINT,p_join_date, p_birthday DATE
ps:1. 使用数据库对应字段的方式定义变量,需要使用DATABASE或SCHEMA声明数据库2. 创建变量是尽量采用变量的方式,后期修改变量就不用手动修改字段宽度3. 连续定义可以使用逗号隔开,省略DEFINE声明4. 同类型的定义可以使用逗号合并使用

变量类型

STRING类型的METHOD

Genero 的预定义变量

定义变量集合(Records)

# 方法一(直接定义):DEFINE rec RECORDid INTEGER,name VARCHAR(20),birth DATEEND RECORD
# 方法二(对于数据库中的字段):DEFINE cust RECORD LIKE customer.*
# 方法三(对于数据库中的字段):DEFINE cust RECORDid LIKE customer.idname LIKE customer.namebirth LIKE customer.birthEND RECORD

使用数据结构(TYPE)

eg1:PUBLIC TYPE customer RECORDid INTEGER,name VARCHAR(20),birth DATEEND RECORDDEFINE c customer # 使用定义的数据结构定义变量eg2:PUBLIC TYPE rpt_order RECORDorder_num INTEGER,store_num INTEGER,order_date DATE,fac_code CHAR(3)END RECORDMAINDEFINE o rpt_order #使用資料結構 rpt_order 並取名為 oDECLARE order_c CURSOR FORSELECT order_num, store_num, order_date, fac_code FROM ordersSTART REPORT order_list FOREACH order_c INTO o.*OUTPUT TO REPORT order_list(o.*)END FOREACHFINISH REPORT order_listEND MAIN REPORT order_list(ro)DEFINE ro rpt_order #使用資料結構 rpt_order 並取名為 roFORMATON EVERY ROWPRINT ro.order_num, ... #使用 ro.* 存取資料

变量赋值

通过LET给定义好的变量赋值

语法

LET variable = expression
eg:MAINDEFINE c1,c2 CHAR(10)LET c1 = "GENERO"LET c2 = c1END MAIN

变量值初始化(INITIALIZE)

使用场景:初始化数据结构(Records)的变量为NULL,或则为数据结构的预设值
eg:DEFINE cr RECORD LIKE customer.*INITAILIZE cr.cust_name TO NULLINITAILIZE cr.* LIKE customer.*

预定义常数(PRE-DEFINED Constant)

定义常数

使用CONSTANT定义常数
语法:CONSTANT constant_id [data_type] = value 可不指明数据类型,会自动设置,设置错误也会自动修改
eg:CONSTANT c1 = "Drink" -- 自行宣告為 STRINGCONSTANT c2 = 4711 -- 自行宣告為 INTEGERCONSTANT c3 SMALLINT = 12000 -- 自行修正為 INTEGERCONSTANT c4 CHAR(10) = "abc" -- 遵照設定為 CHAR(10)

运算符

比较运算符

逻辑运算符

数值运算符

字符串运算符


关联运算符

日期运算符

对话框处理运算符(Dialog handling)运算符

设置全局变量(GLOBALS)

方法一(直接定义):
语法:GLOBALSdeclaration-statement[,...]END GLOBALS
eg:GLOBALSDEFINE g1 VARCHAR,DEFINE g2 VARCHAREND GLOBALS
方法二(导入外部文件):
语法:GLOBALS "filename"

变量的生命周期

Local变量(Local Variables)位置:Moudle中的函数(FUCTION、MAIN等)中生命周期:与函数共存亡
Moudle变量(Moudle Variables)位置:位于Moudle中,函数外生命周期:属于当前Moudle
Global变量(Global Variables)位置:GLOBALS和END GLOBALS中生命周期:属于所有Moudleeg:SCHEMA dsGLOBALSDEFINE g_employee CHAR(10) END GLOBALSDEFINE g_tty CHAR(32)MAINDEFINE answer CHAR(1)END MAINFUNCTION ins_employee()DEFINE flag CHAR(1),change SMALLINTEND FUNCTION以上示例属于GLOBAL变数的有g_employee属于MODULE变数的有g_tty属于LOCAL变数的有answer、flag、change

USING

指定数字或日期的输出格式

数值

日期


eg:

流程控制

Moudle架构

程序(Moudle)可以简单分为前段的设定+函数:

前端的设定:

导入外部程序

eg:1. 导入4GL函数库IMPORT FGL 42m_modulde2. 导入java程序IMPORT JAVA class_name3. 导入C-extension或程序标准函数库IMPORT pacakage 包名ps:不可以循环IMPORT,否则编译时会报错

声明参照数据库

 SCHEMA 声明数据库在编译的时候起参照作用,执行程序是不会进行数据库的连接DATABASE声明数据库除了编译的时候起参照作用,执行时也会进行数据库的连接eg:SCHEMA dsMAINDEFINE lc_zz01 LIKE zz_file.zz01SELECT zz01 into lc_zz01 FROM zz_file where zz01='hgh'END MAIN由于SCHEMA没有真正连接数据库,所以上面的代码会返回一下错误:Program stopped at 'test_schema.4gl', line number 5.SQL statement error number -1803 (-1). Connection does not exist.

全局或模组变量

函数

MAIN函数

一个程序只能有一个MAIN函数
MAIN函数eg:
MAINDISPALY "Hello World!~"
END MAIN
MAIN中的设置DEFER 设置定义是否拦截中断(interrupt)或退出(quit)信号语法:DEFER { INTERRUPT | QUIT }ps:1. DEDER INTERRUPT:当使用者按下中断键(Ctrl+c或Delete键),系统会拦截信号并将INT_FLAG设置为TRUE。当程序中包含ON ACTION interrupt也会重复上述流程。2. DEDER QUIT:当使用者按下退出按键,系统会拦截信号并将QUIT_FLAG设置为TRUE,以及中断程序。OPTIONS设置修改系统预设项,见 OPTIONS设置(图)Exceptions设置当发生SQL错误时,告诉系统该如何处理。程序中想改变应对方式时可再次设置,即以新设置方式处理。语法:WHENEVER [ANY] ERROR { CONTINUE | STOP | CALL function | GOTO label }
MAIN中的设置eg:MAINOPTIONS  #修改系统预设值INPUT NO WRAP, #离开最后一个输入格不重新开始FIELD ORDER FORM  # 数据输入按照字段的顺序WHENEVER ERROR STOP    # 发生错误,程序停止运行DISPLAY "Change Exception!"   # 提示WHENEVER ERROR chk_err  # 发生错误调用函数,此处调用函数无需括号END MAINFUNCTION chk_err()DISPLAY "Error Hanppend"END FUNCTION
OPTIONS设置(图)

套件


os.Path

eg:  IMPORT OSMAINDISPLAY "The Path is :", os.Path.pwd()IF os.Path.mkdir("newdir") THEN DISPLAY "New a new directory OK" END IFEND MAIN
dirname / basename / rootname及extension的比较

util.Math
eg:IMPORT utilMAINDISPLAY util.Math.pi()END MAIN

一般FUNCTION函数

函数提供一些特定的功能,也称为子函数
语法:
[PUBLIC | PRIVATE ] FUNCTION function_name( [arg [ , … ] ] )
eg:MAINCALL say_hello_public()CALL sya_hello_private()END MAINFUNCTION say_hello_public()DISPLAY "Hello, world"END FUNCTIONFUNCTION say_hello_private()END FUNCITON

报表结构函数REPORT

用于设置输出报表的格式
eg:REPORT test_rep(sr)FORMAT·PAGE HEADERBEFORE GROUP ON EVERY ROWAFTER GROUPEND REPORT

函数相关的内容

CALL
执行函数,若有返回值使用RETURING 接收
语法:CALL function ( [ parameter [,...] ] ) [ RETURNING variable [,...] ]
RETURN
返回数值,并结束函数的运行
语法:RETURN [ value [,...] ]
函数相关的练习
1. 返回字符串MAINDEFINE var1 CHAR(10)DEFINE var2 CHAR(10)LET var1 = foo()DISPLAY "var1 = " || var1CALL foo() RETURNING var2DISPLAY "var2 = " || var2END MAINFUNCTION foo()RETURN "hello"END FUNCTION
2. 返回布尔值MAINIF foo() THENDISPLAY "Hello World"END IFEND MAINFUNCTION foo()RETURN TRUEEND FUNCTION
3. 返回两个值MAINDEFINE var1 CHAR(10)DEFINE var2 CHAR(10)CALL foo() RETURNING var1 var2DISPLAY var1,var2END MAINFUNCTION foo()RETURN “hello”,"world"END FUNCTION

常用内置函数 built-in-functions

4GL注解

{} 模块注解
#、-- 单行注解

IF

语法:IF condition THENstatement[...][ELSEstatement[...]]END IF
eg:MAINDEFINE name CHAR(20)LET name = "John Smith"IF name MATCHES "John*" THENDISPLAY "The first name is too common to be displayed."IF name MATCHES "*Smith" THENDISPALY "Even the last name is too common to be displayed."END IFELSEDISPLAY "This name is ",name,"."END IFEND MAIN

CASE

语法一:CASE expression-1WHEN expression-2{ statement | EXIT CASE }[...][ OTHERWISE{ statement | EXIT CASE }[...]]END CASE
eg:MAINDEFINE v CHAR(10)LET v = "C1"CASE vWHEN "C1"DISPLAY "This is C1."WHEN "C2"DISPLAY "This is C2."OTHERWISEDISPLAY "Unexpected value"  END CASE    END MAIN
语法二:当有多个表达式值为真,使用第一个符合条件的statementCASEWHEN boolean-expression1{ statement | EXIT CASE}[...]WHEN boolean-expression2{ statement | EXIT CASE}[...][OTHERWISE{ statement | EXIT CASE}[...]]END CASEeg:MAINDEFINE v CHAR(20)LET v = "C1"CASEWHEN (v="C1" OR v="C2")DISPLAY "This is C1 or C2."WHEN (v="C3" OR v="C4")DISPLAY "This is C3 or C4."OTHERWISEDISPLAY "Unexpected value."END CASEEND MAIN

FOR

语法:FOR counter = start TO finish [ STEP value ]statement[...]
eg:MAINDEFINE i, i_min, i_max INTEGERLET i_min = 1LET i_max = 10DISPLAY "正序:"FOR i = i_min TO i_maxDISPLAY iEND FORDISPLAY "倒序:"FOR i = i_max TO i_min STEP -1DISPLAY iEND FOREND MAIN

END FOR

WHILE

语法:WHILE b-expressionstatement[...]END WHILE
eg:MAINDEFINE a, b INTEGERLET a=20LET b=1WHILE a>bDISPLAY "a>b"LET b = b + 1END WHILEEND MAIN

CONTINUE

语法:CONTINUE { FOR | FOREACH | MENU | CONSTRUCT | INPUT | WHILE }
eg:MAINWHILE TRUEDISPLAY "Show this expression."COTINUE WHILEDISPLAY "Never show this expression."END WHILEEND MAIN

EXIT

语法:EXIT { CASE | FOR | MENU | CONSTRUCT | FOREACH | REPORT | DISPLAY | INPUT | WHILE | PROGRAM }
eg:MAINDEFINE i INTEGERLET i = 1WHILE TRUELET i = i + 1IF i = 100 THENEXIT WHILEEND IFEND WHILEDISPLAY "OK!"END MAIN
ps:执行 EXIT PROGRAM,程序通过正常方式退出,不会抛出异常。可以传出大小为8bit的数值,传负数,exit_code接收时自动转为正数。eg:EIXT PROGRAM(1)

TRY CATCH

语法:TRY[待偵測是否會發生問題的程式段落]CATCH[處理問題或回報訊息的程式段落]END TRY
eg:MAINLET lc_a = ARG_VAL(1)TRYDATABASE lc_aCATCHDISPLAY lc_a,' not in fglprofile, number:',SQLCA.SQLCODEEND TRYEND MAIN

SLEEP

语法:SLEEP seconds
eg:MAINDISPlAY "Sleep 5 seconds."SLEEP 5DISPLAY "Sleep ok!"END MAIN

LABEL

在程序中添加书签
语法:LABEL label-id〆

GOTO

跳转放到指定位置
语法:GOTO〆 label-id
eg:MAINDISPLAY "Before GOTO"GOTO: label_id1DISPLAY "Never Been Displayed"LABEL label_id1:DISPLAY "After GOTO"END MAIN

基本输入输出 Channel

通过内置的base.Channel函数库,可以读写txt文件、以及执行系统命令(ls -a等)获取系统信息
eg1(读取文件内容):
custinfo.txt:8712|David|Cosneski|24-12-1978|3422|Frank|Zapinetti|13-04-1968|323|Mark|Kelson|03-10-1988|
MAINDEFINE ch base.Channel  # 定义变量ch,用于存储Channel实例DEFINE custinfo RECORD    # 定义结构体用于存储文本文件的数据cust_num INTEGER,cust_fname VARCHAR(40),cust_lname VARCHAR(40),cust_bdate DATEEND RECORDLET ch = base.Channel.create()   # 创建Channel实例CALL ch.setDelimiter("|")    # 设置文本分隔符CALL ch.openFile("custinfo.txt", "r") # 通过文件的方式打开custinfo.txt,设置行为rWHILE ch.read([custinfo.*])  # 循环读数据到custinfo中DISPLAY custinfo.* # 打印读入的数据END WHILECALL ch.close()   # 关闭Channel,释放资源
END MAIN
eg2(读取系统指令获取的内容):MAINDEFINE fn STRING  # 定义变量存储用来存储结果DEFINE ch base.Channel    # 定义Channel变量存储实例LET ch = base.Channel.create() CALL ch.setDelimiter("") # 执行系统指令无需设置分隔符CALL ch.openPipe("ls -l", "r")   # 通过管道的方式执行ls -l指令,设置行为是读rWHILE ch.read(fn)  # 循环便利DISPLAY fnEND WHILECALL ch.close()END MAIN

输入(INPUT)

使用INPUT输入数据,必须要页面显示到屏幕上

语法:

 1. Implicit field-to-variable mapping:INPUT BY NAME { variable | record.* } [,...][ WITHOUT DEFAULTS ][ ATTRIBUTE ( { display-attribute | control-attribute } [,...] ) ][ HELP help-number ][ dialog-control-block[...]END INPUT ] 2. Explicit field-to-variable mapping:INPUT { variable | record.* } [,...][ WITHOUT DEFAULTS ]FROM field-list[ ATTRIBUTE ( { display-attribute | control-attribute }[,...] ) ][ HELP help-number ][dialog-control-block[...]END INPUT ]eg:语法1:INPUT BY NAME p_employee.no语法2:INPUT p_employee.no FROM nops:如使用语法1,没有指定【FIELD ORDER FORM】顺序,则使用定义这组变量的顺序

INPUT架构(生命周期)

控制区间执行顺序(时间触发之后,函数执行顺序)

INPUT 控制点(触发的事件)

WITHOUT DEFAULTS

 使用INPUT给栏位(变量)会使用栏位的属性defaultvalue给栏位设值,如果没有设置defaultvalue,则使用
NULL,但如果数据库中已经有数据也会被设置为NULL,导致数据丢失,因此要使WITHOUT DEFAULTS保留原先的值
eg:SELECT * INTO p_employee.* FROM employee_fileWHERE no = ‘David’DISPLAY BY NAME p_employee.*INPUT BY NAME p_employee.* WITHOUT DEFAULTS

PROMPT

询问一些小问题,类似与弹窗,并可以获取用户的答案
语法:PROMPT question FOR [CHAR[ACTER]] variable [ ATTRIBUTE ( input-attributes ) ]ON ACTION action-name#僅有二控制區塊,與 INPUT 功能相同。ON IDLE idle-secondsEND PROMPT
eg:MAINDEFINE a CHAR(10)PROMPT "Are you ok? " FOR CHAR aON IDLE 30EXIT PROGRAMEND PROMPTEND MAIN

指标(CURSOR)

 当进行SQL查询的时候,若需要一次查找多个资料,是一次性查取,还是查询一次处理完成之后再查取。这就要通过一个指标(CURSOR)来说明。首先说明
与SQL查询相关的CONSTRUCT、PREPARE、FREE。

CONSTRUCT

语法一:

ps:1. char_variable 為接取使用者輸入資料的字串變數(建議以 STRING 格式變數接取)2. column_list 為對應到表格(TABLE)的欄位名稱清單(逗號隔開)3. field_list 為畫面(WINDOW 或是 FORM)上的欄位代碼清單(逗號隔開)4. 若有增加控制區段(CONTROL BLOCK,如 ON ACTION 等),則就要加上『END CONSTRUCT』
语法二:

eg(CONSTRUCT 結束後會將組合完成的 WHERE 條件置入『l_str』後回傳到程式中):
CONSTRUCT BY NAME l_str ON employee, salaryON IDLE 10EXIT PROGRAM
END CONSTUCT    # l_str =『employee='1000' AND salary>'30000'』

PREPARE

通过CONSTRUCT获取到查询条件之后,需要使用PREPARE转为真正可执行的SQL指令
PREPARE会检查SQL语法的正确性,执行之后还会传递回一个返回值(prepared-id)。
语法:PREPARE statement-name FROM char_variable
ps:1. statement-name即返回值(prepared-id)。2. 使用PREPARE之前,应确保SQL是完整的,例如加上SELECT等。

FREE

释放PREPARE内存
语法:FREE statement-name
eg:...LET l_str = "“employee='1000' AND salary>'30000’"LET l_sql = "SELECT * from employee_file WHERE", l_strPREPARE emp_pre FROM l_sql...FREE emp_pre...

CURSOR两个值

SCROLLING CURSOR

一次取一个数据,处理完毕之后,可以修改指针位置获取其他数据
语法:DECLARE cursor_id CURSOR [WITH HOLD] FOR sql statementFOREACH cursor_id[USING value][INTO variable ]…END FOREACH

组成部分

DECLARE
1. 語法﹝1﹞使用已知的 SQL 敘述進行 CURSOR 宣告:DECLARE cursor_id SCROLL CURSOR FOR select-statement2. 語法﹝2﹞使用已宣告的 PREPARED ID 來進行 CURSOR 宣告:DECLARE cursor_id SCROLL CURSOR FOR prepared_id 3. 語法﹝3﹞使用已知的 STRING 敘述進行 CURSOR 宣告:DECLARE cursor_id SCROLL CURSOR FROM string-expression
OPEN
在SCROLLING  CURSOR的情况下使用CURSOR,需要通过OPEN打开CURSOR
语法:OPEN cursor_id [USING value]
ps:1. 可以通过status检查此命令是否执行成功
FETCH
移动cursor获取数据
语法:FETCH cursor_id INTO program_variable


CLOSE
在SCROLLING  CURSOR下,需要手动关闭cursor。
语法:CLOSE cursor_id
SCROLLING CURSOR eg:
DATABASE ds
MAINDEFINE a STRING DEFINE b,c CHAR(10)DECLARE test01 SCROLL CURSOR FORSELECT zz01 FROM zz_file WHERE zz01 = “axmt410”OPEN test01FETCH FIRST test01 INTO bDISPALY bLET c = "axmt410"LET a = "SELECT zz01 FROM zz_file WHERE zz01 = '",c CLIPPED,","DECLARE test02 SCRCOLL CURSOR FROM aOPEN test02FETCH LAST test02 INTO bDISPLAY
END MAIN

NON-SCROLLING CURRSOR

一次性获取所有所需数据
语法:DECLARE cursor_id CURSOR [WITH HOLD] FOR sql statementFOREACH cursor_id[USING value][INTO variable ]…END FOREACH

DECLARE 声明

1. 語法﹝1﹞使用已知的 SQL 敘述進行 CURSOR 宣告:DECLARE cursor_id SCROLL CURSOR FOR select-statement2. 語法﹝2﹞使用已宣告的 PREPARED ID 來進行 CURSOR 宣告:DECLARE cursor_id SCROLL CURSOR FOR prepared_id 3. 語法﹝3﹞使用已知的 STRING 敘述進行 CURSOR 宣告:DECLARE cursor_id SCROLL CURSOR FROM string-expression

FOREACH 声明

语法:FOREACH cursor_id INTO program_variableStatementEND FOREACH

FOREACH 与 FETCH的不同

1. FOREACH只能做循环获取数据,FETCH可以跳转获取数据
2. FETCH实现循环获取数需要搭配循环语句
3. FOREACH指令可以自动开启关闭CURSOR,FETCH必须手动开启关闭

NON-SCROLLING CURSOR eg:

MAINDEFINE clist ARRAY[300] OF RECORDcnum INTEGER,cname CHAR(50)END RECORDDEFINE l INTEGERDEFINE str STRINGDEFINE c_name CHAR(50)DATABASE storesLET c_name = ARG_VAL(1)LET str = "SELECT customer_num, cust_name FROM customer WHERE cname = ?"PREPARE  pre_id FROM strDECLARE c1 CURSOR FROM strFOREACH c1 USING c_name INTO clist[l].*LET l = l + 1END FOREACHDISPLAY "获取:",l," 条记录"
END MAIN

数据的锁定(LOCK)

LOCKING CURSOR

又名:FOR UPDATE CURSOR
用于对记录进行更新(UPDATE)时,将记录进行锁定(LOCK)。
语法:DECLARE cursor_name CURSOR FOR sql statement FOR UPDATE [NOWAIT]OPEN cursor_id [USING value]FETCH cursor_id INTO variableCLOSE cursor_id

LOCKING CURSOR组成部分

DECLARE

语法一:DECLARE cursor_id CURSOR FOR select_statement FOR UPDATE [NOWAIT]
语法二(char_variables是Sql变量):DECLARE cursor_id CURSOR FROM char_variable  FOR UPDATE [NOWAIT]
ps:与 SCROLL CURSOR 或 NOT-SCROLL CURSOR不同点在于:需要在最后加上 FOR UPDATE,对于ORACLE数据库还需加上NOWAIT

OPEN

打开cursor
语法:OPEN cursor_id

FETCH

读取数,并给记录加锁,其他人不能使用该记录,直到使用CLOSE关闭cursor_id
语法:FETCH cursor_id INTO program_variable

CLOSE

释放资源,取消记录的锁定
语法:CLOSE cursor_id
LOCKING CURSOR eg:
DATABASE ds
MAINDEFINE g_gav01 LIKE gav_file.gav01DEFINE g_gav02 LIKE gav_file.gav02LET g_forupd_sql = "SELECT * from gav_file WHERE gav01=? AND gav08=?", " FOR UPDATE"DECLARE p_per_lock_u CURSOR FROM g_forupd_sqlOPEN p_per_lock_u USING g_gav01, g_gav02IF STATUS THENCLOSE p_per_lock_u RETURNEND IFFETCH p_per_lock_u INTO  g_gav_lock.*IF SQLCA_sqlcode THENCLOSE p_per_lock_uRETURNEND IFCLOSE p_per_lock_u
END MAIN

USING

这里的USING使用来传值到Sql串中,之前那个USING是用来限制字符串输出的格式
语法:LET sql statement = “SELECT * FROM table_id WHERE key_value = ? “DECLARE cursor_name CURSOR FOR sql statement FOR UPDATE [NOWAIT]OPEN cursor_id USING value
ps:1. 使用USING传参,参数需要与Sql中的问号一一对应,使用逗号隔开2. USING的使用必须在OPEN(Scroll Cursor 与 Locking Cursor)、FOREACH(Non-scroll Cursor)、EXECUTE(批量执行Sql Cursor)之后
eg:...LET g_forupd_sql = "SELECT * from gav_file WHERE gav01=? AND gav08=?", " FOR UPDATE"DECLARE p_per_lock_u CURSOR FROM g_forupd_sqlOPEN p_per_lock_u USING g_gav01, g_gav02...

事务(TRANSACTION)

和Mysql的事务含义相同,执行多个UPDATE、INSERT、DELETE指令,通过事务处理让这些命令要么都执行成功,要么都都执行失败
语法:BEGIN WORK    # 开启事务[ UPDATE statement ][ INSERT statement ][ DELETE statement ]IF ( condiction ) THEN COMMINT WORK   # 提交事务ELSEROLLBACK WORK # 回滚事务END IF
ps:1. 使用BEGIN后一定要使用COMMINT WORK或ROLLBACK WORK说明SQ如何处理2. 建议BEGIN WORK后的Sql命令不要太多,以避免出现大量用户等待相同记录的操作权限3. 部分DDL(数据库定义语言,如CREATE TABLE)有自动COMMIT WORK的功能4. 当执行COMMIT WORK或ROLLBACK WORK后会自动CLOSRE掉没有在声明时加WITH HOLD的CURSOR

大量执行同一Sql(EXECUTE)

当执行大量同一Sql,可以通过循环+Sql的方式实现,通过EXECUTE效率更高
语法:PREPARE prepared_id FROM sql_statementEXECUTE prepared_id [USING variable_list ] [ INTO fvar [,...] ]FREE prepared_id
ps:1. EXECUTE可以应用到INSERT、DELETE、UPDATE、SELECT2. USING传值使用尽量在EXECUTE
eg:MAINDEFINE key INTEGERDEFINE name CHAR(10)PREPARE s1 FROM "UPDATE customer SET name=? WHERE customer_num=?"EXECUTE s1 USING name, keyFREE s1END MAIN

大量执行INSERT(PUT…FLUSH)

当大量插入数据时,比EXECUTE更快的方式时使用PUT...FLUSH
语法:PREPARE prepared_id FROM INSERT_sql_statementDECLARE cursor_id [WITH HOLD] FOR prepared_idOPEN cursor_idPUT cursor_id FROM variable_listFLUSH cursor_idCLOSE cursor_idFREE cursor_idFREE prepared_i
eg:MAINDEFINE i INTEGERDEFINE rec RECORDkey INTEGER,name CHAR(30)END RECORDDARABASE stockPREPARE is FROM "INSERT INTO item VALUES (?,?)"DECLARE ic CURSOR FOR isBEGIN WORKOPEN icFOR i=1 TO 100LET rec.key = iLET rec.name = "Index:" ,iPUT ic FROM res.*IF i MOD 50 = 0 THENFLUSH icEND IFEND FOR   CLOSE icCOMMIT WORKFREE icFREE isEND MAIN

阵列(ARRAY)

阵列就是数组,与数组不同的是,阵列从下标为1开始,并可以定义动态阵列。

固定阵列

语法:ARRAY [ intconst [,intconst [,intconst] ] ] OF datatype

动态阵列

语法:DYNAMIC ARRAY [ WITH DIMENSION rank ] OF datatype

阵列可使用的方法

阵列相关练习

# 练习一:定义固定阵列和动态阵列MAINDEFINE a1 ARRAY[10] OF INTEGER # 长度为10,类型为INTEGER的固定阵列DEFINE a2 DYNAMIC ARRAY OF INTEGER # 定义类型为INTEGER的动态阵列DEFINE i INTEGERLET i = 12LET a1[50] = 123456LET a2[5000] = 123456LET a2[500+i] = 123456END MAIN
# 练习二:getLength()方法MAINDEFINE a1 ARRAY[10] OF INTEGERDEFINE a2 DYNAMIC ARRAY OF INTEGERDISPALY a1.getLength()DISPLAY a2.getLength()END MAIN
# 练习三:clear()方法MAINDEFINE a ARRAY[20] OF INTEGERDISPLAY a.getLength()CALL a.clear()DISPLAY  a.getLength()END MAIN
# 练习四:appendElement()方法MAINDEFINE a DYNAMIC ARRAY OF INTEGERLET a[10] = 10CALL a.appendElementLET a[a.getLength()] = a.getLength()DISPLAY a.getLength()DISPLAY a[10]DISPLAY a[11]END MAIN
# 练习五:insertElement()方法MAINDEFINE a DYNAMIC ARRAY OF INTEGERLET a[10] = 11CALL a.insertElement(10)LET a[10] = 10DISPLAY a.getLength()DISPLAY a[10]DISPLAY a[11]END MAIN
# 练习六:deleteElement()方法MAINDEFINE a DYNAMIC ARRAY OF INTEGERLET a[10] = 9CALL a.deleteElement()DISPLAY a.getLength()DISPLAY a[9]END MAIN
# 练习七:二、三维阵列MAINDEFINE a2 DYNAMIC ARRAY 2 OF INTEGERDEFINE a3 DYNAMIC ARRAY 3 OF INTEGERLET a2[50][100] = 123456LET a2[51][1000] = 123456DISPLAY a2.getLength()    # 51DISPLAY a2[50].getLength() # 100DISPLAY a2[51].getLength() # 1000LET a3[50,100,100] = 12456LET a3[51,101,1000] = 12456DISPLAY a3.getLength() # 51DISPLAY a3[50].getLength() # 100DISPLAY a3[51].getLength() # 101DISPLAY a3[50,100].getLength() # 100DISPLAY a3[51,101].getLength() # 1000CALL a3[50].insertElement(10) # 添加空白数据到50,10CALL a3[50,10].insertElement(1) # 添加空白数据到50,10,1END MAIN

DISPLAY ARRAY

将阵列通过TABLE或TREE等元件显示

控制属性

事件触发后执行的控制段

DISPLAY ARRAY eg1(ARRAY显示到TABLE):

DATABASE ds
MAIN
DEFINE cnt INTEGER
DEFINE arr DYNAMIC ARRAY OF RECORD
gen01 CHAR(8),
gen02 CHAR(8),
gen03 CHAR(6)
END RECORD
OPEN WINDOW f1_w WITH FORM "custlist"
DECLARE c1 CURSOR FOR SELECT gen01,gen02,gen03 FROM gen_file
LET cnt = 1
FOREACH c1 INTO arr[cnt].*
LET cnt = cnt + 1
END FOREACH
CALL arr.deleteElement(cnt)
LET cnt = cnt – 1 #此處也可使用 LET cnt = arr.getLength( ) 取得實際筆數
DISPLAY ARRAY arr TO srec.* ATTRIBUTES(COUNT=cnt) #定義於畫面檔結構內
ON ACTION print
DISPLAY "Print a report"
END DISPLAY
END MAIN

DISPLAY ARRAY eg2(ARRAY显示到TREE):

DEFINE tree DYNAMIC ARRAY OF RECORD
name STRING, #名字〆有顯示的欄位
pid STRING, #父節點資料〆畫面使用幽靈欄位﹝Phantom﹞
id STRING, #本節點資料〆畫面使用幽靈欄位﹝Phantom﹞
hasChildren BOOLEAN, #是否有下層節點資料〆畫面使用幽靈欄位﹝Phantom﹞
description STRING #說明〆有顯示的欄位
END RECORD
DATABASE ds
MAIN
DEFINE cnt INTEGER
DEFINE arr DYNAMIC ARRAY OF RECORD
gen01 CHAR(8),
gen02 CHAR(8),
gen03 CHAR(6)
END RECORD
OPEN WINDOW f1_w WITH FORM "custlist"
DECLARE c1 CURSOR FOR SELECT gen01,gen02,gen03 FROM gen_file
LET cnt = 1
FOREACH c1 INTO arr[cnt].*
LET cnt = cnt + 1
END FOREACH
CALL arr.deleteElement(cnt)
LET cnt = cnt – 1 #此處也可使用 LET cnt = arr.getLength( ) 取得實際筆數
DISPLAY ARRAY arr TO srec.* ATTRIBUTES(COUNT=cnt) #定義於畫面檔結構內
ON ACTION print
DISPLAY "Print a report"
END DISPLAY
END MAIN
ERP T100
Genero 技術手冊 9-6MAIN
DEFINE id INTEGER #節點值
OPEN WINDOW f1_w WITH FORM "custlist"CALL expand(0)
DISPLAY ARRAY tree TO sr_tree.* ATTRIBUTE(UNBUFFERED)
ON EXPAND(id) #展開子節點
CALL expand(id)
ON COLLAPSE(id) #收合子節點
CALL collapse(id)
END DISPLAY
END MAINFUNCTION collapse(p) #收合
DEFINE p INT
DEFINE id STRING
LET id = tree[p].id
WHILE p < tree.getLength()
IF tree[p + 1].pid != id THEN EXIT WHILE END IF
CALL collapse(p + 1)
CALL tree.deleteElement(p + 1) #此節點下的資料,全部用 deleteElement 砍掉
END WHILE
END FUNCTIONFUNCTION expand(p) #展開
DEFINE name, id, pid STRING
DEFINE p, i INT
IF p = 0 THEN #只是給名字,若為根節點命名為 Root,子節點則為 Node1.1
LET pid = 0
LET name = "Root"
ELSE
LET pid = tree[p].id
LET name = "Node"
END IF
FOR i = 1 TO 4 #如果是從資料庫抓取展開資料,此處是 FOREACH 迴圈即可
LET p = p + 1
CALL tree.insertElement(p) #插入子節點
LET id = pid || "." || I #生成子欄位節點值
LET tree[p].id = id
LET tree[p].pid = pid #抓取父節點值
LET tree[p].name = name || " " || i
IF i MOD 2 THEN
LET tree[p].hasChildren = TRUE
ELSE
LET tree[p].hasChildren = FALSE
END IF
LET tree[p].description = "This is node " || tree[p].name #抓取說明值
END FOR
END FUNCTION

CLEAR SCREEN ARRAY

清除指定页面的阵列数据
语法:CLEAR SCREEN ARRAY screen-array.*
eg:#利用 CLEAR 指令逐筆刪除FOR i=1 TO <screen-array-length>CLEAR screen-array[i].*END FOR#利用 CLEAR SCREEN ARRAY 整批移除CLEAR SCREEN ARRAY screen-array.*

对话框(DIALOG)

将CONSTRUCT与INPUT指令封装起来,方便使用。因为单独使用CONSTRUCT和INPUT时,如果想切换不同的指令,必须结束前一项功能,才能进入另外
一项,比较麻烦。

DIALOG封装的指令

INPUT、DISPLAY ARRAY、INPUT ARRAY、CONSTRUCT、SUBDIALOG

语法

DIALOG [ ATTRIBUTE ( { display-attribute | control-attribute } [,...] ) ]BEFORE DIALOGAFTER DIALOGON IDLE idle-secondsON ACTION action-name
END DIALOGps:1. DIALOG不支持INT_FLAG,如果需要中断程序需要配合ON ACTION,在ACTION中使用EXIT DIALOG或ACCEPT DIALOG指令2. 如果在DIALOG只打算使用一个封装的指令,请不要使用DIALOG
eg:SCHEMA stores DEFINE p_customer RECORD LIKE customer.*DEFINE p_orders DYNAMIC ARRAY OF RECORD LIKE order.*FUNCTION customer_dialog()DIALOG ATTRIBUTES(UNBUFFERED, FIELD ORDER FORM)INPUT BY NAME p_customer.* # sub-DIALOGAFTER FIELD cust_nameCALL setup_dialog(DIALOG)END INPUTDISPLAY ARRAY p_orders TO s_orders.* # sub-DIALOGBEFORE ROWCALL setup_dialog(DIALOG)END DISPLAYON ACTION close # Action for DIALOGEXIT DIALOGEND DIALOGEND FUNCTION

ui.Dialog方法





总结

T100学习笔记 - Genero FGL相关推荐

  1. 【实习之T100开发】Genero FGL (TIPTOP4GL) 学习笔记(1)

    Genero FGL 学习 Genero FGL 简介 Genero FGL 开发(编译.连接.执行) 第一个程序 Hello World 变量与运算符 变量定义(DEFINE) 预定义变量 变量集合 ...

  2. 【实习之T100开发】Genero FGL (TIPTOP4GL) 学习笔记(2)

    Genero FGL学习 CURSOR CONSTRUCT:获取用户输入组成[WHERE条件] PREPARE:将[SQL字符串]转成[可执行SQL] FREE:释放 PREPARE 的记录 数据的查 ...

  3. 【实习】T100开发学习笔记

    T100开发学习笔记 笔记目录 一些小技巧 实用的通用快捷键 所有全局变量(top_global.inc文件) 笔记目录 Linux 学习笔记 T100 基础架构.命名原则 Genero FGL (T ...

  4. 【实习之T100开发】Linux 学习笔记

    Linux学习 ERP系统架构 Linux 基本操作 Linux 用户管理 Linux 环境变量 Linux 显示帮助命令 Linux 文件系统 操作目录相关指令 文件类型及权限说明 文件操作 服务器 ...

  5. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  6. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  7. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  8. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  9. 2020年Yann Lecun深度学习笔记(上)

    2020年Yann Lecun深度学习笔记(上)

最新文章

  1. 零代码 OR 低代码
  2. Yabbly:让经验缔结因果
  3. C#CodeSmith代码批量生成模板制作经验分享
  4. 日光能和电池两用计算机,计算机类专业竞赛模拟试题(doc 7页)全面优秀版优秀版...
  5. BZOJ2301: [HAOI2011]Problem b(莫比乌斯反演)
  6. 开源开放 | 计算机科学示意图问答数据集CSDQA(CCKS2021)
  7. 回车,根据编码获取相应记录,然后再将这录绑定到AutoList
  8. 微信开始收费,一年130元起!?
  9. SLAM_信息矩阵协方差矩阵
  10. 利用google closure管理javascript模块依赖
  11. LINUX编译autoconf
  12. vue脚手架学习笔记
  13. 《on Java 中文版》读后感(《JAVA编程思想》的原作者)(JAVA 小虚竹)
  14. NOIP2016普及组复赛 解题分析
  15. httprunner 2.x学习4-测试用例分层
  16. 汉诺塔递归算法python详细解析图_汉诺塔递归算法的图解(自我总结)
  17. 在qt中出现During startup program exited with code 0xc0000135错误原因
  18. 漫谈程序员(十三)健康程序猿系列之男人晚睡的7大危害
  19. 基于HL7-V3医疗系统信息交换标准SOAP开发
  20. linux服务器下进入BIOS,一种8路服务器Linux操作系统下刷新BIOS的方法与流程

热门文章

  1. 8大预测分析工具比较
  2. 惠州电子计算机职业学校,惠州市十大中专学校排名
  3. bind9 dlz mysql_Bind9和MySQL DLZ缓冲区错误
  4. python eel 多线程_Python的一个轻量级桌面GUI开发第三方库:Eel
  5. DLM learning materials
  6. 如果你在做安利或者认识做安利的人
  7. 个人永久性免费-Excel催化剂功能第85波-灵活便捷的批量发送短信功能(使用腾讯云接口)...
  8. 在线分析网站日志软件-免费分析网站蜘蛛的软件
  9. PHPWord替换word模板内容时,存在表格,且不确定表格行数的处理方式
  10. mysql_affect_array_Mysql代理类 支持Master/Slave 读写分离