第一章 关系型数据模型
1-1 前言 传统上,企业公司的数据处理,大都是按照部门或应用加以分类。因此,早期企业公司的计算机大多是为了处理各个部门或者应用系统的大量资料而装置的;例如一家汽车制迼公司,可能有产品制造部门、会计部门;而一家餐馆,可以有编制顾客帐单之应用系统、维护应收帐款之档案系统等。而每一个部门或每一种应用系统原则上都有它自己的主要档案,而各个部门或应用系统都有自己所需的资料,和更新档案及提供信息所需的程序。利用这种数据处理方式来存取资料,最大的好处是程序的设计方式相当单纯,因为每个档案系统均针对该部门或应用系统的特殊处理要求来设计,因此所设计出来的系统较容易满足各部门或应用系统之要求。但是相随衍生的问题却不少。 应用系统 一 应用程序一 ←→ 档案系统一 (或部门一) 应用系统 二 应用程序二 ←→ 档案系统二 (或部门二) 应用系统 N 应用程序N ←→ 档案系统N (或部门N) 1-2 传统的数据处理
一、资料重复 相同的数据域位值会重复出现在不同的档案系统上。例如:在一家公司里,销售员的地址资料、学历资料年龄资料也可能会重复地出现在人事管理部门、会计部门、产品销售部门;须要在这么多的档案中输入、保存及维护这些相同的资料,代价何其昂贵啊!举例来说吧!当某一位销售员的地址数据有所更动时,就必须到所储存地址资料的档案系统中,去更正这些旧有的地址数据,否则就会造成数据的不一致。
二、资料的不完整 不同的应用系统间之资料往往关系十分密切。例如:陈先生向银行办理个人小额货款买了一部卡拉OK,然而因未履约,故其卡拉OK须被取回,并降低了他的个人小额贷款的信用等级。但陈先生在银行里,也曾办过房屋贷款,假使房屋贷款所对应的信用等级未随之同时更新的话,那就产生混乱了。然而要维持资料的完整性,就须执行好几个程序来更新资料,此将花费很高的费用。
三、资料的不安全 由于企业公司各部门各自为政,公司的资料分散在不同的档案系统上,对于敏感性和机密性较高的资料,无法做有效的集中管理;往往会因某些部门负摃人的管理不善,而让商业间谍有机可乘,从中盗取机密资料。
四、应用程序的不稳定 在程序上,我们往往利用format或者Picture来定义资料之精确格式。例如:有一个学校在该校的学生姓名存在各个不同的档案中,居然用很多种不同的资料格式。因此,一旦有姓名格式发生变化,如增长或减短,或删除时,相对应的程序也要跟着修改,同时数据文件库也要随之改变,甚至连带地撷取数据的逻辑也要跟着翻新了。因之,应用程序的稳定性不佳。而改程序往往是最浪费时间和金钱的。 由于不同应用系统间的资料息息相关,而当这种关系愈来愈复杂后,传统的数据处理技术就再也难以胜任愉快了。于是有新的数据处理技术─数据库系统之提倡。数据库系统的观念主要强调资料应该是集中式的与整合式的,资料的异动在系统中仅需一次即可完成。
1-3 数据库系统的优点
使用数据库系统的优点,大致可归纳如下: (一).避免资料的大量重复─相同的资料在数据库内只需出现一次即可,但在非不得已时,亦可重复出现。如此可使重复性资料减至最少。 (二).资料独立─数据库之结构与内含资料发生变动时,不影响使用者之 程序,亦即使用者程序无须随之修改。 (三).避免资料不致的现象─数据库由专人统一管理维护,资料有所异动 ,亦一次同时更新,因此不会发生同样的数据项而资料值却不相同的现象。 (四).维持资料的完整性或整体性─各部门资料均集中在一起,因此可随时提供经营管理者所需的各种整体性信息。 (五).简化程序撰写工作─应用程序不需描述数据库之结构与资料记录间的相互关系,同时欲存取数据库资料,亦有一定之方法与格式,因此程序撰写工作可大为简化,程序设计员之生产力将大为提高。 (六).保护资料的安全─由于数据库管理系统对其内部资料有完善的保护功能,故资料不易被偷取或破坏。 (七).资料共通性─数据库可包容各部门之资料,因之数据库愈大资料的价值就愈高,它不仅可供更多使用者使用,且可提供更详细与完整的资料。 1-4 关连式数据模型 关连式数据模型是由E.F. Codd在1970年所提出。它将每一个档案用一此表格,又叫关连,来表示。而表格上的每一字段称做一个领域,它代表一笔记录的最基本资料项。例如职称的领域代表公司里所有可能的职称。年龄的领域代表公司里所有员工的可能年龄。例如下面的关连表示一个EMPLOYEE记录档案。其中领域EMPLOYEE NAME = {C.C CHANG,R.H. LEE,W.H. TSAI,M.Y. LEE, L.H. HWANG,....},领域EMPLOYEE NUMBER = {1041,2172,1437,4012,3128,....}等。 表1 EMPLOYEE 关连 ┌───────┬────────┬──┬──┬─────┬───┐ │EMPLOYEE NAME │EMPLOYEE NUMBER │SEX │AGE │ TITLE │SALARY│ ├───────┼────────┼──┼──┼─────┼───┤ │C.C. CHANG │ 1041 │ M │ 37 │MANAGER │ 79000│ │R.H. LEE │ 2172 │ F │ 28 │SECRETARY │ 28000│ │W.H. TSAI │ 1437 │ M │ 30 │MANAGER │ 60000│ │M.Y. LEE │ 4012 │ F │ 35 │ASSISTANT │ 23000│ │L.H. HWANG │ 3128 │ F │ 35 │DIRECTOR │ 31000│ │D.J. BUEHRER │ 4412 │ M │ 40 │MANAGER │ 62000│ └───────┴────────┴──┴──┴─────┴───┘ 而在关连中的每一列分别代表一笔记录,又叫一个元素组。至于DEPARTMENT关连可以用表2来表示。
表2 DEPARTMENT 关连 ┌────────┬────────┬──────┬──────┐ │DEPARTMENT NAME │DEPARTMENT CODE │ MANAGER │PHONE NUMBER│ ├────────┼────────┼──────┼──────┤ │COMPUTER │ 117 │C.C. CHANG │ 2263420 │ │ACCOUNTING │ 120 │W.H. TSAI │ 2547326 │ │ENGINERRING │ 137 │D.J. BUEHRER│ 2263410 │ └────────┴────────┴──────┴──────┘ 由于关连结构中的各个关连无主从关系,亦无键相连系,故要表示EMPLOYEE与DEPARTMENT间的关系,则需仰赖另一关连的穿针引线,此关连包含EMPLOYEE关连和DEPARTMENT关连之主键属性。
表3 DEPT-EMP 关连 ┌─────────┬────────┐ │DEPARTMENT NUMBER│EMPLOYEE NUMBER │ ├─────────┼────────┤ │ 117 │ 1041 │ │ 117 │ 2172 │ │ 117 │ 3128 │ │ 120 │ 1437 │ │ 120 │ 4012 │ │ 137 │ 4012 │ └─────────┴────────┘
1-5 关连式数据库系统之应用 1-5-1 键型态 在每一个关连中,如果我们仔细检查每一笔元素组,均可以发现一个特性,那就是某一个属性,或某一组(多于一个)属性之组合,可以唯一用来代表该笔元素组,因此该属性或该组属性就可以称做该关连的主键(Primary Key)。 例如,在下面的关连S中,SNO可以当作主键,而SNAME也可以被用来当作主键,然而在一个关连中我们最多只选用一个主键就够了,譬如选SNO当作主键斯足矣。值得一提的是,不一定每一个关连均要宣告一个主键。而在关关连中 够资格当主键的单一属性或属性组均被称为候选键(CandidateKey), ┌─────────────────┐ │ SNO SNAME STATUS SCITY │ ├─────────────────┤ │S001 SMITH 20 LONDON │ │S002 JONES 10 PARIS │ │S003 BLAQE 30 PARIS │ │S004 CLARK 20 LONDON │ │S005 ADAMS 30 ATHENS │ └─────────────────┘
若该键没有被选上担任主键,则就称之为替换键(Alternate Key),如SNAME没有被选上担任主键,则它称之为替换键。
在关连SP中,属性SP和属性组(SNO PNO)均为候选键,而我们若选上属性SP当做主键,则(SNO PNO)就称之为替换键。 ┌───────────────┐ │ SP SNO PNO QTY │ ├───────────────┤ │ SP01 S001 P001 120.00 │ │ SP02 S001 P002 200.00 │ │ SP03 S001 P003 100.00 │ │ SP04 S002 P004 300.00 │ │ SP05 S002 P005 230.00 │ │ SP06 S003 P001 150.00 │ │ SP07 S003 P003 400.00 │ └───────────────┘ 然而,在关连的所有属性中,有一些属性常常会出现在查询条件中,这一烦的属性可以被事先宣告为次键(Secondary Key)。例如:一个SQL的查询有可能是这样宣告的:SELECT PNAME FROM P WHERE COLOR = 'RED' OR WEIGHT < 16.00,在查询条件子句中出现了属性COLOR和属性WEIGHT。假使该两项属性事先曾经宣告为次键的话,则系统会针对该两项属性,分别为它们建立索引档案,以加速查询结果的回复速度。 在关连中除了主键之外,还带有一个或多个外来键(Foreign Key)。身为外来键的属性一定要对应到别的关连的主键上;换言之,假如我们说甲关连的某一个属性主键型态为外来键,那么该键值必须与某一个关连的某一笔元素组之主 键值吻合。举个例来说吧!例如在关连SP中的每一个SNO之值均对应到关连S之某一笔元素组之主键值SNO,所以在关连SP中,SNO称之为外来键,特别除带一提的是,外来键可以看成〞指到〞某一个关连之主键之〞假想〞指针,而且外来键与所对应之主键名称可以取不同的名字。
第二章 关联式资料正规化 在前面各节的讨论中,我们一再地用一个数据库─关连S、关连P和关连SP作为说明的范例;然而,是否曾经想过当初这三个关连是怎么决定出来的?为什么不将STATUS摆在关连SP中?若是将STATUS放在关连SP会有什么不好的影响? 首先来看看关连SP中含有SCITY的样子。 SP SNO PON QTY SCITY ────────────────────────── SP01 S001 P001 120.00 LONDON SP02 S001 P002 200.00 LONDON SP03 S001 P003 100.00 LONDON SP04 S002 P004 300.00 PARIS SP05 S002 P005 230.00 PARIS SP06 S003 P001 150.00 TOKYO SP07 S003 P003 400.00 TOKYO
很直觉地,我们发现SCITY和厂商较有关,而与出货资料较不相关。在上表中,我们发现SCITY出现了太多的累赘(Redundant),换言之,每一个厂商,其SCITY出现的次数与出货值之个数一样多,不只浪费了资料的储存空间,同时,亦增加了资料更新的复杂度。因此对于关连数据库之设计,如何勾划出一个数据库中包含的所有最适当的关连之轮廓,是相当重要的。在关连数据库中也就有了所谓的「正规化」(Normalization)之倡议。
假设有一群供货商,他们分别供应多种蔬果给台南市多家超级市场;每一个供货商有一个代码、名字及年龄,而每一家超级市场均有一位负责人(经理)、多位助手及多支联络电话。并且每一家超级市场座落于台南市的一个区,该区有一位区长。
┌──┬───┬──┬──┬───┬───┬───┬───┬────┬────┬──┐ │SNO │SNAME │AGE │VNO │ SMNO │ AST │ MGR │ SEC │SEC-DIR │PHONE │QTY │ ├──┼───┼──┼──┼───┼───┼───┼───┼────┼────┼──┤ │ │ │ │V001│ SM002│ ALAN │MR.X │EAST │ CHEN │3211319 │ 40 │ │S001│CHANG │ 38 │V003│ SM001│ MARY │MISS T│EAST │ CHEN │2514172 │ 12 │ │ │ │ │V003│ SM001│ MARY │MISS T│EAST │ CHEN │2514173 │ 12 │ │ │ │ │V004│ SM003│ LISA │MR.Y │WEST │ PAN │3259122 │ 80 │ ├──┼───┼──┼──┼───┼───┼───┼───┼────┼────┼──┤ │ │ │ │V002│ SM003│ LISA │MR.Y │WEST │ PAN │3259122 │ 20 │ │S002│TSAI │ 34 │V003│ SM004│ JOHN │MR.E │SOUTH │ LIU │4013212 │ 30 │ │ │ │ │V003│ SM004│ JANE │MR.E │SOUTH │ LIU │4013212 │ 30 │ ├──┼───┼──┼──┼───┼───┼───┼───┼────┼────┼──┤ │ │ │ │V001│ SM001│ MARY │MISS T│EAST │ CHEN │2514172 │ 24 │ │S002│HWANG │ 36 │V001│ SM001│ MARY │MISS T│EAST │ CHEN │2514173 │ 24 │ │ │ │ │V001│ SM002│ ALAN │MR.X │EAST │ CHEN │3211319 │ 46 │ ├──┼───┼──┼──┼───┼───┼───┼───┼────┼────┼──┤ │S004│LEE │ 29 │V003│ SM005│SMITH │MISS B│NORTH │ SHEN │6017121 │ 85 │ └──┴───┴──┴──┴───┴───┴───┴───┴────┴────┴──┘ 我们看到上面的关连总共含有11个属性:SNO(供货商代号),SNAME(供货商名字),AGE(供货商年龄),VNO(蔬果代号),SMNO(超市代号),AST(超市助理),MGR(超市经理),SEC(市区名称),SEC-DIR(区长名字),PHONE(超市电话),QTY(蔬果供应量)。而每一个属性所相关之领域均只包含基元值(Atomic value),亦即无法再细分的属性值。
我们称上面的关连为第一正规形式(First Normal form),简称1NF;换句话说,1NF可被正式定义为:
定义一:一个关连R为1NF,若且唯若所有的属性所相关之领域均只包含基元值。 因此,可以说任何关连均为1NF;然而它却不一定合乎我们的理想。考虑前面的关连,假使S004结束营业,他的资料须被从关连中删除,则连同SM005的资料也一并地被杀掉了,此称为异常地删除(Deletion Anomalies)。再如:假设有一家新的超级市场开业,然而因为它未找到合适的供货商,是故目前尚无法知道SNO等资料,这时,若硬要将此超级市场的信息插入关连,则会因有些键值空白,而产生毛病,此称之为异常地插入(Insertion Anomalies)。接着,假设SM001的助理 MARY换了人,现在变成了LINDA,若只更新一个MARY,而忘了或来不及更新另外的MARY,则以后的麻烦可就大了,如此称为异常地更新(Update Anomalies)。为了解决上述的这些问题,所以有「正规化」的产生。
在解释下列的各种正规形式之前,让我们首先定义一些术语。我们将上述的关连之十一个属性名称绘成如下的关系图来加以说明。
SNAME
↗
SNO
↘
AGE
AST
↗ MGR
↗
SMNO ─→SEG
\ ↘ ↓
↘ SEC-DIR
PHONE
SNO, VNO, SMNO ───→ QTY
当我们知道了供货商代号时,自然地,就可以找出他的名字,但若是知道了供货商的名字,则不一定可以找到一个明确的供货商代号,因此我们说SNAME的功能相关(Functional Dependency)SNO,而且AGE亦功能相关于SNO;反之不然。而供应量功能相关于供货商代号、蔬果代号、超市代号之组合,但却不功能相关于上面三者之集合的任一个子集合;所以我们说QTY完全地功能相关于(Full Functional Dependency)SNO、VNO和SMNO。值得特别注意的是,功能相关有递移(Transitive)的性质存在,亦即B=f(A),C = g(B)则C =h(A)。 由于每一家超级市场有不只一位助理人员且不只一支联络电话,因此,我们称AST为多值相关于(Multivalued Dependency)SMNO,且PHONE亦为多值相关于SMNO。是故,我们可以将上面的关系图再细分如下:
SNAME
↗
SNO
↘
AGE
MGR
↗
SMNO →SEC
↘ ↓
SEC-DIR
SNO, VNO, SMNO ────→ QTY
AST
↗
↗
SMNO
↘
↘
PHONE
而勾划出另一个正规形式之蓝图。
┌──┬───┬──┐ ┌───┬───┬───┬────┐ │SNO │SNAME │AGE │ │ SMNO │ MGR │ SEC │ SEC-DIR│ ├──┼───┼──┤ ├───┼───┼───┼────┤ │S001│CHANG │ 38 │ │ SM001│MISS T│ EAST │ CHEN │ │S002│TSAI │ 34 │ │ SM002│MR.X │ EAST │ CHEN │ │S003│HWANG │ 36 │ │ SM003│MR.Y │ WEST │ PAN │ │S004│LEE │ 29 │ │ SM004│MR.E │ SOUTH│ LIU │ └──┴───┴──┘ │ SM005│MISS B│ NORTH│ CHEN │ └───┴───┴───┴────┘
┌──┬──┬───┬──┐ ┌───┬───┬────┐ │SNO │VNO │SMNO │QTY │ │SMNO │ AST │ PHONE │ ├──┼──┼───┼──┤ ├───┼───┼────┤ │S001│V001│SM002 │ 40 │ │SM001 │MARY │2514172 │ │S001│V003│SM001 │ 12 │ │SM001 │MARY │2514173 │ │S001│V004│SM003 │ 80 │ │SM002 │ALAN │3211319 │ │S002│V002│SM003 │ 20 │ │SM003 │LISA │3259122 │ │S002│V003│SM004 │ 30 │ │SM004 │JOHN │4013212 │ │S003│V001│SM001 │ 24 │ │SM004 │JANE │4013212 │ │S003│V002│SM002 │ 46 │ │SM005 │SMITH │6017121 │ │S004│V003│SM003 │ 85 │ └───┴───┴────┘ └──┴──┴───┴──┘ 定义二:若且唯若关连R为1NF且每个非键之属性完全相关于主键,则关连R为2NF(Second Normal form)。
第三章 INformIX-SQL 3-1 CREATE DATABASE <语法格式> CREATE DATABASE database_name [WITH LOG IN "pathname"] §例: create database nckucom create database payroll with log in "/user1/nckucc/nckucc.log" database_name 不可超过8个字符 3-2 CREATE TABLE <语法格式> CREATE [TEMP] TABLE table_name (column_name datatype [NOT NULL][UNIQUE]) §例: create table tab1 ( c1 integer not null unique, c2 integer, c3 integer not null, c4 integer not null unique(c3,c4) ) CREATE VIEW view_name [(column_list)] AS SELECT-statement. DROP TABLE table_name 3-3 CREATE INDEX <语法格式> CREATE [UNIQUE][CLUSTER] INDEX index_name ON table_name(column_name[ASC|DESC],...) §例: create unique index i_ordnum1 on orders(order_num) create cluster index i_ordnum2 on orders(order_num DESC) 3-4 LOAD 与 UNLOAD <语法格式一> LOAD FROM "/pathname/loadfile" [DELIMITER "char"] INSERT INTO table_name §例: load from "ssaltab.d" delimiter ";" insert into ssaltab <语法格式二> UNLOAD TO "/pathname/unloadfile" [DELIMITER "char"] SELECT clause §例: unload to "ssaltab.d" delimiter ";" select * from ssaltab 3-5 LOCK TABLE <语法格式> LOCK TABLE table_name IN {SHARE|EXCLUSIVE} MODE §例: lock table orders in exclusive mode 3-6 RENAME <语法格式一> RENAME COLUMN table.oldcolumn TO newcolumn §例: rename column customer.customer_num to c_num <语法格式二> RENAME TABLE oldname TO newname §例: create table newtable ( item_num smallint, order_num integer, quantity smallint, stock_num smallint, manu_code char(3), total_price money(8) ) insert into newtable select item_num,order_num,quantity,stock_num,manu_code,total_price from items drop table items rename table newtable to items rename column customer.customer_num to c_num
3-7 SELECT Statement <语法格式> SELECT clause FROM clause [WHERE clause] [GROUP BY clause] [HAVING clause] [ORDER BY clause] [UNION SELECT clause] 3-7-1 SELECT <语法格式> SELECT[ALL|DISTINCT|UNIQUE] select_list §例: select customer_num, lname, city from custom select count(*) from order where customer_num = 101 select avg(total_price) from items where order_num = 1008 select a+b abtotal, c*d cdprod from items where order_num = 1008
3-7-2 FROM <语法格式> FROM[OUTER]table_name[table alias][,...] §例: select fname, lname, order_num from customer, orders where customer.customer_num = order.customer_num select fname, lname, order_num from customer, outer orders where customer.customer_num = order.customer_num 3-7-3 WHERE <语法格式> WHERE condition condition 是由一个或一个以上的寻找条件(search condition)配合逻辑操作数AND、OR、NOT 所组成。寻找条件如下列所示: .比较条件(comparision Condition): a.expr rel_op expr b.expr [NOT] BETWEEN expr AND expr c.expr [NOT] IN (value_list) d.column_name[NOT] LIKE "string" [ESCAPE "esc_char"] e.column_name[NOT] MATCHES "string" [ESCAPE "esc_char"] f.column_name IS [NOT] NULL 1.%,* 表示零或零个以上 2.ˍ,? 表示任何字符 3.\ 表示下一个字符,不是万用字符 a.expr rel_op {ALL|ANY|SOME}(SELECT_statemnet) b.expr [NOT] IN (SELECT_statemnet) c.[NOT] EXISTS (SELECT_statemnet)
§例: select customer_num, order_date from orders where paid_date is null select fname, lname, company from customer where address[1,6] = "宜昌市" select customer_num, company from customer where address MATCHES "宜昌市*" select order_num, company from orders o, customer c where o.order_date > "83/07/01" and o.customer_num = c.customer_num select stock_num, manu_code from stock where unit_price between 125.0 and 200.0 select distinct customer_num, stock_num, manu_code from orders, items where order_date between "83/07/01" and "83/07/07" and orders.order_num = items.order_num select fname, lname from customer where zipcode not between "443000" and "443003" select lname, fname, company from customer where city in ("宜昌市","三峡市") select fname, lname from customer where lname like "%son" select fname, lname from customer where lname like "Richard*" select stock_num, manu_code, unit_price from stock where description like"%ball%" select * from customer where company like "%z_% escape "z" select * from customer where company like "%z?% escape "z" select order_num, customer_num from orders where paid_date is null select order_num, total_price from items where total_price > 1000.0 and manu_code like "H%" select lname,customer_num from customer where zipcode between "300" and "899" and city not in ("宜昌市","三峡市") .连结条件(Join Condition):连结表字段的比较条件
§例: select order_num, lname, fname from customer, orders where customer.custom_num = orders.customer_num select distinct company, stock_num, manu_code from cysuomer c, orders o, items i where c.customer_num = o.customer_num and o.order_num = i.order_num select x.stock_num, x.manu_code, y.stock_num, y.manu_code from stock x, stock y where x.unit_price > 2.5 * y.unit_price select company, order_num from customer c, outer orders o where c.customer_num = o.customer_num .巢状式的条件(Condition wirh Subquery): §例: select order_num from items where stock_num = 9 and quantity = (select max(quantity from items where stock_num = 9) select distinct order_num from items where total_price > (select total_price from items where order_num = 1234) select distinct customer_num from orders where order_num not in (select order_num from items where stock_num = 1) select order_num, stock_num, manu_code, total_price from item x where total_price > (select 2 * min(total_price) from items where order_num = x.order_num) select distinct customer_num from orders where order_num in (select distinct order_num from items where quautity > 1) select * from healcashtab h where h.heal_tot <> (select sum(e.heal_fee) from healcashtab e where h.staff_num = e.staff_num) and p_idx = “1” select u.idno,e.eduwelf_ty,d.eduwelf_ty from eduwelftab u,outer eduwelftab e, outer eduwelftab d where u.idno = e.idno and u.idno = d.idno and e.eduwelf_ty = 1 and d.eduwelf_ty = 2 3-7-4 GROUP BY <语法格式> GROUP BY column_list column_list 最多允许8个 §例: select order_num, count(*), sum(total_price) from items group by order_num select order_num, count(*), sum(total_price) from items group by 1 select order_date, paid_date - order_date from items group by 2 3-7-5 HAVING <语法格式> HAVING condition §例: select order_num, avg(total_price) from items group by order_num having count(*) > 2 3-7-6 ORDER BY <语法格式> ORDER BY column_name [ASC|DESC][,...] §例: CORRECT: select order_date, ship_date from orders order by order_date CORRECT: select * from orders order by order_date INCORRECT: select order_date, ship_date from orders order by customer_num select customer_num, fname, lname, company from customer order by 3, 2 3-7-7 UNION <语法格式> SELECT statement UNION [ALL] SELECT statement [UNION [ALL] SELECT statement ...] §例: select distinct stock_num, manu_code from stock where unit_price < 100.0 union select stock_num, manu_code from items where quantity > 3 order by 1 3-8 Function in SQL Statement Aggregate Length Date Datetime Function Function Functions Functions ========= ============= =================== ========= COUNT(*) LENGTH(string) DATE(expr) CURRENT SUM(x) DAY(date_expr) AVG(x) MDY(date_expr) MAX(x) MONTH(date_expr) MIN(x) WEEKDAY(date_expr) YEAR(date_expr) §例: select max(distinct total_price) from items select avg(unit_price) from stock where description matches "baseball*" select * from orders where end_date > date ("2003/01/08") select order_num, day(order_date) from orders select customer_num, length(fname)+length(lname) from customer where length(company) > 10 let sys_date = MDY(MONTH(TODAY),DAY(TODAY),YEAR(TODAY)-1911) select order_num, month(order_date) from orders select order_num, weekday(order_date) from orders 0 表示星期日,1 表示星期一 ... select order_num, year(order_date) from orders select prog_title from tv_program where air_date > current year to day 3-9 VIEW table in SQL Statement CREATE VIEW psfbirthday (idno,psn_code,pos_code,psn_name,dept_code,dept_code_sort, birthday,birth_mm) AS SELECT psftab.idno,psftab.psn_code,psfcurrtab.pos_code, psftab.psn_name, psfcurrtab.dept_code, deptab.dept_code_sort, psftab.birthday, TRUNC(psftab.birthday/100)-TRUNC(psftab.birthday/10000)*100 FROM psftab,psfcurrtab WHERE psftab.psn_code = psfcurrtab.psn_code AND psfcurrtab.dept_code = deptab.dept_code AND psfcurrtab.data_indtr = "1" AND ((EXISTS (SELECT * FROM ssaltab WHERE ssaltab.staff_num = psftab.psn_code AND ssaltab.work_ty = "1") ) OR (EXISTS (SELECT * FROM memptab WHERE memptab.psn_code = psftab.psn_code AND memptab.ctrl_ty = "1") ) )
第四章 基本资料形态和运算式 4-1 字符 char(n) 字符的基本资料型态包括小写字母,大写字母,数字,标点符号以及像+、﹪、*之类的特殊符号。 <语法格式> char(n) char(n) n为使用者所定义的资料长度,其范围 1 <= n <= 32,767 §例: DEFINE answer CHAR(1) 4-2 小型整数 smallint
资料长度为 2 位,其范围 -32,767 至 +32,767
<语法格式> smallint
§例: DEFINE i SMALLINT
4-3 整数 integer
资料长度为4位,其范围 -2,147,483,647 至 +2,147,483,647
<语法格式> integer
§例: DEFINE i INTEGER
4-4 浮动点数 decimal[(m[,n])]
<语法格式> DECIMAL(precision[, scale])
此种资料最多的长度为32个数字。
1.precision为所有数字个数,但不包括小数点。
2.scale为小数点右边的数字个数。
3.资料长度为
bytes = ROUND(precision/2+1)
§例:DEFINE unit_price DECIMAL(6,2)
此定义 unit_price 4 位整数 2 位小数。
4-5 小型浮点数 smallfloat
小型浮点数相当于C语言中的 float 的资料型态,大约有7个有效数字资料长度为4位。
<语法格式> smallfloat
§例: DEFINE unit_price SMALLFLOAT
4-6 浮点数 float
小型浮点数相当于C语言中的 double 的资料型态,大约有14个有效数字。资料长度为8位。
<语法格式> float
§例: DEFINE unit_price FLOAT
4-7 序数 serial
序数资料型态为 informix-4gl 自动设定的连续整数. informix-4gl 在开始时,预设为1,使用者亦可任选一个大于0的数值做起始值,之后每次新增一笔资料则自动加1当作序号。
<语法格式> serial
§例: DEFINE employee_num serial
§例: DEFINE custom_num serial(1000)
员工编号启始值为 1,顾客编号启始值为 1000.
4-8 日期 date
<语法格式> month/day/year
1.其中/为分隔符,亦可使用(.)或连字符号(-)代替。
2.月和日为两位数,不足两位者可补 0 或不补 0 皆可。
3.年为4位数介于 0000 和 9999 之间,若只输入两位数,informix-4gl 会在此数值之前加上19。
4.系统所储存的资料长度为4位.
§例: DEFINE birth_date date
若要使用中华民国年份以符合国人习惯,而所使用系统为 unit 下的 Bournelshell,则可以在 .profile 档中设定下列的格式:
DBDATE=Y2MD/;export DBDATE
年份变成在最前面且只占2位数,若输入790820,则系统会显示79/08/20的格式
4-9 钱制 money[(m[,n])]
基本上钱制资料型态雷同于 decimal 资料型态,当一个值被定义成此型态后,informix-4gl 会在其值之前自动出现钱制符号($),并以小数点型态显示。
<语法格式> money(precision[scale])
1.precision为所有数字个数,但不包括小数点。
2.scale为小数点右边的数字个数。
3.若没有设定 scale,则 informix-4gl 预设小数2位,若没有设定 precision
则 informix-4gl 预设小数为 decimal(16,2)。
4.资料长度为
bytes = ROUND(precision/2+1)
§例: DEFINE unit_price money(7,3)
此定义 unit_price4位整数3位小数。 4-10 变量的定义(define):
<语法格式>
define variable-name [, ...] data-type
§例: DEFINE answer CHAR(1) DEFINE sys_program CHAR(6) DEFINE i,j,k SMALLINT DEFINE tot_cnt INTEGER DEFINE upddate DATE DEFINE yy DATETIME YEAR TO YEAR DEFINE mm DATETIME MONTH TO MONTH DEFINE fetch_dir, toward_last, toward_first, at_end SMALLINT
变量定义叙述(define)必须放在main、function、report和global等叙述的后面。
<语法格式>
define variable-name [, ...] record like table.*
§例:
DEFINE p_ssaltab RECORD LIKE ssaltab.* <语法格式> define variable-name [, ...] like table.column §例: DEFINE rank LIKE ssaltab.payrank <语法格式> define variable-name [, ...] like table.column §例: DEFINE old_insure_no LIKE ssaltab.insure_no <语法格式> define variable-name [, ...] record var-name [, ...] data-type end reocrd §例: DEFINE p_formonly RECORD char1 CHAR(8), char2 CHAR(10), char3 CHAR(2), char4 CHAR(4) END RECORD <语法格式> define variable-name array [...] of record var-name [, ...] data-type end reocrd §例: DEFINE s_menu ARRAY[4] OF RECORD menu_name CHAR(4), action CHAR(6) END RECORD
§例: DEFINE p_st ARRAY[20] OF RECORD family_name LIKE sfamilytab.family_name, family_idno LIKE sfamilytab.family_idno END RECORD 4-11 算术表达式 ┌──────────────────────────┐ │ 运算子 意 义 │ ├──────────────────────────┤ │ ** 指数运算 │ ├──────────────────────────┤ │ * 乘法运算 │ ├──────────────────────────┤ │ / 除法运算 │ ├──────────────────────────┤ │ mod 余数运算 │ ├──────────────────────────┤ │ + 加法运算 │ ├──────────────────────────┤ │ - 减数运算 │ └──────────────────────────┘
4-12 字符串表达式 ┌──────────────────────────┐ │ 运算子 意 义 │ ├──────────────────────────┤ │ , 连结运算 │ ├──────────────────────────┤ │ [m,n] 从m至n字符位置取出子字符串 │ ├──────────────────────────┤ │ USING 设定格式 │ ├──────────────────────────┤ │ CLIPPED 消除尾部空白 │ └──────────────────────────┘ 4-13 布尔表达式 在 informix-4gl 程序的叙述如 IF、CASE、WHILE、SELECT、UPDATE 和DELETE 均可使用布尔表达式来作运算。 ┌──────────────────────────┐ │ 值 意 义 │ ├──────────────────────────┤ │ TRUE 真, 定义成 1 │ ├──────────────────────────┤ │ FALSE 假, 定义成 0 │ ├──────────────────────────┤ │ UNKNOWN 未知情况 │ └──────────────────────────┘
一般布尔表达式所使用到的表达式子有下列三种: ┌──────────────────────────┐ │ 运算子 意 义 │ ├──────────────────────────┤ │ AND 且 │ ├──────────────────────────┤ │ OR 或 │ ├──────────────────────────┤ │ NOT 非 │ └──────────────────────────┘
AND │T F ? OR │T F ? NOT│ ──┼──── ──┼──── ──┼── T │T F ? T │T T T T │ F F │F F F F │T F ? F │ T ? │? ? ? ? │T ? ? ? │ ?
4-13 关系表达式 ┌─────────────────┐ │关系运算符号 │ ├─────────────────┤ │关系运算符号 : 小于 : < │ │ 大于 : > │ │ 小于或等于 : <= │ │ 大于或等于 : >= │ │ 不等于 : != 或 <>│ └─────────────────┘ 4-14 空值 (NULL value) 在算数表达式中,若有一个值为 null 时,则整个表达式的结果也将是 null 值。
第五章 控制流程与叙述
5-1 informix-4gl 的程序架构
<语法格式>
DATABASE database-name
GLOBAL
...
END GLOBALS
MAIN
...
END MAIN
FUNCTION function-name()
...
END FUNCTION
REPORT report-name()
...
END REPORT
5-2 批注叙述
1.行批注 { # text }
2.行批注 { -- text }
3.段批注 { text }
5-3 IF 叙述
<语法格式>
IF boolean-exp THEN
statement
...
ELSE
statement
...
END IF
§例:
IF p_count < 1 THEN
ERROR "小于1"
ELSE
LET p_count = p_count + 1
END IF
5-4 FOR 叙述
<语法格式>
FOR varibale = integer_exp TO integer_exp
STATEMENT
...
[CONTINUE FOR]
...
[EXIT FOR]
...
END FOR
§例:
let order_total = 0
for i = 1 to ARR_COUNT()
let order_tatal = order_total + p_item.total_price
end for
5-4 WHILE 叙述
<语法格式>
WHILE boolean-exp
STATEMENT
...
[CONTINUE WHILE]
STATEMENT
...
[EXIT WHILE]
END WHILE
§例:
while true
call check() returning answer
if answer matches [yY] then
continue while
else if x is null then
exit while
end if
end if
...
end while
FOR i = 1 TO 100
LET sw = 0
FOR j = 1 TO 100
IF A = 1 THEN
CONTINUE FOR
ELSE IF A = 2 THEN
EXIT FOR
ELSE IF A = 3 THEN
LET sw = 1
EXIT FOR
ELSE IF A = 4 THEN
LET sw = 2
EXIT FOR
END IF
END IF
END IF
END IF
END FOR
IF sw = 1 THEN
CONTINUE FOR
ELSE IF sw = 2 THEN
EXIT FOR
END IF
END IF
....
....
....
....
....
END FOR
....
....
....
....
5-5 CASE 叙述
<语法格式>
CASE [(exp)]
WHEN {exp|boolean}
statement
...
[exit case]
WHEN {exp|boolean}
statement
...
[exit case]
...
OTHERWISE
statement
...
[exit case]
END CASE
§例:
case choise
when 1 : call choice-1()
when 2 : call choice-2()
when 3 : call choice-3()
when 4 : call choice-4()
...
end case
§例:
case
when choice = 1 call choice_1()
when choice = 2 call choice_2()
when choice = 3 call choice_3()
when choice = 4 call choice_4()
...
end case
5-6 CONTINUE 叙述
提早返回循环开始处。
<语法格式>
CONTINUE {CASE|DISPLAY|FOR|FOREACH|INPUT|MENU|WHILE}
5-7 EXIT 叙述
提早跳出循环、程序、INPUT、DISPLAY之外。
<语法格式>
EXIT{CASE|DISPLAY|FOR|FOREACH|INPUT|MENU|WHILE}
5-8 GOTO 叙述
无条件跳至标记处(同一函数、报表、MAIN之中)执行命令。
<语法格式>
GOTO标记名称
§例:
if status != 0 then goto stop_run
end if
statement
...
label stop_run: statement
...
5-8 LABEL 叙述
标记GOTO跳到的地址。
<语法格式>
LABEL 标记名称
5-9 SLEEP 叙述
使程序暂停几秒。
<语法格式>
SLEEP 整数表达式
§例:
sleep 2
5-10 WHENEVER 叙述
当错误或警告发生时执行 ...
<语法格式>
WHENEVER {ERROR|WARNING}
{GOTO 标计|CALL 函数|CONTINUE|STOP}
§例:
whenever error continue
...
whenever error stop
...
5-11 FOREACH 叙述
相当于 WHILE 循环半和 FETCH 的组合。
<语法格式>
FOREACH 指针名称 [INTO 变量串行]
statement
...
[CONTINUE FOREACH]
...
[EXIT FOREACH]
END FOREACH
§例:
foreach psn_cursor INTO p_psn.*
...
if p_psn.type = "n" then
continue foreach
end if
...
if int_flag = true
exit foreach
end if
...
end foreach
5-12 CALL 叙述
<语法格式>
CALL 函数([参数串行]) [RETURNING 变量串行]
§例:
call sample_function(parm1,parm2) returning variable
call sample_function(parm)
call sample_function()
5-13 RETURN 叙述
立刻返回呼叫之程序,并可传回值。
<语法格式>
RETURN [表达式串行]
§例:
return x,y,z
return x+y
return 7
return true
return
5-14 DEFER 叙述
阻止使用者中断程序执行
<语法格式>
DEFER INTERRUPT
一旦宣告,无法改变。
5-15 RUN 叙述
执行操作系统下的可执行文件
<语法格式>
RUN 可执行档名称
§例:
run sample.4ge
5-16 PROMPT 叙述
PROMPT 叙述可以从使用者处,交谈式的接受所输入之资料
<语法格式>
PROMPT display_list FOR variable
§例:
define stuff_num char(7)
prompt "请输入员工编号" for stuff_num
5-17 DISPLAY 叙述
<语法格式>
DISPLAY display_list [USING|CLIPPED] AT ROW,COLUMN
§例:
display p_ssaltab.idno at 24,1
display p_emp_name CLIPPED at 24,20
display "" at 2,1
5-17 CLIPPED 叙述
若变量是 CHAR 的资料型态时,当设定一个值给变量时,如果所设定的资料长度比要设定的值还要大时,informix-4gl 会自动把空白值填入变量尾部多余的长度内,直到和它所定义的长度为止。所以,使用者若要将变量尾部多余的空白清除掉,则必须使用 CLIPPED 叙述。
<语法格式>
DISPLAY display_list CLIPPED
§例:
define emp_name char(10)
define title_name char(4)
let emp_name = "张三丰"
let title_name = "先生"
display emp_name clipped,title_name clipped
5-18 MESSAGE 叙述
用来显示讯息至屏幕的讯息行(default 第二行)
<语法格式>
MESSAGE display_list
§例:
let address="台南市"
message "请选择户籍所在地为",address
sleep 2
message ""
5-19 ERROR 叙述
用来显示错误讯息至屏幕的错误行(default 第 24 行)
<语法格式>
ERROR display_list
§例:
error "身份证号重复"
5-20 CLEAR 叙述
<语法格式一>
CLEAR SCREEN
此叙述用来清除整个屏幕,包刮讯息行、错误行。
<语法格式二>
CLEAR form
此叙述用来清除所有的屏幕字段资料值。
<语法格式三>
CLEAR VARIABLE_LIST
此叙述用来清除 field_list 所包含的一个或一个以上的屏幕字段资料值。
§例:
clear emp_name,idno,stuff_num ...
5-21 INITIALIZE 叙述
通常变量可以用lLET 设定,但若要设定为 NULL 时,必须使用 INITIALIZE。
§例:
INITIALIZE variable TO NULL
INITIALIZE record_name.* TO NULL | | |