精华内容
下载资源
问答
  • 数据库面试

    千次阅读 多人点赞 2019-02-13 09:03:42
    、数据库问答题 1. SQL语言包括哪些类型? 数据定义DDL:Create Table,Alter Table,Drop Table, Create/Drop Index等 数据操纵DML:Select ,insert,update,delete, 数据控制DCL:grant,revoke 2. 内联接,外联接...

    数据库常见问题

    1. SQL语言包括哪些类型?
    数据定义DDL:Create Table,Alter Table,Drop Table, Create/Drop Index等
    数据操纵DML:Select ,insert,update,delete,
    数据控制DCL:grant,revoke

    2. 内联接,外联接区别?
    内连接是保证两个表中所有的行都要满足连接条件,而外连接则不然。
    在外连接中,某些不满条件的列也会显示出来,也就是说,只限制其中一个表的行,而不限制另一个表的行。分左连接、右连接、全连接(mysql不支持)三种。

    3. 什么是存储过程?用什么来调用?
    答:存储过程是一组为了完成特定功能的SQL 语句集,经编译创建并保存在数据库中,一次编译后永久有效。通过Call语句指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
    由于存储过程是经过预编译处理的,因此如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。存储过程不允许执行return语句,但是可以通过out参数返回多个值,存储过程一般是作为一个独立的部分来执行,存储过程是一个预编译的SQL语句。

    4.触发器的作用?
    答:触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的。
    它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。触发器无法由用户直接调用,而是由于对表的【增/删/改】操作被动引发的。

    5. 索引的作用?和它的优点缺点是什么?
    答:索引就一种特殊的查询表,可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。
    缺点:它减慢了数据录入和修改的速度,同时索引也会占用一定的存储资源,因此我们在建索引的时候需要斟酌。

    6. 维护数据库的完整性和一致性,你喜欢用触发器还是自写业务逻辑?为什么?
    答:我是这样做的,尽可能使用约束,如主键,外键,非空字段等来约束(Check约束在mysql中可以使用但是对数据验证没有任何作用),这样做效率最高,也最方便。其次是使用触发器,这种方法可以保证,无论什么业务系统访问数据库都可以保证数据的完整新和一致性。触发器是针对每一行的;对增删改非常频繁的表上切记不要使用触发器,因为它会非常消耗资源。 最后考虑的是自写业务逻辑,但这样做麻烦,编程复杂,效率低下。

    7. 什么是事务?什么是锁?事务有哪些类型?

    1. 事务:就是被绑定在一起作为一个逻辑工作单元的SQL语句分组。如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。
    2. 锁:在所以的DBMS中,锁是实现事务的关键,锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。当然锁还分级别的。
    • 扁平化事务:在扁平事务中,所有的操作都在同一层次,这也是平时使用最多的事务,主要限制是不能提交或回滚事务的某一部分,要么都成功要么都回滚。
      带保存点的扁平事务:解决了扁平事务的弊端,它允许事务在执行过程中回滚到较早的状态而不是全部回滚,通过在事务中插入保存点,当操作失败后可以选择回滚到最近的保存点处。
      链事务:可看做第二种事务的变种,它在事务提交时,会将必要的上下文隐式传递给下一个事务,当事务失败时,可以回滚到最近的事务,不过链事务只能回滚到最近的保存点,而带保存点的扁平化事务是可以回滚到任意一个保存点。
      嵌套事务:由顶层事务和子事务构成,类似于树的结构,一般顶层事务负责逻辑处理,子事务负责具体的工作,子事务可以提交,但真正的提交要等到顶层事务的提交,如果顶层事务回滚,那么所有的子事务都将回滚。
      分布式事务:在分布式环境中的扁平化事务。
      常用的分布式事务解决方案:
      (1) XA规范,是保证强一致性的刚性事务,实现方式有两段式提交(2PC)和三段式提交(3PC),2PC需要一个事务协调者来保证事务的参与者都完成了第一阶段的准备工作,如果协调者收到了所有的参与者都准备好的消息,就会通知所有的事务执行第二阶段的提交,一般场景下两段式提交已经能很好的解决分布式事务了。然而两阶段在即使只有一个进程发生故障时,也会导致整个系统存在较长时间的阻塞。三段式提交通过增加pre-commit阶段来减少两段式提交提到的系统阻塞时间,三段式提交很少在实际中使用,简单了解就行了。
      (2) TCC:是满足最终一致性的柔性事务方案。TCC采用补偿机制,核心的思想是对每一个操作都要注册对应的确认和补偿操作,分为三个阶段,try阶段主要对业务系统进行检测及资源预留,confirm阶段对业务系统进行确认提交,cancel阶段是对业务执行错误,执行回滚释放预留的资源。
      (3) 消息一致性方案:基本思路是将本地操作和发送消息封装在一个事务中,保证本地的操作和消息发送要么都成功,要么都失败。下游应用订阅消息,收到消息后执行对应的操作。
      (4)GTS:阿里云的全局事务服务,对应的开源版本是Fescar,Fescar基于两段式提交进行改良,剥离了分布式事务方案对数据库在协议支持上的要求,使用Fescar的前提是分支事务中涉及的资源必须支持ACID事务的关系型数据库,分支的提交和回滚都依赖于本地事务来保障。了解即可。

    8. 事务的基本要素?
    原子性Atomicity,指事务由原子的操作序列组成,所有操作要么全部成功,要么全部失败回滚。
    一致性Consistency,指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处以一致性状态。比如在做多表操作时,多个表要么都是事务后新的值,要么都是事务前的旧值。
    隔离性Isolation,指多个用户并发访问数据库时,数据库为每个用户执行的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。事务的隔离级别在后文中介绍。
    持久性Durability,指一个事务一旦提交并执行成功,那么对数据库中数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

    9. 事务的并发问题?事务的隔离级别有哪些?

            事务的并发问题

      1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

      2、不可重复读:在一个事务里面读取了两次某个数据,读出来的数据不一致,事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。

      3、幻读:在一个事务里面的操作中发现了未被操作的数据,系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条新的学生成绩具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

      小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

    事务隔离级别脏读不可重复读幻读
    读未提交(read-uncommitted)
    读已提交(read-committed)
    可重复读(repeatable-read)
    串行化(serializable)

    10. 什么叫视图?游标是什么?
    答:视图是对一些原表选择部分列合并成的一个虚拟表格,具有和物理表相同的功能。可以对视图进行插入、更新、删除操作。对视图的修改会同步到具体数据表中。注意以下几种情况不能对视图进行插入、更新、删除的操作:

    1. 视图列中含有统计函数的情况
    2. 视图使用了GROUP BY /HAVING,DISTINCT,UNION语句的情况
    3. 视图定义时使用了子查询的情况
    4. 对视图的修改涉及到了多个基础表的数据

    游标:是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。

    11. 什么是主键?什么是外键?
    主键是表格里的(一个或多个)字段,只用来定义表格里的行;主键里的值总是唯一的。外键是一个用来建立两个表格之间关系的约束。这种关系一般都涉及一个表格里的主键字段与另外一个表格(尽管可能是同一个表格)里的一系列相连的字段。那么这些相连的字段就是外键。

    12.一个表有过多索引需要有什么样的性能考虑?
    时间和空间。对一个表格的索引越多,数据库引擎用来更新、插入或者删除数据所需要的时间就越多,因为在数据操控发生的时候索引也必须要维护。

    13.你可以用什么来确保表格里的字段只接受特定范围里的值?
    这个问题可以用多种方式来回答,但是只有一个答案是"好"答案。您希望听到的回答是Check限制(MYSQL有,但是没有强制约束,使用了也没用),它在数据库表格里被定义,用来限制输入该列的值。
    触发器也可以被用来限制数据库表格里的字段能够接受的值,但是这种办法要求触发器在表格里被定义,这可能会在某些情况下影响到性能。因此,微软建议使用Check限制而不是其他的方式来限制域的完整性。

    15. 使用索引查询一定能提高查询的性能吗?为什么
    通常,通过索引查询数据比全表扫描要快.但是我们也必须注意到它的代价.
    索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时,索引本身也会被修改. 这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出磁盘I/O. 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.使用索引查询不一定能提高查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种情况:
        1.基于一个范围的检索,一般查询返回结果集小于表中记录数的30%宜采用;
        2.基于非唯一性索引的检索
    索引就是为了提高查询性能而存在的,如果在查询中索引没有提高性能,只能说是用错了索引,或者讲是场合不同

    16. 列举几种表连接方式,并写出SQL语句? 什么是相关子查询?关联查询和相关子查询的区别?
    内连接、外连接(左、右、全)、自连接(特殊的内连接)、交叉连接
    Or hash join/merge join/nest loop(cluster join)/index join 
    1)内连接:只连接匹配的行
    select A.c1,B.c2 from A join B on A.c3 = B.c3;
    2)左外连接:包含左边表的全部行(不管右边的表中是否存在与它们匹配的行)以及右边表中全部匹配的行,最终结果数大于等于左表行数
    select A.c1,B.c2 from A left join B on A.c3 = B.c3;
    3)右外连接:包含右边表的全部行(不管左边的表中是否存在与它们匹配的行)以及左边表中全部匹配的行,最终结果数大于等于右表结果数
    select A.c1,B.c2 from A right join B on A.c3 = B.c3;
    4)全外连接:包含左、右两个表的全部行,不管在另一边的表中是否存在与它们匹配的行
    select A.c1,B.c2 from A full join B on A.c3 = B.c3;
    5)交叉连接又称隐式的内联查询:生成笛卡尔积——它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行一一匹配
    select A.c1,B.c2 from A,B;
    6)相关子查询是一种包含子查询的特殊类型的查询。查询里包含的子查询会用到外部查询的值。
        SELECT * FROM A WHERE A.id IN(SELECT B.aId FROM B  WHERE B.name=A.name)
     7)表关联可能有多条记录,子查询只有一条记录,如果需要唯一的列,最好走子查询

    交叉连接与内连接,查询的结果是一样的,但是效率不同,内连接查询的效率更高。

    17 如何优化数据库,如何提高数据库的性能?
    主要从:表结构、索引、sql语句考虑
    (1)表结构如:合适的字段类型、适当增加中间表、适当拆分表、增加冗余字段避免关联查询、尽量不要使用null
    (2)索引:不要盲目使用索引、要在数据差别大的列上使用索引、要在查询常用到的列上增加索引、根据具体查询情况选择合适的索引数据结构
    (3)查询时不要select *,注意查询是否使用了索引、减少关联查询、减少in和not in这些查询、针对不同的情况选择in或者exists查询
    (4)适当的使用存储过程

    18. 谈谈数据库设计的三范式
    第一范式的定义:所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,则这个表属于第一范式(常记成1NF)。简而言之:"每一字段只存储一个值"。例如:职工号,姓名,电话号码组成一个表(一个人可能有一个办公室电话 和一个家里电话号码)
    第二范式的定义:如果一个表属于1NF,任何属性只依赖于关键字,则这个表属于第二范式(常记成2NF )。简而言之:必须先符合1NF的条件,且每一行都能被唯一的识别。将1NF转换成2NF的方法是添加主键。例如:学号,姓名,课程名,成绩
    第三范式的定义:如果一个表属于2NF,且不包含传递依赖性,则这个表是第三范式(常记成 3NF)。简而言之,第三范式就是属性不依赖于其它非主属性。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。

    19. 设计数据库应注意那些问题
    首先应尽量满足三范式的要求,在一定程度上打破三范式的要求以提高数据库的性能。例如,我们创建某些表的时候,不仅会插入外键,还会插入相关的属性,这违反了第三范式,但这样做的好处,就是我们在业务查询的时候会减少很多关联查询,从而提高查询效率。

    20. 表与表之间的关联关系
    分为3种:一对一、一对多、多对多。

    21. 主键和外键的区别
    主键在本表中是唯一的、不可为空的,外键可以重复可以唯空;外键和另一张表的主键关联,不能创建对应表中不存在的外键。

    22. 游标的作用?如何知道游标已经到了最后?
    游标用于定位结果集的行,在mysql中用DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; 可以判断是否到了最后,通常此变量不等于0表示出错或到了最后。

    23. 事前触发和事后触发有何区别?语句级触发和行级触发有何区别?
    事前触发器运行于触发事件发生之前,如表的插入、更新、删除之前,而事后触发器运行于触发事件发生之后,如表的插入、更新、删除之后。通常事前触发器可以获取事件之前和新的字段值。语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次。

    24. 数据库设计的必要性及设计步骤
    好的数据库结构有利于:节省数据的存储空间,能够保证数据的完整性,方便进行数据库应用系统的开发
    设计不好的数据库结构将导致:数据冗余、存储空间浪费和内存空间浪费
    不管数据库的大小和复杂程度如何,可以用下列基本步骤来设计数据库:收集信息--标识对象--设计数据模型--标识每个对象--存储的信息类型–标识对象之间的关系

    25. 什么是数据模型?什么是规范化?
    数据模型是一种标识实体类型及其实体间联系的模型。典型的数据模型有网状模型、层次模型和关系模型。
    从关系数据库的表中,除去冗余数据的过程称为规范化。包括:精简数据库的结构,从表中删除冗余的列,标识所有依赖于其它数据的数据

    26. 说出一些数据库优化方面的经验?
    用PreparedStatement 一般来说比Statement性能高:一个sql 发给服务器去执行,涉及步骤:语法检查、语义分析, 编译,缓存
    “inert into user values(1,1,1)”-?二进制
    “inert into user values(2,2,2)”-?二进制
    “inert into user values(?,?,?)”-?二进制

    有外键约束会影响插入和删除性能,如果程序能够保证数据的完整性,那在设计数据库时就去掉外键。(比喻:就好比免检产品,就是为了提高效率,充分相信产品的制造商)
    (对于hibernate来说,就应该有一个变化:empleyee->Deptment对象,现在设计时就成了employee?deptid)

    看mysql帮助文档子查询章节的最后部分,例如,根据扫描的原理,下面的子查询语句要比第二条关联查询的效率高:
    1)select e.name,e.salary where e.managerid=(select id from employee where name='zxx');
    2)select e.name,e.salary,m.name,m.salary from employees e,employees m where
    e.managerid = m.id and m.name='zxx';

    表中允许适当冗余,譬如,主题帖的回复数量和最后回复时间等
    将姓名和密码单独从用户表中独立出来。这可以是非常好的一对一的案例哟!
    sql语句全部大写,特别是列名和表名都大写。特别是sql命令的缓存功能,更加需要统一大小写,sql语句?发给oracle服务器?语法检查和编译成为内部指令?缓存和执行指令。根据缓存的特点,不要拼凑条件,而是用?和PreparedStatment
    还有索引对查询性能的改进也是值得关注的。

    27. union和union all有什么不同?
    Union和Union All的区别之一在于对重复结果的处理。

    UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。
    而UNION ALL只是简单的将两个结果合并后就返回。这样,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了。
    从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复的数据的话,那么就使用UNION ALL

    28. 几种索引类型?

    MySQL数据库几个基本的索引类型:普通索引、唯一索引、主键索引、组合索引、全文索引

    • 索引加快数据库的检索速度
    • 索引降低了插入、删除、修改等维护任务的速度
    • 唯一索引可以确保每一行数据的唯一性
    • 通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能
    • 索引需要占物理和数据空间 

    29. 数据库的乐观锁和悲观锁是什么?数据库表锁和行锁又是什么?

    数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。
    乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。

    • 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
    • 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。

    在MySQL中 引擎为InnoDB的表支持表锁和行锁,而引擎为MyISAM的表只支持表锁

    • 表锁:开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
    • 行锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高

    30. char和vachar区别?

    char是固定长度,处理速度比vachar快,费内存空间,当存储的值没有达到指定的范围时,会用空格替代。
    vachar是不固定长度,节约存储空间,存储的是真实的值。
    如:存储字符串'abc'
    使用char(10),表示存储的字符将占10个字节(包括7个空字符)
    使用varchar(10),则表示只占3个字节,10是最大值,当存储的字符小于10时,按照实际的长度存储。

    31. 什么是E-R图?

    E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。

    ER图中有如下四个成分:

    矩形框:表示实体,在框中记入实体名。

    菱形框:表示联系,在框中记入联系名。

    椭圆形框:表示实体或联系的属性,将属性名记入框中。对于主属性名,则在其名称下划一下划线。

    连线:实体与属性之间;实体与联系之间;联系与属性之间用直线相连,并在直线上标注联系的类型。(对于一对一联系,要在两个实体连线方向各写1; 对于一对多联系,要在一的一方写1,多的一方写N;对于多对多关系,则要在两个实体连线方向各写N,M。

    E-R图的3个基本要素是实体、属性和联系

    32.MySQL两种引擎InnoDB和MyISAM的区别?

    1. MyISAM不支持事务,而InnoDB支持事务。
    2. MyISAM锁的是表锁(表锁又分读锁和写锁),而InnoDB锁为行级锁。
    3. MyISAM支持全文类型索引,而InnoDB不支持。
    4. MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。
    5. MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦。
    6. InnoDB表比MyISAM表更安全,可以在保证数据不会丢失的情况下,切换非事务表到事务表(alter table tablename type=innodb)。

    33. 如何解决MYSQL数据库中文乱码问题?

    建表和建库的时候指定字符集。

    SQL练习

    1.为管理业务培训信息,建立3个表:
    S(S#,SN,SD,SA)S#,SN,SD,SA分别代表学号,学员姓名,所属单位,学员年龄
    C(C#,CN)C#,CN分别代表课程编号,课程名称
    SC(S#,C#,G) S#,C#,G分别代表学号,所选的课程编号,学习成绩
    1)使用标准SQL嵌套语句查询选修课程名称为’税收基础’的学员学号和姓名?
    答案:select s# ,sn from s where S# in(select S# from c,sc where c.c#=sc.c# and cn=’税收基础’)
    2) 使用标准SQL嵌套语句查询选修课程编号为’C2’的学员姓名和所属单位?
    答:select sn,sd from s,sc where s.s#=sc.s# and sc.c#=’c2’
    3) 使用标准SQL嵌套语句查询不选修课程编号为’C5’的学员姓名和所属单位?
    答:select sn,sd from s where s# not in(select s# from sc where c#=’c5’)
    4)查询选修了课程的学员人数
    答:select 学员人数=count(distinct s#) from sc
    5) 查询选修课程超过5门的学员学号和所属单位?
    答:select sn,sd from s where s# in(select s# from sc group by s# having count(distinct c#)>5)

    2. 查询表A(id,name)中存在id重复三次以上的记录,查询语句请写出来?
    SELECT * FROM A GROUP BY id HAVING COUNT(id)>3

    3. 适用于MySql的分页查询语句?
    --limit函数,从数据库表中的m条记录开始,检索n条记录。
    select * from 表名 limit m,n;

    4. 适用于Oracle的分页查询语句?使用rownum关键字,oracle特有的分析函数和树查询非常有用可以看看。
    --从m条开始,检索n条记录。
    select * from (select rownum r,t1.* from 表名称 t1 where rownum < m + n) b where b.r >= m;

    5. 所有部门之间的比赛组合
    一个叫department的表,里面只有一个字段name,一共有4条纪录,分别是a,b,c,d,对应四个球对,现在四个球对进行比赛,用一条sql语句显示所有可能的比赛组合.

    答:SELECT t1.name AS whiteName,t2.name AS blackName FROM department t1 INNER JOIN department t2 ON t1.name>t2.name

    6.简单说一说drop、delete与truncate的区别

    SQL中的drop、delete、truncate都表示删除,但是三者有一些差别

    • delete和truncate只删除表的数据不删除表的结构
    • 速度,一般来说: drop> truncate >delete 
    • delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;
      如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger. 

     7. 每个月份的发生额都比101科目多的科目
    请用SQL语句实现:从TestDB数据表中查询出所有月份的发生额都比101科目相应月份的发生额高的科目。
    请注意:TestDB中有很多科目,都有1-12月份的发生额。
    表名:TestDB
    字段:AccID:科目代码,Occmonth:发生额月份,DebitOccur:发生额。
    答案:
    SELECT DISTINCT t1.AccID FROM TestDB t1 INNER JOIN TestDB t2 ON t2.Occmonth=t1.OccMonth AND t1.DebitOccur>t2.DebitOccur AND t2.AccID=101

    8. 统计每年每月的信息
    year month amount
    1991 1 1.1
    1991 2 1.2
    1991 3 1.3
    1991 4 1.4
    1992 1 2.1
    1992 2 2.2
    1992 3 2.3
    1992 4 2.4
    查成这样一个结果
    year m1 m2 m3 m4
    1991 1.1 1.2 1.3 1.4
    1992 2.1 2.2 2.3 2.4
    答案一:
    select sales.year ,
    (select t.amount from sales t where t.month='1' and t.year= sales.year) '1',
    (select t.amount from sales t where t.month='1' and t.year= sales.year) '2',
    (select t.amount from sales t where t.month='1' and t.year= sales.year) '3',
    (select t.amount from sales t where t.month='1' and t.year= sales.year) as '4' 
    from sales group by year;
    答案二:

    SELECT sales.`year`,GROUP_CONCAT(CONCAT(sales.`year`,':',sales.amount))
     FROM sales GROUP BY sales.`year`

    9. 显示文章标题,发帖人、最后回复时间
    表:id,title,postuser,postdate,parentid
    准备sql语句:
    drop table if exists articles;
    create table articles(id int auto_increment primary key,title varchar(50), postuser varchar(10), postdate datetime,parentid int references articles(id));
    insert into articles values
    (null,'第一条','张三','1998-10-10 12:32:32',null),
    (null,'第二条','张三','1998-10-10 12:34:32',null),
    (null,'第一条回复1','李四','1998-10-10 12:35:32',1),
    (null,'第二条回复1','李四','1998-10-10 12:36:32',2),
    (null,'第一条回复2','王五','1998-10-10 12:37:32',1),
    (null,'第一条回复3','李四','1998-10-10 12:38:32',1),
    (null,'第二条回复2','李四','1998-10-10 12:39:32',2),
    (null,'第一条回复4','王五','1998-10-10 12:39:40',1);

    答案:
    select a.title,a.postuser,
    (select max(postdate) from articles where parentid=a.id) reply 
    from articles a where a.parentid is null;

    10. 查出比经理薪水还高的员工信息:
    Drop table if not exists employees;
    create table employees(id int primary key auto_increment,name varchar(50)
    ,salary int,managerid int references employees(id));
    insert into employees values (null,' lhm',10000,null), (null,' zxx',15000,1
    ),(null,'flx',9000,1),(null,'tg',10000,2),(null,'wzg',10000,3);

    Wzg大于flx,lhm大于zxx

    解题思路:
    根据sql语句的查询特点,是逐行进行运算,不可能两行同时参与运算。
    涉及了员工薪水和经理薪水,所有,一行记录要同时包含两个薪水,所有想到要把这个表自关联组合一下。
    首先要组合出一个包含有各个员工及该员工的经理信息的长记录,譬如,左半部分是员工,右半部分是经理。而迪卡尔积会组合出很多垃圾信息,先去除这些垃圾信息。

    select e.* from employees e,employees m where e.managerid=m.id and e.sala
    ry>m.salary;

    11. 求出小于45岁的各个老师所带的大于12岁的学生人数
    数据库中有3个表 teacher 表,student表,tea_stu关系表。 
    teacher 表 teaID name age 
    student 表 stuID name age 
    teacher_student表 teaID stuID 
    要求用一条sql查询出这样的结果 
    1)显示的字段要有老师name, age 每个老师所带的学生人数 
    SELECT t1.teaID,COUNT(*) FROM teacher_student t1 LEFT JOIN teacher t2 ON t1.teaID=t2.teaID GROUP BY t1.teaID
    2)只列出老师age为40以下,学生age为12以上的记录
    SELECT t1.teaID,t2.name AS teaName,t1.stuID,t3.name AS stuName FROM teacher_student t1 INNER JOIN teacher t2 ON t1.teaID=t2.teaID AND t2.age<40 INNER JOIN student t3 ON t1.stuID=t3.stuID AND t3.age>12


    12. 求出发帖最多的人:
    select authorid,count(*) total from articles group by authorid ORDER BY total DESC LIMIT 1

    13. 一个用户表中有一个积分字段,假如数据库中有100多万个用户,若要在每年第一天凌晨将积分清零,你将考虑什么,你将想什么办法解决?
    alter table drop column score;
    alter table add colunm score int;
    可能会很快,但是需要试验,试验不能拿真实的环境来操刀,并且要注意,
    这样的操作时无法回滚的,在我的印象中,只有inert update delete等DML语句才能回滚,
    对于create table,drop table ,alter table等DDL语句是不能回滚。

    解决方案一,update user set score=0; 
    解决方案二,假设上面的代码要执行好长时间,超出我们的容忍范围,那我就
    alter table user drop column score;
    alter table user add column score int。

    14. xxx公司的sql面试
    Table EMPLOYEES Structure:
    EMPLOYEE_ID NUMBER Primary Key,
    FIRST_NAME VARCHAR2(25),
    LAST_NAME VARCHAR2(25),
    Salary number(8,2),
    HiredDate DATE,
    Departmentid number(2)
    Table Departments Structure:
    Departmentid number(2) Primary Key,
    DepartmentName VARCHAR2(25).

    1)基于上述EMPLOYEES表写出查询:写出雇用日期在今年的,或者工资在[1000,2000]之间的,或者员工姓名(last_name)以’Obama’打头的所有员工,列出这些员工的全部个人信息。
    select * from employees 
    where Year(hiredDate) = Year(date()) 
    or (salary between 1000 and 200)
    or left(last_name,3)='abc';

    2) 基于上述EMPLOYEES表写出查询:查出部门平均工资大于1800元的部门的所有员工,列出这些员工的全部个人信息。
    mysql> select id,name,salary,deptid did from employee1 where (select avg(salary)
    from employee1 where deptid = did) > 1800;

    3) 基于上述EMPLOYEES表写出查询:查出个人工资高于其所在部门平均工资的员工,列出这些员工的全部个人信息及该员工工资高出部门平均工资百分比。
    select employee1.*,(employee1.salary-t.avgSalary)*100/employee1.salary 
    from employee1,
    (select deptid,avg(salary) avgSalary from employee1 group by deptid) as t
    where employee1.deptid = t.deptid and employee1.salary>t.avgSalary;

    二、数据库选择题:
    1. 下面叙述正确的是___C___。 
    A、算法的执行效率与数据的存储结构无关 
    B、算法的空间复杂度是指算法程序中指令(或语句)的条数 
    C、算法的有穷性是指算法必须能在执行有限个步骤之后终止D、以上三种描述都不对

    2. 以下数据结构中不属于线性数据结构的是__C____。
    A、队列 B、线性表 C、二叉树 D、栈

    3. 在一棵二叉树上第5层的结点数最多是__B____。
    A、8 B、16 C、32 D、15

    4. 在结构化方法中,用数据流程图(DFD)作为描述工具的软件开发阶段是__B__。 
    A、可行性分析 B、需求分析 C、详细设计 D、程序编码

    5. 在软件开发中,下面任务不属于设计阶段的是___D___。 
    A、数据结构设计 B、给出系统模块结构 C、定义模块算法 D、定义需求并建立系统模型

    6. 数据库系统的核心是___B___。 
    A、数据模型 B、数据库管理系统 C、软件工具 D、数据库

    7. 下列叙述中正确的是___C___。 
    A、数据库是一个独立的系统,不需要操作系统的支持 
    B、数据库设计是指设计数据库管理系统 
    C、数据库技术的根本目标是要解决数据共享的问题 
    D、数据库系统中,数据的物理结构必须与逻辑结构一致

    8. SQL语句中修改表结构的命令是__C____。 
    A、MODIFY TABLE B、MODIFY STRUCTURE C、ALTER TABLE D、ALTER STRUCTURE

    9. 如果要创建一个数据组分组报表,第一个分组表达式是"部门",第二个分组表达式是"性别",第三个分组表达式是"基本工资",当前索引的索引表达式应当是___B___。 
    A、部门+性别+基本工资 B、部门+性别+STR(基本工资) 
    C、STR(基本工资)+性别+部门 D、性别+部门+STR(基本工资) 

    10. 数据库DB、数据库系统DBS、数据库管理系统DBMS三者之间的关系是___A___。 
    A、DBS包括DB和DBMS B、DBMS包括DB和DBS 
    C、DB包括DBS和DBMS D、DBS就是DB,也就是DBMS

    11. 要控制两个表中数据的完整性和一致性可以设置"参照完整性",要求这两个表__A___。 
    A、是同一个数据库中的两个表 B、不同数据库中的两个表 
    C、两个自由表 D、一个是数据库表另一个是自由表

    12. 在关系模型中,实现"关系中不允许出现相同的元组"的约束是通过___B___。 
    A、候选键 B、主键 C、外键 D、超键

    13. 只有满足联接条件的记录才包含在查询结果中,这种联接为___C___。 
    A、左联接 B、右联接 C、内部联接 D、完全联接

    14. 索引字段值不唯一,应该选择的索引类型为___B___。 
    A、主索引 B、普通索引 C、候选索引 D、唯一索引

    15. 从数据库中删除表的命令是__A____。 
    A、DROP TABLE B、ALTER TABLE C、DELETE TABLE D、USE

    16. DELETE FROM S WHERE 年龄>60语句的功能是__B____。 
    A、从S表中彻底删除年龄大于60岁的记录 B、S表中年龄大于60岁的记录被加上删除标记 
    C、删除S表 D、删除S表的年龄列

    17. SELECT-SQL语句是__B____。 
    A、选择工作区语句 B、数据查询语句 C、选择标准语句 D、数据修改语句

    18. SQL语言是___C___语言。
    A、层次数据库 B、网络数据库 C、关系数据库 D、非数据库

    19. 在SQL中,删除视图用___C___。 
    A、DROP SCHEMA命令 B、CREATE TABLE命令 C、DROP VIEW命令 D、DROP INDEX命令

    20. 在命令窗口执行SQL命令时,若命令要占用多行,续行符是__D____。 
    A、冒号(:) B、分号(;) C、逗号(,) D、连字符(-)

    21. 设有图书管理数据库: 
    图书(总编号C(6),分类号C(8),书名C(16),作者C(6),出版单位C(20),单价N(6,2)) 
    读者(借书证号C(4),单位C(8),姓名C(6),性别C(2),职称C(6),地址C(20)) 
    借阅(借书证号C(4),总编号C(6),借书日期D(8)) 
    对于图书管理数据库,查询0001号借书证的读者姓名和所借图书的书名。 
    SQL语句正确的是___A___。 
    SELECT 姓名,书名 FROM 借阅,图书,读者 WHERE; 
    借阅.借书证号="0001" AND; 
    ______ 
    ______ 
    A、图书.总编号=借阅.总编号 AND; 
    读者.借书证号=借阅.借书证号 
    B、图书.分类号=借阅.分类号 AND; 
    读者.借书证号=借阅.借书证号 
    C、读者.总编号=借阅.总编号 AND; 
    读者.借书证号=借阅.借书证号 
    D、图书.总编号=借阅.总编号 AND; 
    读者.书名=借阅.书名

    22. 设有图书管理数据库: 
    图书(总编号C(6),分类号C(8),书名C(16),作者C(6),出版单位C(20),单价N(6,2)) 
    读者(借书证号C(4),单位C(8),姓名C(6),性别C(2),职称C(6),地址C(20)) 
    借阅(借书证号C(4),总编号C(6),借书日期D(8)) 
    对于图书管理数据库,分别求出各个单位当前借阅图书的读者人次。下面的SQL语句正确的是___A___。 
    SELECT 单位,______ FROM 借阅,读者 WHERE; 
    借阅.借书证号=读者.借书证号 ______ 
    A、COUNT(借阅.借书证号) GROUP BY 单位 B、SUM(借阅.借书证号) GROUP BY 单位 
    C、COUNT(借阅.借书证号) ORDER BY 单位 D、COUNT(借阅.借书证号) HAVING 单位

    23. 设有图书管理数据库: 
    图书(总编号C(6),分类号C(8),书名C(16),作者C(6),出版单位C(20),单价N(6,2)) 
    读者(借书证号C(4),单位C(8),姓名C(6),性别C(2),职称C(6),地址C(20)) 
    借阅(借书证号C(4),总编号C(6),借书日期D(8)) 
    对于图书管理数据库,检索借阅了《现代网络技术基础》一书的借书证号。下面SQL语句正确的是___B___。 
    SELECT 借书证号 FROM 借阅 WHERE 总编号=; 
    ______ 
    A、(SELECT 借书证号 FROM 图书 WHERE 书名="现代网络技术基础") 
    B、(SELECT 总编号 FROM 图书 WHERE 书名="现代网络技术基础") 
    C、(SELECT 借书证号 FROM 借阅 WHERE 书名="现代网络技术基础") 
    D、(SELECT 总编号 FROM 借阅 WHERE 书名="现代网络技术基础")


    三、Oracle面试题
    1. 解释冷备份和热备份的不同点以及各自的优点 
    解答:热备份针对归档模式的数据库,在数据库仍旧处于工作状态时进行备份。而冷备份指在数据库关闭后,进行备份,适用于所有模式的数据库。热备份的优点在于当备份时,数据库仍旧可以被使用并且可以将数据库恢复到任意一个时间点。冷备份的优点在于它的备份和恢复操作相当简单,并且由于冷备份的数据库可以工作在非归档模式下,数据库性能会比归档模式稍好。(因为不必将archive log写入硬盘)
    2. 你必须利用备份恢复数据库,但是你没有控制文件,该如何解决问题呢?
    解答:重建控制文件,用带backup control file 子句的recover 命令恢复数据库。
    3. 如何转换init.ora到spfile?
    解答:使用create spfile from pfile 命令.
    4. 解释data block , extent 和 segment的区别(这里建议用英文术语)
    解答:data block是数据库中最小的逻辑存储单元。当数据库的对象需要更多的物理存储空间时,连续的data block就组成了extent . 一个数据库对象
    拥有的所有extents被称为该对象的segment.
    5. 给出两个检查表结构的方法
    解答:
    1)DESCRIBE命令
    2)DBMS_METADATA.GET_DDL 包
    6. 怎样查看数据库引擎的报错
    解答:alert log.

    7. 比较truncate和delete 命令
    解答:两者都可以用来删除表中所有的记录。区别在于:truncate是DDL操作,它移动HWK,不需要 rollback segment .而Delete是DML操作, 需要rollback segment 且花费较长时间.

    8. 使用索引的理由
    解答:快速访问表中的data block

    9. 给出在STAR SCHEMA中的两种表及它们分别含有的数据
    解答:Fact tables 和dimension tables. fact table 包含大量的主要的信息而 dimension tables 存放对fact table 某些属性描述的信息

    10. FACT Table上需要建立何种索引?
    解答:位图索引 (bitmap index)

    11. 给出两种相关约束?
    解答:主键和外键

    12. 如何在不影响子表的前提下,重建一个母表
    解答:子表的外键强制实效,重建母表,激活外键

    13. 解释归档和非归档模式之间的不同和它们各自的优缺点
    解答:归档模式是指你可以备份所有的数据库 transactions并恢复到任意一个时间点。非归档模式则相反,不能恢复到任意一个时间点。但是非归档模式可以带来数据库性能上的少许提高.

    14. 如何建立一个备份控制文件?
    解答:Alter database backup control file to trace.

    15. 给出数据库正常启动所经历的几种状态 ?
    解答:
      STARTUP NOMOUNT – 数据库实例启动
      STARTUP MOUNT - 数据库装载
      STARTUP OPEN – 数据库打开

    16. 哪个column可以用来区别V$视图和GV$视图?
    解答: INST_ID 指明集群环境中具体的 某个instance 。

    17. 如何生成explain plan?
    解答:运行utlxplan.sql. 建立plan 表
    针对特定SQL语句,使用 explain plan set statement_id = 'tst1' into plan_table
    运行utlxplp.sql 或 utlxpls.sql察看explain plan

    18. 如何增加buffer cache的命中率?
    解答:在数据库较繁忙时,适用buffer cache advisory 工具,查询v$db_cache_advice . 如果有必要更改,可以使用 alter system set db_cache_size 命令

    19. ORA-01555的应对方法?
    解答:具体的出错信息是snapshot too old within rollback seg , 通常可以通过
    增大rollback seg来解决问题。当然也需要察看一下具体造成错误的SQL文本

    20. 解释$ORACLE_HOME和$ORACLE_BASE的区别?
    解答:ORACLE_BASE是oracle的根目录,ORACLE_HOME是oracle产品的目录。

    21. 如何判断数据库的时区?
    解答:SELECT DBTIMEZONE FROM DUAL;

    22. 解释GLOBAL_NAMES设为TRUE的用途
    解答:GLOBAL_NAMES指明联接数据库的方式。如果这个参数设置为TRUE,在建立数据库链接时就必须用相同的名字连结远程数据库

    23。如何加密PL/SQL程序?
    解答:WRAP

    24. 解释FUNCTION,PROCEDURE和PACKAGE区别
    解答:function 和procedure是PL/SQL代码的集合,通常为了完成一个任务。procedure 不需要返回任何值而function将返回一个值在另一
    方面,Package是为了完成一个商业功能的一组function和proceudre的集合

    25. 解释TABLE Function的用途
    解答:TABLE Function是通过PL/SQL逻辑返回一组纪录,用于普通的表/视图。他们也用于pipeline和ETL过程。

    26. 举出3种可以收集three advisory statistics
    解答:Buffer Cache Advice, Segment Level Statistics, Timed Statistics

    27. Audit trace 存放在哪个oracle目录结构中?
    解答:unix $ORACLE_HOME/rdbms/audit Windows the event viewer

    28. 解释materialized views的作用
    解答:Materialized views 用于减少那些汇总,集合和分组的信息的集合数量。它们通常适合于数据仓库和DSS系统。

    29. 当用户进程出错,哪个后台进程负责清理它
    解答: PMON

    30. 哪个后台进程刷新materialized views?
    解答:The Job Queue Processes.

    31. 如何判断哪个session正在连结以及它们等待的资源?
    解答:V$SESSION / V$SESSION_WAIT

    32. 描述什么是 redo logs
    解答:Redo Logs 是用于存放数据库数据改动状况的物理和逻辑结构。可以用来修复数据库.

    33. 如何进行强制LOG SWITCH?
    解答:ALTER SYSTEM SWITCH LOGFILE;

    34. 举出两个判断DDL改动的方法?
    解答:你可以使用 Logminer 或 Streams

    35. Coalescing做了什么?
    解答:Coalescing针对于字典管理的tablespace进行碎片整理,将临近的小extents合并成单个的大extent.

    36. TEMPORARY tablespace和PERMANENT tablespace 的区别是?
    解答:A temporary tablespace 用于临时对象例如排序结构而 permanent tablespaces用来存储那些'真实'的对象(例如表,回滚段等)

    37. 创建数据库时自动建立的tablespace名称?
    解答:SYSTEM tablespace.

    38. 创建用户时,需要赋予新用户什么权限才能使它联上数据库。
    解答:CONNECT

    39. 如何在tablespace里增加数据文件?
    解答:ALTER TABLESPACE ADD DATAFILE SIZE

    40. 如何变动数据文件的大小?
    解答:ALTER DATABASE DATAFILE RESIZE ;

    41. 哪个VIEW用来检查数据文件的大小?
    解答: DBA_DATA_FILES

    42. 哪个VIEW用来判断tablespace的剩余空间
    解答:DBA_FREE_SPACE

    43. 如何判断谁往表里增加了一条纪录?
    解答:auditing

    44. 如何重构索引?
    解答: ALTER INDEX REBUILD;

    45. 解释什么是Partitioning(分区)以及它的优点。
    解答:Partition将大表和索引分割成更小,易于管理的分区。

    46. 你刚刚编译了一个PL/SQL Package但是有错误报道,如何显示出错信息?
    解答:SHOW ERRORS

    47. 如何搜集表的各种状态数据?
    解答: ANALYZE
    The ANALYZE command.

    48. 如何启动SESSION级别的TRACE
    解答: DBMS_SESSION.SET_SQL_TRACE
    ALTER SESSION SET SQL_TRACE = TRUE;

    49. IMPORT和SQL*LOADER 这2个工具的不同点
    解答:这两个ORACLE工具都是用来将数据导入数据库的。
    区别是:IMPORT工具只能处理由另一个ORACLE工具EXPORT生成
    的数据。而SQL*LOADER可以导入不同的ASCII格式的数据源

    50。用于网络连接的2个文件?
    解答: TNSNAMES.ORA and SQLNET.ORA

    展开全文
  • 第三章 创建一个分组报表 1. 建立数据模型 数据模型用于定义一个报表中使用的数据及数据结构,这些数据可以是数据库表中的原始数据,也可以是经过加工后的数据,如工资的总和等。从数据库中检索出的数据是否在报表...

     

    第三章   创建一个分组报表

    数据模型用于定义一个报表中使用的数据及数据结构,这些数据可以是数据库表中的原始数据,也可以是经过加工后的数据,如工资的总和等。从数据库中检索出的数据是否在报表输出中显示,也是在数据模型中定义的。

    数据模型由五部分对象组成:查询Queries)、Groups)、Columns)、连接Links)和参数Parameter)。

    1)     建立查询

    查询实际上就是一条SQL SELECT语句,决定了从数据库中指定的表或视图中取哪些行和列。查询所取得的数据可被用于计算、排序、集合运算等,并可以在报表输出时显示。

    Ø 报表中的查询可分为两种:内部查询外部查询。两者的区别在于外部查询可以被其他报表多次引用,而内部查询不能被其他报表参考引用,只能被其所属的报表引用。

    Ø 根据报表中查询的个数可以将报表分为单查询报表多查询报表

    单查询报表:只有一个查询的报表称为单查询报表。单查询报表的常见格式有列表式(Tabular)、标签式(Mailing Label)、信封式(Form Letter)以及分组式。单查询报表虽然只有一个查询,但可以多次显示查询数据,并且可以用不同的格式显示。

    多查询报表:含有多个查询的报表称为多查询报表。多个查询相互之单可以有关联,称为相关的多查询报表;也可以没有关联,称为不相关的多查询报表。

    l  相关的多查询报表:多个查询之间相互关联,一般用于主从式报表,也就是说,报表的一部分数据决定了报表的另一部分数据。取出前一部分数据的查询称为主查询,取出后一部分的查询称为从查询,主查询的每一条记录查询都将引起从查询的执行,从查询只检索与主查询匹配的那些记录。两个查询之间通过定义数据连接产生联系。

    l  不相关的多查询报表:多个查询之间没有关联,Oracle Reports将独立地为每一个查询获取数据,显示出来的是一系列不相关的数据。

    查询之间运行的先后次序由数据模型中的查询次序决定。在数据模型中,查询次序是先上后下,先左后右,所以放在左上角的查询最先执行。

    示例:为避免数据冗余,我们这里将订单头和行分别建立两个查询:

    a)     在对象管理器中选中报表,右击打开“报表编辑器”,然后点击打开“数据模型”。


    b)     点击SQL查询创建两个查询。


    c)     修改Q1->Q_headerG_order_number->G_header;

        Q2->Q_line,G_line_num->G_line

    2)     建立数据连接

    数据连接用于建立两个查询数据之间的关系。在数据模型编辑器中,两个查询之间的连线即表示了一个数据连接。

    工作原理:数据连接通过主键和外部键定义了两个查询之间的主/从关系。主/从关系中父查询的每一条记录的产生都会引起子查询的执行,子查询只检索满足在连接中指定的条件的记录。

    通常情况下,两个查询之间的连接是等值连接,但也可以采用SQL语句(如WHEREHAVINGSTART WITH等)建立非等值连接。

    当一个带有数据连接的报表执行时,该数据连接就被转换成一个SQL子句,并添加到子查询的后面。子查询根据父查询的主链值执行查询。

    建立方法:一种是手动建立的数据连接,一种是自动建立的数据连接。

    手动连接的步骤:在数据模型编辑器中选择:“数据连接”小图标;

    单击父查询的主链列或外部键列,并拖动鼠标到子查询的主链或外部键列,使它们之间建立一条连线。注意,连线总是从父查询到子查询的;

    自动连接的步骤:在数据模型编辑器中选择:“数据连接”小图标;

    单击父查询,并拖动鼠标到子查询上,系统会自动显示父查询和子查询之间是依据哪个列建立连接的;

           示例:点击数据连接,创建从Q_header (header_id)Q_line(header_id1)的数据连接。


    3)     建立组

    组对象主要有两个功能:

    Ø 将一个查询的数据分成几个集合,每个集合称为组。例如,将“EMP”表按“DEPTNO”分组,结果显示如下:

    clip_image008

    Ø 过滤查询数据,通过组可以对查询的结果进行过滤。

    Oracle Reports中将组分为缺省组和用户定义组两类:

    Ø 在缺省的情况下,Oracle Reports为数据模型中的每一个查询产生一个组,取名取成查询的名称。查询名称以“Q_”开头,而组名以“G_”开头。例如,查询名称为“Q_header”,则Oracle Reports为其产生的缺省组名为“Q_header”。

    Ø 用户定义组可用于以下三种情况:分组报表;矩阵报表;子汇总。

    组过滤器允许有条件的选择由查询检索出来的数据,通过组过滤器过滤查询结果。

    有两种类型的组过滤器:Oracle Reports封装过滤器和用户定义过滤器。

    Ø Oracle Reports封装过滤器允许指定在一个组中希望检索的记录数,在报表开发过程中可以使用封装过滤器来限制数据。Oracle Reports软件包中有两个封装过滤器:First Filter,只显示组内前n条记录;Last Filter,只显示组内后n条记录。

    Ø 用户定义过滤器:用户可以定义自己的过滤器来限制在特定条件下的记录的检索。用户定义的过滤器是通过编写PL/SQL代码建立的。


    数据模型中组的层次决定了在缺省布局对话框中组的次序,同时也决定了在缺省布局中组的次序,但这不是最终的报表格式,因为可以对缺省的显示格式进行修改。

    在数据模型编辑器中若没有数据连接,则组的层次是由组在数据模型编辑器中的位置从左至右,从上至下决定的。在数据模型编辑器中若有数据连接,则组的层次可以由数据连接描述。通过对象导航器可以清晰地看到组的层次:


    4)     定义列

    报表的列表示报表的数据。在定义了从数据库检索数据的查询后,可能需要进一步调整报表,增加更多的列,而这些列可以用作报表的数据,执行总计汇总等功能。

    Oracle Reports中的列可以分为两类,缺省列和用户定义列。

    Ø 缺省列

    Oracle Reports为查询SELECT语句中的每一项都建立一个列,因为它们直接对应从数据库中检索出来的各个列,所以缺省列也叫数据库列。

    Oracle Reports除了支持典型的数据类型的列(如字符型、数值型、日期型)以外,还支持图型列。图型列的值可能是:

    直接存储在数据库中的图型:这种列的数据类型通常是RAWLONG RAW。在这种情况下,需在列的属性选项板中指明图形格式。

    文件名或者是图型的URL:这种列的数据类型通常是REF,列中的值对应于用指针指向一个存在操作系统中的文件,报表输出时会根据指针将文件内容输出,在这种情况下,需在列的属性选项板中将“Read from File”设置为“Yes”并输入文件名。文件名前可以带有路径,若文件名前没有带有路径,则Oracle Reports会按照其路径搜索顺序查找文件。可以通过Report Builder的环境变量REPORT30_PATH来设置搜索路径。注意,若列的属性选项板中“Read from File”被置为“No”并且输入了文件名,则报表最后输出的只会是文件名,而不会是文件内容。

    Oracle Reports支持多种图形格式,包括BMPCALSCGMGIFJFIFPCDPCXPICTRASTIFF等。

    Ø 用户定义列

    用户可在特定的组内或报表一级建立列。在特定的组内建立的列称为组一级的列,该列与组内的其他列有相同的显示频度。而报表一级的列只在整个报表中显示一次。用户定义列分为三种类型:公式列占位列汇总列

    a)     公式列,公式列是对其他列执行一个用户定义的计算。建立公式列的方法是用PL/SQL语句写一个函数,从一个或多个列中计算结果,该列的缺省名为“CF_n”。

    示例:在G_line组中定义一个的公式列newAmount,来显示Amount *1.06的值。

    在数据模型编辑器中单击:“公式列”小图标。如果要在组中建一个公式列,则在画布的组区域内单击一下鼠标左键,如果要建一个报表一级的公式列,则在画布的空白区域内单击一下鼠标左键,会生成一个公式列对象;


    双击该公式列对象,弹出其属性选项板;

    点击属性选项板中的“PL/SQL公式”项,弹出“程序单元编辑器”;


    在“程序单元编辑器”中为公式项用PL/SQL语句书写一个计算公式并编译通过


    b)     占位列,占位列的值和数据类型是通过PL/SQL语句设置的,该列的缺省名为“CP_n”。当需要有选择地设置一个列的值时(例如,在每次出现第n个记录时,或每次出现包含有特殊值的记录时)占位列非常有用。

    可以在以下几个地方设置占位列的值:

    Before Reports的报表触发器中(如果占位列是一个报表级的列);

    在报表级的公式列中(如果占位列是一个报表级的列);

    在占位列组或占位列组下面的公式中(为组中的每一条记录设一次值)。

    占位列的用途:

    在公式列的PL/SQL代码中计算出的一些值可以分配给不同的占位列;

    利用占位列保存中间值。例如,存储当前检索出的最高工资对应的记录。

    c)     汇总列,汇总列是对其他列的数据执行计算。Oracle Reports为汇总列提供的计算函数有:总和、平均值、最小值、最大值、计数、第一个、最后一个、%(总计)、标准差、方差。

    示例:在G_header组中添加CS_countAmount,来计算订单行的总金额;

             Report级别添加CS_total,来计算订单的总数量;

    在数据模型编辑器中单击“汇总列”小图标,如果要在组中建立一个汇总列,则在组中你希望该列所在的位置上单击一下鼠标左键,如果要建一个报表一级的汇总列,则在画布的空白区域内单击一下鼠标左键,会生成一个汇总列;


    双击该汇总列对象,弹出其属性选项板;

    从属性选项板中的“汇总”项下的“功能”子项的下拉列表中选择所需的计算公式;在“源”子项中选择要汇总的列名;

    在“重设于”子项中选择汇总的频度,即是就整个报表做一次汇总还是每一页做一次汇总,或者每一组做一次汇总;

    当“功能”子项被选为“%(总计)”时,“计算于”项有用,其值为计算“%(总计)”的汇总列时的组名。该项只对“%(总计)”有用。

    clip_image022 clip_image024

    5)     参数

    参数是报表变量,在报表运行过程中,用户可以为其指定不同的值。参数主要用于在运行过程中修改SELECT语句和设置PL/SQL变量。Oracle Reports中的参数分为两类:系统参数和用户参数。

    Ø 系统参数

    系统参数又称缺省参数。Oracle Reports允许为每一个报表修改标准的运行设置,系统参数共有7个。

    clip_image026

    系统参数

    功能

    取值

    省缺值

    COPIES

    报表输出到打印机的份数

    任何整数

    1

    DESFORMAT

    输出设备的格式,如:打印机

    DfltPslan80

    Dflt

    DESNAME

    输出设备的名字,如:文件名、打印机名

     

     

    DESTYPE

    输出结果送到什么地方,如屏幕、文件、邮件、打印机等

    FileMailScreenPrinter

    Screen

    MODE

    报表运行的模式,如:字符界面、图形界面等

    BitmapCharacter

    Default

    ORIENTATION

    打印报表输出时的打印方向,如:LandscapePortrait

    LandscapePortrait

    LandscapePortrait

    PRINTJOB

    当运行一个报表时是否显示“PRINT JOB”对话框

    YESNO

    YES

    Ø 用户参数

    用户参数是用户建立的一个对象,该对象用于保存在运行时用户可以改变的值。在一个查询的任何地方都可以引用用户的参数,用户参数主要用于以下几个方面:

    l  SELECT语名的WHERE子句中用参数替代常数作限制值。

    l  用参数替代SELECT语句的任何部分,包括选择列、表,甚至整个SELECT语句。

    l  SELECT列表中用参数替换一个单列或一个表达式。

    引用参数的方法主要有两种:连接引用置换引用

    a)     连接引用

    连接引用主要用于替换SQL语句和PL/SQL块中的一个值或表达式。

    使用连接引用的方法是在要引用的参数前加上“:”号。

    连接引用的使用受以下限制:不能在SELECT语句中替换列名;不能在FROM从句中使用连接引用;不能替代保留的单词和子句。

             示例:将查询Q_headerwhere条件中写死的条件:

             oh.order_numberbetween 29480and29485

    修改为:oh.order_numberbetween:p_order_fromand:p_order_to

             保存修改后,Oracle Report会自动加入这两个用户参数。


    b)     置换引用

    置换引用可以用参数替代SELECT语句的任何部分,如替换列名、FROM子句、WHERE子句、GROUP BY子句、ORDER BY子句、HAVING子句、CONNECT BY子句、START WITH子句等。

    使用置换引用的方法是在要引用的参数前加上“&”符号。

    注意:不能在PL/SQL中使用置换引用,但可以在PL/SQL中使用连接引用。

    和连接引用不同的是,对于置换引用的参数,用户必须事先在对象导航器中建立,并且在属性选项板中为其输入初始化值,Oracle Reports不会缺省地建立该参数。

    举例:使用置换引用替代列名和FROM子句。

    SELECT &P_ENAME NAME, &P_EMPNO ENO

    FROM &P_EMP;

    这样可以动态地根据运行时输入的参数值,决定从哪个表检索那些列。

    使用置换引用替换WHERE子句

    SELECT * FROM EMP &P_WHERE;

    在运行时可任意指定WHERE子句,根据不同的限制条件检索所需数据。

    值列表,为参数值建立值列表,这样,在运行时用户就可以从该值列表中选择一个有效值。可以限制用户只能选择值列表中的值,也可以允许用户输入其他的值。

    对于连接引用的参数,值列表可以是一个不能修改的静态的值列表,也可以是在运行时从数据库中动态地选择值的动态值列表。

    对于置换引用的参数,值列表只能是静态的。

    布局的功能是定义报表的格式,包括数据文本及图形的位置和显示格式。

    在布局模型编辑器中将报表布局分为三个区域:表头区域、表尾区域和主体区域,每个区域又分为主体和页边距。

    Ø 表头区域 在报表每一页的开头显示一次,表头区域可以包含文本、图形、数据及其运算。

    Ø 表尾区域 在报表每一页的结尾处显示一次,表尾区域可以包含文本、图形、数据及运算。

    Ø 主体区域 出现在表头和表尾之间,是报表的主要部分。当第一次进入一个新报表的布局模型编辑窗口时,所处的位置就对应着报表的主体区域。主体区域包含报表的主要文本、图形、数据及其运算。

    基本布局对象:

    在布局模型编辑器中,是通过定义和修改布局对象来实现的,Oracle Reports中的基本布局对象有框架Frames)、重复框架Repeating Frames)、Fields)、图文Boilerplate)、定位Anchors)、按钮Buttons)、OLE2对象、Oracle Graphics对象。

    1)     框架

    框架用来围绕其它布局对象。一个框架可以包含任何布局对象,包括其它的框架。框架的打印次数与它所围绕的对象的打印次数一样,框架与记录无关。

    框架的主要用途:

    l  把对象组织在一起,以保证在打印时它们之间的相对位置;

    l  避免覆盖其他对象和被其他对象覆盖;

    l  将报表划分为几个部分。例如,在每一页的顶部采用列表式的报表格式,而在底部采用钜阵式的报表格式;

    l  确保一些对象总是在相同的页中。

    框架分为两种类型:缺省框架和用户定义框架。

    缺省框架,当接受缺省的布局模型时,Oracle Reports会自动生成包含对象的框架。缺省框架的命名形式为“M_n”。缺省框架又可分为两种:垂直可变的组框架和固定尺寸的框架。例如,当创建最初缺省的布局模型时,Oracle Reports产生一个围绕整个布局模型的组框架,这个组框架在垂直方向上是可伸缩的。而固定尺寸的框架通常是围绕图文对象(Boilerplate)建立的,例如列的标题。

    用户定义框架,用户定义的框架是在布局模型编辑器中通过“框架”工具建立的。

    框架的重要属性:

    l  在这之前分页Page Break Before):指示在打印该对象前进行换页。

    l  在这之后分页Page Break After):指示在打印完该对象后进行换页,在其后面的对象都将移到下一页打印。

    l  页保护Page Protect):指示对象内的所有对象尽可能地打印在一个页内,如果一个页容纳不下的话,在开始打印该对象时会先换页。

    l  垂直缩放值Vertical Elasticity):指示对象的垂直大小是否可以改变,有:收缩、扩展、固定、可变。

    l  水平缩放值Horizontal Elasticity):指示对象的水平大小是否可以改变,有:收缩、扩展、固定、可变。

    l  打印对象在Print Object On):指示对象在报表的打印频率,有:全部页、除首页外的全部、除尾页外的全部、缺省、第一页、最后一页。

    l  基于以下环境打印Base Print On):指示对象是以定位对象还是以包含对象为基准进行打印。

    l  跟随定位对象Keep With Anthoring Object):指示对象是否跟随定位对象打印在同一个逻辑页中。

    2)     重复框架

    重复框架主要用于显示由一个组检索出来的多行数据的对象。一个重复框架可以包含任何布局对象,也可以包括其它的重复框架。重复框架是与记录相关的,它为一个组的每一条记录及其所关联的数据模型对象都打印一次。使用重复框架可以控制记录层的显示和格式,比如:记录的打印方向、记录的空隙、边框线、颜色、字体等。重复框架的箭头方向指明了重复框架重复的方向。

    嵌套的重复框架常常用于建立主/从表和分组表。

    重复框架分为两种类型,缺省的重复框架和用户定义的重复框架。

    缺省的重复框架,当接受缺省的布局模型时,Oracle Reports会自动地为数据模型中的每一个组生成一个重复框架,并且为组中的每一列都对应安排一个域,放在重复框架内。

    用户定义的重复框架,用户定义的重复框架是在布局模型编辑器中通过“重复框架”工具建立的。

    重复框架的几个重要属性:

    l  Source):每一个重复框架必须有一个源()作为其数据来源,在重复框架中每一条源数据显示一次;

    l  打印方向Print Drection):重复框架中记录的打印方向,有:横向、纵向、横向/纵向、纵向/横向;

    l  每页的最大记录数Maximum Record per Page):在逻辑页上显示的重复框架记录的最大数目,可以通过该属性改善报表的可看性。例如,希望在每个逻辑页上只显示三条记录,则将该属性设置为3。该属性的取值可以为正整数和空,若为空,则尽可能在一个逻辑页上显示最大数目的记录。

    l  最小孤立记录数Minimum Widow Records):必须在一张逻辑页上显示的最少记录数。若从逻辑页的指定位置开始放不下此属性中给出的记录数,则将从下一张逻辑页开始显示。。例如下图,有两个独立的重复框架按纵向打印,第二个重复框架位于第一页的底部,但第一页上仅有打印两条记录的空间了,为了使报表看起来更美观,我们希望第二个重复框架换记录能从第二页开始打印,这时就需要将“最小孤立记录数”设置为3


    l  列模式Column Mode):用于控制如何为重复框架中的记录提取数据和格式化数据。这个属性有两个选项:“是”和“否”。若选“是”,则允许在上一个重复框架的记录没有打完之前就打印下一个重复框架的记录。例如,若设置“列模式”为是,则虽然记录2直到第二页才打完,但记录3却可以开始在第一页上打印了。若设置:“列模式”为“否”,则记录3只能等到记录2打印完后,才开始在第二页上打印。

    clip_image032 clip_image034

    l  水平框架间隔:重复框架记录间的水平间隔。当打印方向为“纵向”或“纵向/横向”时,该属性的设置无效。

    l  垂直框架间隔:重复框架记录间的垂直距离。当打印方向为“横向”或“横向/纵向”时,该属性的设置无效。

    3)     

    域是用来放置参数、列、页号、当前日期等值的地方。例如一个参数或列没有对应的域,那么它的值不会在报表输出时显示。当生成一个缺省布局模型时,Oracle Reports会自动地为每一个列建立一个域,并将这些域排放在重复框架中。

    域有两种类型:缺省域和用户定义域。

    缺省域,当接爱缺省的布局模型时,Oracle Reports会自动地为每一列产生一个域,并将这些域排放在重复框架中。每一个域的属性都是缺省生成的,但是可以修改。

    用户定义域,用户可以根据需要定义一些域来显示诸如页号、日期等信息。

    用户定义的域是在布局模型编辑器中通过“域”工具建立的。

    域的数据来源有三种:数据模型的中的一个列或参数、系统变量和系统参数。

    系统变量包括:当前日期(&current date)、页码(&logical page number)、面板数值(&panel number)、物理页码(&physucal page number)、总记页(&total logical pages)、总记面版(&total panel)、总计物理页(&total physical pages

    域的属性:

    l  Source):域值的来源。

    l  源数据来源Source Data Type):源的数据类型,此属性为只读。

    l  可视的Visible):若设置为“否”,则表示该域不被格式化。这一属性公用于那些在图文对象中引用的域,通常用于格式信件式报表。若想引用一个“可视的”属性设置为“否”的域,可以在图文对象中输入“&fieldname”。

    l  格式掩码Format Mask):定义以何种格式显示在域中的日期和数值。有值列表可供选择,但是字符型的域没有该属性。

    l  编页码Page Numbering):当域的源列是页码、物理页码、总记页、总记物理页之一时,可以使用该属性来定义如何计算页号。点击:编页码按钮,出现“编页码”对话框。

    4)     图文

    图文是一个查询获取不到但又要在报表中输出的对象,如文本、线条、图形等。可以使用图文对象来改变报表的外观,例如建立报表的页头、增加图形等。

    图文有两种类型:缺省的图文和用户定义的图文。

    缺省的图文,当接受缺省的布局模型时,Oracle Reports会自动地为每个域生成一个列标题。对于某些报表类型,Oracle Reports会在列标题下加一条下划线。

    用户定义的图文,一种是通过图文工具新建的一个图文,一种是从外部文件输入的图文。

    从外部文件输入图文,可以用“导入”工具或者使用“链接文件”工具来链接一个文件。

    链接一个文件,只是建立了一个指针,指向要连接的文件,并不将文件的内容输入到图文对象中,所以在每一次运行报表时,都动态地将文件内容输入到图文对象中,因此,图文对象中的内容是动态的,会随着文件内容的改变而改变,采用这种方式,能保证报表的输出总是反映最新的内容,这种方式是在布局模型编辑中通过“链接文件”工具建立的。

    5)     定位

    定位是用于确定报表输出时子对象相对于其父对象的水平和垂直位置。由于在运行报表时,有些布局尺寸会发生变化,所以需要用定位来定义一个对象相对于另一个对象的位置。

    例如,对于一个水平方向大小可变的重复框架,希望它里面的一个域总是位于重复框架水平方向的中间位置,同时又希望该域与重复框架的顶部保持固定距离,由于重复框架是水平方向大小可变的,因此其将来实际输出时的水平尺寸是不可预知的,所以需要定义一个定位来实现以上目的,如下图所示。

    clip_image036

    用定位连接的两个对象之间的相对位置关系是基于数据取出数据之后的对象的实际尺寸,而不是对象在布局模型编辑器中的尺寸。布局模型编辑器中对象间相对位置实际上反映了报表输出对象的位置。

    定位分为两种类型:隐式定位和显示定位。

    隐式定位Oracle Reports会自动地为每个没有显示定位的布局对象生成一个隐式定位,以防止该对象被其他对象覆盖。隐式定位节约了用于定义每个对象的位置的时间。

    在对象导航器中,若采用“对象类型视图”,则看不到隐式定位,但可以看到显示定位。若采用“所有权视图”,则缺省情况下看不到定位的,要想看到定位,须打开“工具”菜单中的“选项”->“导航器”,弹出“对象导航器选择”对话框,在“布局”栏中选中“定位信息”,则会在导航器中显示所有的定位信息,包括隐式定位和显示定位。

    但隐式定位在布局模型编辑器中总是不可见的。

    显示定位,显示定位是在布局模型编辑器中通过“定位”工具建立的,通过显示定位可以强制性地将某些对象放在一起。当一个对象在水平或垂直的大小可能会随着许多记录的增减而改变时,或者在决定一个对象相对于重复框架的相对位置时,显示定位尤其有用。

    1)     设计布局前的参数设置

    点击菜单“工具”->“选项”->“标尺”

    clip_image038

    2)     在数据模型和布局模型的编辑页面中的,可以点击菜单“视图”来选择是否显示标尺,网格等辅助设计的面板,尤其是“工具面板”一定要选择显示。


    3)     最外层固定框的属性“打印对象在”必须设置为“第一页”。

    4)     表头的“打印对象在”必须设置为“全部页”。

    5)     要实现自动分页,必须将最外层的固定框或循环框“打印对象在”设置为“第一页”。

    6)     可以在循环框外面加一个固定框,并将固定框的属性更改为“可变”,固定框的输出会紧接着循环框的位置。

    当运行一个报表时,Oracle Reports会弹出一个窗口,称为参数表。可以在此窗口中输入参数值,从而屏蔽原有的缺省值。

    如果没有建立报表参数表格,在运行时,Oracle Reports将会自动建立一个参数表格以供用户输入参数,但当报表运行完后,这个参数表格的内容就会自动地被删除。

    Oracle Reports提供缺省的参数表格样式,可以采用缺省的参数表格,也可以在缺省参数表格的基础上进行修改,或者建立用户自已定义的参数表格。

    建立缺省的参数表格:

    点击菜单“工具”->“参数表单创建器”


    修改“标题”、“提示行”和“状态行”的内容,它们将显示在运行参数表的顶端;

    根据需要选中要在运行参数表中出现的参数,被选中参数的背景色为黑色,如上图中,参数“P_ORDER_FROM”被选中,则该参数将会出现在运行参数表中,用户可以为它输入新值,而不使用其缺省值。注意,这里未被选中的参数不会出现在缺省的参数表格中。

     

    建立用户自定义的参数表格:

    双击对象导航器中的“页面参数表单”

    clip_image044

    在这里,只能建立两种对象:域对象和图文对象。

    Ø 域对象:域对象是用来放置参数值的地方。如果某一参数没有定义与其相应的域对象,则在运行参数表上不会显示该参数。缺省情况下,Oracle Reports会为每一个参数建立一个域对象。也可以通过使用“报表编辑器-参数表格”中的“域”工具建立一个域,然后将一个已有的系统参数或用户定义参数分配到该域。

    Ø 图文对象:图文对象的作用和在布局模型中的作用一样。缺省情况下,Oracle Reports会生成运行参数表的“标题”、“提示行”和“状态行”图文对象,并为每个域建立一个标签图文对象。也可以通过使用“报表编辑器-参数表格”中的“图文”工具建立额外的图文对象以增强运行参数表的可观性。

    Oracle Reports中,触发器可分为三类:

    Ø 报表触发器:共有5个报表触发器,分别在运行报表的不同阶段被触发。

    Ø 数据模型触发器:包括公式列触发器、组过滤触发器、参数验证触发器。其中,公式列触发器在每次处理列时被触发,组过滤触发器可以由组中的每一条记录触发,参数验证触发器在显示参数表格和用户离开参数域时被触发。

    Ø 布局格式触发器:在处理布局对象时触发。

    1)     报表触发器,是用户在运行报表和设置报表格式时,在指定时刻执行的PL/SQL函数。这些报表触发器允许用户执行以下操作:调整报表格式、执行初始化任务、访问数据库。

    系统定义了五个报表触发器,用户可以修改触发器的内容,但不能创建新的报表触发器。


    Before Parameter Form

    在显示运行参数表之前被触发,即使参数表被隐藏起来不显示,此触发器仍然可以被触发。它用于存取并修改参数值、PL/SQL全局变量和报表组列值。通常利用此触发器来检验命令行参数。

    After Parameter Form

    在显示运行参数表之后触发,即使参数表被隐藏起来不显示,此触发器仍然可以被触发。该触发器用于存取、校验和修改参数值。如果在运行中出现错误,则返回到运行参数表。该触发器不能存取数据模型中的列。

    Before Reoprt

    该触发器在分析查询语法和检索数据之后、运行报表之前被触发,用于执行初始化处理各种参数。

    Between Pages

    除去第一页以外,该触发器在每一页报表被格式化之前被触发,用于页的格式化设置。在预览器中,此触发器只在第一次进入该页时被触发,如果后续再进入该页,则此触发器不再被触发。

    After Report

    该触发器在退出预览器后或将报表输出到目的地(如:文件、打印机或Oracle*Mail用户标识)以后初触发,用于清除对参数的初始化处理,如删除临时表。无论报表是否成功执行,此触发器一直是处于激活状态。

    2)     数据模型触发器

    公式列触发器,是指在公式列中编写一个PL/SQL函数,该列又可以构造其他对象,如占位列或公式列本身。

    公式列中的代码必须返回给公式列,此列可以是一个“虚”列,既在报表的布局模型中不被显示出来。

    例:

    目的:希望当员工工资大于3000时,奖金显示的是工资乘以0.1,否则奖金显示出的是工资乘以0.5,并给出提示。

    实现方法:使用公式列构成两个占位列“BONUS”和“BONUS_CHAR”,根据不同条件给这两个列赋值。

    FUNCTION SET_BONUS RETURN CHAR IS
    BEGIN
    IF :SAL > 3000 THEN
    :BONUS := :SAL * 0.1;
    :BONUS_CHAR := 'ten percent';
    ELSE
    :BONUS := :SAL * 0.1;
    :BONUS_CHAR := 'ten percent';
    END IF;
    RETURN '';
    END;

    由于该公式列是一个虚列,因此函数返回一个空字符串。

    组过滤器,组过滤器用于限制出现在报表中的记录的行数。组过滤器对数据的限制是在检索数据之后,在显示数据之前,所有使用组过滤器并不能减少由查询语句检索出来的数据总量,若想减少由查询语句检索出来的数据,可以在查询语句中使用WHERE子句进行限制。

    Oracle Reports提供了两个组过滤器:前几个(First)和后几个(Last)。用户还可以编写自己的组过滤器。

    组过滤器只能由两个返回值:

    Ø TRUE:表示提取组中指定的数据。

    Ø FALSE:表示不提取组中指定的数据。

    另外,组过滤器不能用于交叉分组。

    验证触发器,用户可以在系统参数和用户自定义的参数中编写验证触发器,用于检测输入到运行参数表中的参数值,如果参数不正确,则停止报表运行。

    验证触发器必须返回一个布尔值(TRUEFALSE)。若返回为FALSE,则光标会停留在参数中,用户可以输入不同的值或则退出报表的运行。

    示例:验证用户输入的订单号范围是否合理

    FUNCTION P_ORDER_TOValidTrigger return boolean IS
    BEGIN
     IF :P_ORDER_TO < :P_ORDER_FROM THEN
       RETURN (FALSE);
     ELSE
      RETURN (TRUE);
     END IF;
    END;

    3)     布局格式触发器

    大多数的布局对象都含有一个布局格式触发器,它是布局对象的一个公共属性。布局格式触发器存在于以下对象中:框架、重复框、域和图文对象。

    布局格式触发器允许用户在报表运行时根据一定条件动态地修改布局对象的显示或隐藏。

    4)     动作触发器

    动作触发器是在预览器中选中一个按钮时执行的PL/SQL过程。该触发器可以动态地调用另一个报表或执行PL/SQL程序。在动作触发器中输入的PL/SQL过程,可参考Oracle Reports中的封装函数、过程和异常处理。

    用户可以将PL/SQL用于Oracle Reports对象中以增加报表功能。

    1)     PL/SQL中引用报表对象

    PL/SQL中引用报表对象有两种方法:

    变量值引用,通过在Oracle Reports对象前加一个“:”号来引用Oracle Reports对象值。

    例如,要使ORDER_NUM列的值为1000,则输入ORDER_NUM= 1000

    变量名引用,通过用单引号括起Oracle Reports对象来引用对象的名称。

    例如,要使变量FIELDNAME等于F_NAME域的名称,FIELDNAME := ‘F_NAME’

    2)     Oracle Reports中的PL/SQL

    Oracle Reports中能使用以下9种方法的PL/SQL结构块:

    PL/SQL程序库(external libraries)、附件的程序库(attached libraries

    程序单元(report program units)、报表触发器(report triggers

    组过滤器(group filters)、公式(formula)、验证触发器(validation triggers

    格式触发器(format triggers)、动作触发器(action triggers


    PL/SQLPL/SQL程序库、程序单元;

    Trigger&Filters:重复框、框架、域、图文、参数、组、报表触发器;

    Formula:公式列;

    Button Triggers:按钮;

    3)     Oracle Reports中的PL/SQL异常处理

    通常有三种类型的异常处理:

    Ø 用户定义的异常处理,具体方法参考PL/SQL技术文档。

    Ø 标准封装的异常处理,是Oracle系统预先定义的例外,同参考PL/SQL技术文档。

    Ø Oracle Reports特有封装的异常处理Oracle Reports特有的例外定义在SRW包中,具体有:

    SRW.CONTEXT_FAILURE     SRW.RUN_REPORT_FAILURE

    SRW.DO_SQL_FAILURESRW.RUN_REPORT_BATCHNO

    SRW.INTEGER_ERROR SRW.TRUNCATED_VALUE

    SRW.MAXROW_INERRSRW.UNKNOW_QUERY

    SRW.MAXROW_UNSETSRW.UNKNOW_USER_EXIT

    SRW.NULL_ARGUMENTS    SRW.USER_EXIT_FAILURE

    SRW.PROGRAM_ABORT

    异常处理的使用规则:

    Ø 如果用户没有处理一个异常,那么Oracle Reports会替用户去处理它,既在异常处理被激活时,Oracle Reports将产生一个错误,终止报表的执行。

    Ø 用户必须在当前PL/SQL域中测试结构块的失败情况。

    例如,如果用户给公式列编写了PL/SQL代码,那么该公式列必须测试它自己的失败情况,其他对象甚至另一个公式列是不能对它的失败进行测试。

    4)     SRW包

    为了方便用户使用,Oracle Reports提供了一个封装的包,称为SRW。它是一组PL/SQL结构块的集合,包含了许多可在库和报表中引用的函数、过程和异常处理。用户可以在库或报表中参考引用它们。

    当用户在PL/SQL结构块中参考SWR包时,必须加上前缀SRW,例如SRW.DO_SQL

    SRW包的用途有:控制报表的运行、在运行时输出信息、初始化域对象、执行DDL语句(建立/删除临时表)、调用用户接口、动态地设置布局对象属性、如字体和填充模式等。

    可以在报表中的任何PL/SQL语句中引用SRW包的任何部分,但是,SRW包中的内容只能在Oracle Reports中被引用,不能在其他工具(如Oracle Forms)中被引用。

    SRW包由下列结构块组成:

    SRW.BREAK         SRW.CONTEXT_FAILURE

    SRW.DO_SQL      SRW.DO_SQL_FAILURE

    SRW.GETERR_RUN       SRW.GET_PAGE_NUM

    SRW.INTEGER_ERROR SRW.MAXROW_INERR

    SRW.MAXROW_UNSETSRW.MESSAGE

    SRW. NULL_ARGUMENTS   SRW.PROGRAM_ABORT

    SRW.REFERENCE         SRW.RUN_REPORT

    SRW.SET_ATTR           SRW.RUN_REPORT_FAILURE

    SRW.RUN_REPORT_BATCHNO     SRW.SET_FIELD_CHAR

    SRW.SET_FIELD_DATE  SRW.SET_FIELD_NUM

    SRW.SET_MAXROW           SRW.TRACE_ADD_OPTION

    SRW.TRACE_END        SRW.TRACE_REM_OPTION

    SRW.TRACE_START            SRW.TRUNCATED_VALUE

    SRW.UNKNOWN_QUERY    SRW.UNKNOWN_USER_EXIT

    SRW.USER_EXIT          SRW.USER_EXIT20

    SRW.USER_EXIT_FAILURE

    1)     程序单元(Program Units)

    程序单元是指从当前报表中的任何PL/SQL库中参考引用的包、函数和过程。程序单元不能被其他程序参考。若想创建一个能被多个程序参考引用的包、函数或过程,需要创建一个PL/SQL程序库。

    clip_image050

    2)     附加的程序库(Attached Libraries)

    对于一些比较通用的函数和过程,或者逻辑比较复杂的函数和过程,我们可以把它们集合在一起写成一个PL/SQL程序库。一个PL/SQL程序库就是一个PLL库文件。

    在报表中,我们可以采用附加的程序库的方式来引用它。对于附加程序库,用户可以在报表中调用它的包、函数和过程。

    Ø 建立PL/SQL程序库

    PL/SQL程序库,即PLL文件,需要在Reports Builder中去建立。

    详细的建立过程如下:

    a)     在对象导航器中选择“PL/SQL库”节点,然后单击工具栏上的“创建”工具,则在“PL/SQL库”节点下会出现一个新的库结点,该节点下有两个子节点:“程序单元”子节点和“附加的库”子节点。

    b)     选中“程序单元”子结点,然后单击工具栏上的“创建”工具,弹出“新建程序单元对话框。

    c)     在对话框中输入过程、函数、包说明或包主体的名称,接受对话框,则弹出“程序单元编辑器”窗口。

    d)     输入PL/SQL过程、函数、包的代码,编译后关闭“程序单元编辑器”窗口。


     e)     点击保存按钮,保存库文件到指定的目录中。


    Ø 连接PL/SQL程序库

    建立好PL/SQL程序库后,库中的所有函数、过程都可以在任何Oracle产品中被引用。但在引用前,须将库连接到引用它的报表上。

    连接步骤如下:

    a)     在对象导航器中选择“附加的库(Attached Libraries)”节点,然后单击工具栏上的“创建”工具,则弹出“附加程序库(Attach library)”对话框。

    b)     先在对话框中输入PL/SQL库的名称,或者点击“浏览”来选择要附加的PL/SQL程序库文件。然后再单击“附加”按钮来连接该PL/SQL程序库。

    c)     系统会提示“附加的程序库的名称包含不可移植的目录设置,要删除此路径吗?”,一般我们会选择“Yes”,这样附加的库文件和路径无关,只要把库文件放在REPORTS60_PATH所指定的路径下系统就可以找到。如果选“No”,则附加的库文件带有绝对路径,库文件的位置不能改变,不利于报表安装。

    将建立好的PL/SQL程序库附加在报表上后,程序库库中的所有函数、过程、包就可以在报表的任何地方被调用。


    展开全文
  • 第三章 创建一个分组报表 1. 建立数据模型 数据模型用于定义一个报表中使用的数据及数据结构,这些数据可以是数据库表中的原始数据,也可以是经过加工后的数据,如工资的总和等。从数据库中检索出的数据是否...

    本文转自:http://blog.csdn.net/deepsea_allen/article/details/53900284

     

    第三章   创建一个分组报表

    1.     建立数据模型

    数据模型用于定义一个报表中使用的数据及数据结构,这些数据可以是数据库表中的原始数据,也可以是经过加工后的数据,如工资的总和等。从数据库中检索出的数据是否在报表输出中显示,也是在数据模型中定义的。

    数据模型由五部分对象组成:查询(Queries)、组(Groups)、列(Columns)、连接(Links)和参数(Parameter)。

    1)     建立查询

    查询实际上就是一条SQL SELECT语句,决定了从数据库中指定的表或视图中取哪些行和列。查询所取得的数据可被用于计算、排序、集合运算等,并可以在报表输出时显示。

    Ø 报表中的查询可分为两种:内部查询和外部查询。两者的区别在于外部查询可以被其他报表多次引用,而内部查询不能被其他报表参考引用,只能被其所属的报表引用。

    Ø 根据报表中查询的个数可以将报表分为单查询报表和多查询报表。

    单查询报表:只有一个查询的报表称为单查询报表。单查询报表的常见格式有列表式(Tabular)、标签式(Mailing Label)、信封式(Form Letter)以及分组式。单查询报表虽然只有一个查询,但可以多次显示查询数据,并且可以用不同的格式显示。

    多查询报表:含有多个查询的报表称为多查询报表。多个查询相互之单可以有关联,称为相关的多查询报表;也可以没有关联,称为不相关的多查询报表。

    l  相关的多查询报表:多个查询之间相互关联,一般用于主从式报表,也就是说,报表的一部分数据决定了报表的另一部分数据。取出前一部分数据的查询称为主查询,取出后一部分的查询称为从查询,主查询的每一条记录查询都将引起从查询的执行,从查询只检索与主查询匹配的那些记录。两个查询之间通过定义数据连接产生联系。

    l  不相关的多查询报表:多个查询之间没有关联,Oracle Reports将独立地为每一个查询获取数据,显示出来的是一系列不相关的数据。

    查询之间运行的先后次序由数据模型中的查询次序决定。在数据模型中,查询次序是先上后下,先左后右,所以放在左上角的查询最先执行。

    示例:为避免数据冗余,我们这里将订单头和行分别建立两个查询:

    a)     在对象管理器中选中报表,右击打开“报表编辑器”,然后点击打开“数据模型”。

     

    b)     点击SQL查询创建两个查询。

     

    c)     修改Q1->Q_header,G_order_number->G_header;

        Q2->Q_line,G_line_num->G_line

    2)     建立数据连接

    数据连接用于建立两个查询数据之间的关系。在数据模型编辑器中,两个查询之间的连线即表示了一个数据连接。

    工作原理:数据连接通过主键和外部键定义了两个查询之间的主/从关系。主/从关系中父查询的每一条记录的产生都会引起子查询的执行,子查询只检索满足在连接中指定的条件的记录。

    通常情况下,两个查询之间的连接是等值连接,但也可以采用SQL语句(如WHERE、HAVING、START WITH等)建立非等值连接。

    当一个带有数据连接的报表执行时,该数据连接就被转换成一个SQL子句,并添加到子查询的后面。子查询根据父查询的主链值执行查询。

    建立方法:一种是手动建立的数据连接,一种是自动建立的数据连接。

    手动连接的步骤:在数据模型编辑器中选择:“数据连接”小图标;

    单击父查询的主链列或外部键列,并拖动鼠标到子查询的主链或外部键列,使它们之间建立一条连线。注意,连线总是从父查询到子查询的;

    自动连接的步骤:在数据模型编辑器中选择:“数据连接”小图标;

    单击父查询,并拖动鼠标到子查询上,系统会自动显示父查询和子查询之间是依据哪个列建立连接的;

           示例:点击数据连接,创建从Q_header (header_id)到Q_line(header_id1)的数据连接。

     

    3)     建立组

    组对象主要有两个功能:

    Ø 将一个查询的数据分成几个集合,每个集合称为组。例如,将“EMP”表按“DEPTNO”分组,结果显示如下:

     

    Ø 过滤查询数据,通过组可以对查询的结果进行过滤。

    在Oracle Reports中将组分为缺省组和用户定义组两类:

    Ø 在缺省的情况下,Oracle Reports为数据模型中的每一个查询产生一个组,取名取成查询的名称。查询名称以“Q_”开头,而组名以“G_”开头。例如,查询名称为“Q_header”,则Oracle Reports为其产生的缺省组名为“Q_header”。

    Ø 用户定义组可用于以下三种情况:分组报表;矩阵报表;子汇总。

    组过滤器允许有条件的选择由查询检索出来的数据,通过组过滤器过滤查询结果。

    有两种类型的组过滤器:Oracle Reports封装过滤器和用户定义过滤器。

    Ø Oracle Reports封装过滤器允许指定在一个组中希望检索的记录数,在报表开发过程中可以使用封装过滤器来限制数据。Oracle Reports软件包中有两个封装过滤器:First Filter,只显示组内前n条记录;Last Filter,只显示组内后n条记录。

    Ø 用户定义过滤器:用户可以定义自己的过滤器来限制在特定条件下的记录的检索。用户定义的过滤器是通过编写PL/SQL代码建立的。

     

    数据模型中组的层次决定了在缺省布局对话框中组的次序,同时也决定了在缺省布局中组的次序,但这不是最终的报表格式,因为可以对缺省的显示格式进行修改。

    在数据模型编辑器中若没有数据连接,则组的层次是由组在数据模型编辑器中的位置从左至右,从上至下决定的。在数据模型编辑器中若有数据连接,则组的层次可以由数据连接描述。通过对象导航器可以清晰地看到组的层次:

     

    4)     定义列

    报表的列表示报表的数据。在定义了从数据库检索数据的查询后,可能需要进一步调整报表,增加更多的列,而这些列可以用作报表的数据,执行总计汇总等功能。

    Oracle Reports中的列可以分为两类,缺省列和用户定义列。

    Ø 缺省列

    Oracle Reports为查询SELECT语句中的每一项都建立一个列,因为它们直接对应从数据库中检索出来的各个列,所以缺省列也叫数据库列。

    Oracle Reports除了支持典型的数据类型的列(如字符型、数值型、日期型)以外,还支持图型列。图型列的值可能是:

    直接存储在数据库中的图型:这种列的数据类型通常是RAW或LONG RAW。在这种情况下,需在列的属性选项板中指明图形格式。

    文件名或者是图型的URL:这种列的数据类型通常是REF,列中的值对应于用指针指向一个存在操作系统中的文件,报表输出时会根据指针将文件内容输出,在这种情况下,需在列的属性选项板中将“Read from File”设置为“Yes”并输入文件名。文件名前可以带有路径,若文件名前没有带有路径,则Oracle Reports会按照其路径搜索顺序查找文件。可以通过Report Builder的环境变量REPORT30_PATH来设置搜索路径。注意,若列的属性选项板中“Read from File”被置为“No”并且输入了文件名,则报表最后输出的只会是文件名,而不会是文件内容。

    Oracle Reports支持多种图形格式,包括BMP、CALS、CGM、GIF、JFIF、PCD、PCX、PICT、RAS、TIFF等。

    Ø 用户定义列

    用户可在特定的组内或报表一级建立列。在特定的组内建立的列称为组一级的列,该列与组内的其他列有相同的显示频度。而报表一级的列只在整个报表中显示一次。用户定义列分为三种类型:公式列、占位列和汇总列。

    a)     公式列,公式列是对其他列执行一个用户定义的计算。建立公式列的方法是用PL/SQL语句写一个函数,从一个或多个列中计算结果,该列的缺省名为“CF_n”。

    示例:在G_line组中定义一个的公式列newAmount,来显示Amount *1.06的值。

    在数据模型编辑器中单击:“公式列”小图标。如果要在组中建一个公式列,则在画布的组区域内单击一下鼠标左键,如果要建一个报表一级的公式列,则在画布的空白区域内单击一下鼠标左键,会生成一个公式列对象;

     

     

    双击该公式列对象,弹出其属性选项板;

    点击属性选项板中的“PL/SQL公式”项,弹出“程序单元编辑器”;

     

     

    在“程序单元编辑器”中为公式项用PL/SQL语句书写一个计算公式并编译通过。

     

     

    b)     占位列,占位列的值和数据类型是通过PL/SQL语句设置的,该列的缺省名为“CP_n”。当需要有选择地设置一个列的值时(例如,在每次出现第n个记录时,或每次出现包含有特殊值的记录时)占位列非常有用。

    可以在以下几个地方设置占位列的值:

    在Before Reports的报表触发器中(如果占位列是一个报表级的列);

    在报表级的公式列中(如果占位列是一个报表级的列);

    在占位列组或占位列组下面的公式中(为组中的每一条记录设一次值)。

    占位列的用途:

    在公式列的PL/SQL代码中计算出的一些值可以分配给不同的占位列;

    利用占位列保存中间值。例如,存储当前检索出的最高工资对应的记录。

    c)     汇总列,汇总列是对其他列的数据执行计算。Oracle Reports为汇总列提供的计算函数有:总和、平均值、最小值、最大值、计数、第一个、最后一个、%(总计)、标准差、方差。

    示例:在G_header组中添加CS_countAmount,来计算订单行的总金额;

             在Report级别添加CS_total,来计算订单的总数量;

    在数据模型编辑器中单击“汇总列”小图标,如果要在组中建立一个汇总列,则在组中你希望该列所在的位置上单击一下鼠标左键,如果要建一个报表一级的汇总列,则在画布的空白区域内单击一下鼠标左键,会生成一个汇总列;

     

    双击该汇总列对象,弹出其属性选项板;

    从属性选项板中的“汇总”项下的“功能”子项的下拉列表中选择所需的计算公式;在“源”子项中选择要汇总的列名;

    在“重设于”子项中选择汇总的频度,即是就整个报表做一次汇总还是每一页做一次汇总,或者每一组做一次汇总;

    当“功能”子项被选为“%(总计)”时,“计算于”项有用,其值为计算“%(总计)”的汇总列时的组名。该项只对“%(总计)”有用。

     

    5)     参数

    参数是报表变量,在报表运行过程中,用户可以为其指定不同的值。参数主要用于在运行过程中修改SELECT语句和设置PL/SQL变量。Oracle Reports中的参数分为两类:系统参数和用户参数。

    Ø 系统参数

    系统参数又称缺省参数。Oracle Reports允许为每一个报表修改标准的运行设置,系统参数共有7个。

     

    系统参数

    功能

    取值

    省缺值

    COPIES

    报表输出到打印机的份数

    任何整数

    1

    DESFORMAT

    输出设备的格式,如:打印机

    Dflt、Pslan80

    Dflt

    DESNAME

    输出设备的名字,如:文件名、打印机名

     

     

    DESTYPE

    输出结果送到什么地方,如屏幕、文件、邮件、打印机等

    File、Mail、Screen、Printer

    Screen

    MODE

    报表运行的模式,如:字符界面、图形界面等

    Bitmap、Character

    Default

    ORIENTATION

    打印报表输出时的打印方向,如:Landscape、Portrait

    Landscape、Portrait

    Landscape、Portrait

    PRINTJOB

    当运行一个报表时是否显示“PRINT JOB”对话框

    YES、NO

    YES

    Ø 用户参数

    用户参数是用户建立的一个对象,该对象用于保存在运行时用户可以改变的值。在一个查询的任何地方都可以引用用户的参数,用户参数主要用于以下几个方面:

    l  在SELECT语名的WHERE子句中用参数替代常数作限制值。

    l  用参数替代SELECT语句的任何部分,包括选择列、表,甚至整个SELECT语句。

    l  在SELECT列表中用参数替换一个单列或一个表达式。

    引用参数的方法主要有两种:连接引用和置换引用。

    a)     连接引用

    连接引用主要用于替换SQL语句和PL/SQL块中的一个值或表达式。

    使用连接引用的方法是在要引用的参数前加上“:”号。

    连接引用的使用受以下限制:不能在SELECT语句中替换列名;不能在FROM从句中使用连接引用;不能替代保留的单词和子句。

             示例:将查询Q_header的where条件中写死的条件:

             oh.order_numberbetween 29480and29485

    修改为:oh.order_numberbetween:p_order_fromand:p_order_to

             保存修改后,Oracle Report会自动加入这两个用户参数。

     

    b)     置换引用

    置换引用可以用参数替代SELECT语句的任何部分,如替换列名、FROM子句、WHERE子句、GROUP BY子句、ORDER BY子句、HAVING子句、CONNECT BY子句、START WITH子句等。

    使用置换引用的方法是在要引用的参数前加上“&”符号。

    注意:不能在PL/SQL中使用置换引用,但可以在PL/SQL中使用连接引用。

    和连接引用不同的是,对于置换引用的参数,用户必须事先在对象导航器中建立,并且在属性选项板中为其输入初始化值,Oracle Reports不会缺省地建立该参数。

    举例:使用置换引用替代列名和FROM子句。

    SELECT &P_ENAME NAME, &P_EMPNO ENO

    FROM &P_EMP;

    这样可以动态地根据运行时输入的参数值,决定从哪个表检索那些列。

    使用置换引用替换WHERE子句

    SELECT * FROM EMP &P_WHERE;

    在运行时可任意指定WHERE子句,根据不同的限制条件检索所需数据。

    值列表,为参数值建立值列表,这样,在运行时用户就可以从该值列表中选择一个有效值。可以限制用户只能选择值列表中的值,也可以允许用户输入其他的值。

    对于连接引用的参数,值列表可以是一个不能修改的静态的值列表,也可以是在运行时从数据库中动态地选择值的动态值列表。

    对于置换引用的参数,值列表只能是静态的。

    2.     设计布局

    布局的功能是定义报表的格式,包括数据文本及图形的位置和显示格式。

    在布局模型编辑器中将报表布局分为三个区域:表头区域、表尾区域和主体区域,每个区域又分为主体和页边距。

    Ø 表头区域 在报表每一页的开头显示一次,表头区域可以包含文本、图形、数据及其运算。

    Ø 表尾区域 在报表每一页的结尾处显示一次,表尾区域可以包含文本、图形、数据及运算。

    Ø 主体区域 出现在表头和表尾之间,是报表的主要部分。当第一次进入一个新报表的布局模型编辑窗口时,所处的位置就对应着报表的主体区域。主体区域包含报表的主要文本、图形、数据及其运算。

    基本布局对象:

    在布局模型编辑器中,是通过定义和修改布局对象来实现的,Oracle Reports中的基本布局对象有框架(Frames)、重复框架(Repeating Frames)、域(Fields)、图文(Boilerplate)、定位(Anchors)、按钮(Buttons)、OLE2对象、Oracle Graphics对象。

    1)     框架

    框架用来围绕其它布局对象。一个框架可以包含任何布局对象,包括其它的框架。框架的打印次数与它所围绕的对象的打印次数一样,框架与记录无关。

    框架的主要用途:

    l  把对象组织在一起,以保证在打印时它们之间的相对位置;

    l  避免覆盖其他对象和被其他对象覆盖;

    l  将报表划分为几个部分。例如,在每一页的顶部采用列表式的报表格式,而在底部采用钜阵式的报表格式;

    l  确保一些对象总是在相同的页中。

    框架分为两种类型:缺省框架和用户定义框架。

    缺省框架,当接受缺省的布局模型时,Oracle Reports会自动生成包含对象的框架。缺省框架的命名形式为“M_n”。缺省框架又可分为两种:垂直可变的组框架和固定尺寸的框架。例如,当创建最初缺省的布局模型时,Oracle Reports产生一个围绕整个布局模型的组框架,这个组框架在垂直方向上是可伸缩的。而固定尺寸的框架通常是围绕图文对象(Boilerplate)建立的,例如列的标题。

    用户定义框架,用户定义的框架是在布局模型编辑器中通过“框架”工具建立的。

    框架的重要属性:

    l  在这之前分页(Page Break Before):指示在打印该对象前进行换页。

    l  在这之后分页(Page Break After):指示在打印完该对象后进行换页,在其后面的对象都将移到下一页打印。

    l  页保护(Page Protect):指示对象内的所有对象尽可能地打印在一个页内,如果一个页容纳不下的话,在开始打印该对象时会先换页。

    l  垂直缩放值(Vertical Elasticity):指示对象的垂直大小是否可以改变,有:收缩、扩展、固定、可变。

    l  水平缩放值(Horizontal Elasticity):指示对象的水平大小是否可以改变,有:收缩、扩展、固定、可变。

    l  打印对象在(Print Object On):指示对象在报表的打印频率,有:全部页、除首页外的全部、除尾页外的全部、缺省、第一页、最后一页。

    l  基于以下环境打印(Base Print On):指示对象是以定位对象还是以包含对象为基准进行打印。

    l  跟随定位对象(Keep With Anthoring Object):指示对象是否跟随定位对象打印在同一个逻辑页中。

    2)     重复框架

    重复框架主要用于显示由一个组检索出来的多行数据的对象。一个重复框架可以包含任何布局对象,也可以包括其它的重复框架。重复框架是与记录相关的,它为一个组的每一条记录及其所关联的数据模型对象都打印一次。使用重复框架可以控制记录层的显示和格式,比如:记录的打印方向、记录的空隙、边框线、颜色、字体等。重复框架的箭头方向指明了重复框架重复的方向。

    嵌套的重复框架常常用于建立主/从表和分组表。

    重复框架分为两种类型,缺省的重复框架和用户定义的重复框架。

    缺省的重复框架,当接受缺省的布局模型时,Oracle Reports会自动地为数据模型中的每一个组生成一个重复框架,并且为组中的每一列都对应安排一个域,放在重复框架内。

    用户定义的重复框架,用户定义的重复框架是在布局模型编辑器中通过“重复框架”工具建立的。

    重复框架的几个重要属性:

    l  源(Source):每一个重复框架必须有一个源(组)作为其数据来源,在重复框架中每一条源数据显示一次;

    l  打印方向(Print Drection):重复框架中记录的打印方向,有:横向、纵向、横向/纵向、纵向/横向;

    l  每页的最大记录数(Maximum Record per Page):在逻辑页上显示的重复框架记录的最大数目,可以通过该属性改善报表的可看性。例如,希望在每个逻辑页上只显示三条记录,则将该属性设置为3。该属性的取值可以为正整数和空,若为空,则尽可能在一个逻辑页上显示最大数目的记录。

    l  最小孤立记录数(Minimum Widow Records):必须在一张逻辑页上显示的最少记录数。若从逻辑页的指定位置开始放不下此属性中给出的记录数,则将从下一张逻辑页开始显示。。例如下图,有两个独立的重复框架按纵向打印,第二个重复框架位于第一页的底部,但第一页上仅有打印两条记录的空间了,为了使报表看起来更美观,我们希望第二个重复框架换记录能从第二页开始打印,这时就需要将“最小孤立记录数”设置为3。

     

    l  列模式(Column Mode):用于控制如何为重复框架中的记录提取数据和格式化数据。这个属性有两个选项:“是”和“否”。若选“是”,则允许在上一个重复框架的记录没有打完之前就打印下一个重复框架的记录。例如,若设置“列模式”为是,则虽然记录2直到第二页才打完,但记录3却可以开始在第一页上打印了。若设置:“列模式”为“否”,则记录3只能等到记录2打印完后,才开始在第二页上打印。

     

    l  水平框架间隔:重复框架记录间的水平间隔。当打印方向为“纵向”或“纵向/横向”时,该属性的设置无效。

    l  垂直框架间隔:重复框架记录间的垂直距离。当打印方向为“横向”或“横向/纵向”时,该属性的设置无效。

    3)     

    域是用来放置参数、列、页号、当前日期等值的地方。例如一个参数或列没有对应的域,那么它的值不会在报表输出时显示。当生成一个缺省布局模型时,Oracle Reports会自动地为每一个列建立一个域,并将这些域排放在重复框架中。

    域有两种类型:缺省域和用户定义域。

    缺省域,当接爱缺省的布局模型时,Oracle Reports会自动地为每一列产生一个域,并将这些域排放在重复框架中。每一个域的属性都是缺省生成的,但是可以修改。

    用户定义域,用户可以根据需要定义一些域来显示诸如页号、日期等信息。

    用户定义的域是在布局模型编辑器中通过“域”工具建立的。

    域的数据来源有三种:数据模型的中的一个列或参数、系统变量和系统参数。

    系统变量包括:当前日期(&current date)、页码(&logical page number)、面板数值(&panel number)、物理页码(&physucal page number)、总记页(&total logical pages)、总记面版(&total panel)、总计物理页(&total physical pages)

    域的属性:

    l  源(Source):域值的来源。

    l  源数据来源(Source Data Type):源的数据类型,此属性为只读。

    l  可视的(Visible):若设置为“否”,则表示该域不被格式化。这一属性公用于那些在图文对象中引用的域,通常用于格式信件式报表。若想引用一个“可视的”属性设置为“否”的域,可以在图文对象中输入“&fieldname”。

    l  格式掩码(Format Mask):定义以何种格式显示在域中的日期和数值。有值列表可供选择,但是字符型的域没有该属性。

    l  编页码(Page Numbering):当域的源列是页码、物理页码、总记页、总记物理页之一时,可以使用该属性来定义如何计算页号。点击:编页码按钮,出现“编页码”对话框。

    4)     图文

    图文是一个查询获取不到但又要在报表中输出的对象,如文本、线条、图形等。可以使用图文对象来改变报表的外观,例如建立报表的页头、增加图形等。

    图文有两种类型:缺省的图文和用户定义的图文。

    缺省的图文,当接受缺省的布局模型时,Oracle Reports会自动地为每个域生成一个列标题。对于某些报表类型,Oracle Reports会在列标题下加一条下划线。

    用户定义的图文,一种是通过图文工具新建的一个图文,一种是从外部文件输入的图文。

    从外部文件输入图文,可以用“导入”工具或者使用“链接文件”工具来链接一个文件。

    链接一个文件,只是建立了一个指针,指向要连接的文件,并不将文件的内容输入到图文对象中,所以在每一次运行报表时,都动态地将文件内容输入到图文对象中,因此,图文对象中的内容是动态的,会随着文件内容的改变而改变,采用这种方式,能保证报表的输出总是反映最新的内容,这种方式是在布局模型编辑中通过“链接文件”工具建立的。

    5)     定位

    定位是用于确定报表输出时子对象相对于其父对象的水平和垂直位置。由于在运行报表时,有些布局尺寸会发生变化,所以需要用定位来定义一个对象相对于另一个对象的位置。

    例如,对于一个水平方向大小可变的重复框架,希望它里面的一个域总是位于重复框架水平方向的中间位置,同时又希望该域与重复框架的顶部保持固定距离,由于重复框架是水平方向大小可变的,因此其将来实际输出时的水平尺寸是不可预知的,所以需要定义一个定位来实现以上目的,如下图所示。

     

    用定位连接的两个对象之间的相对位置关系是基于数据取出数据之后的对象的实际尺寸,而不是对象在布局模型编辑器中的尺寸。布局模型编辑器中对象间相对位置实际上反映了报表输出对象的位置。

    定位分为两种类型:隐式定位和显示定位。

    隐式定位,Oracle Reports会自动地为每个没有显示定位的布局对象生成一个隐式定位,以防止该对象被其他对象覆盖。隐式定位节约了用于定义每个对象的位置的时间。

    在对象导航器中,若采用“对象类型视图”,则看不到隐式定位,但可以看到显示定位。若采用“所有权视图”,则缺省情况下看不到定位的,要想看到定位,须打开“工具”菜单中的“选项”->“导航器”,弹出“对象导航器选择”对话框,在“布局”栏中选中“定位信息”,则会在导航器中显示所有的定位信息,包括隐式定位和显示定位。

    但隐式定位在布局模型编辑器中总是不可见的。

    显示定位,显示定位是在布局模型编辑器中通过“定位”工具建立的,通过显示定位可以强制性地将某些对象放在一起。当一个对象在水平或垂直的大小可能会随着许多记录的增减而改变时,或者在决定一个对象相对于重复框架的相对位置时,显示定位尤其有用。

    3.     设计报表布局的注意事项

    1)     设计布局前的参数设置

    点击菜单“工具”->“选项”->“标尺”

     

    2)     在数据模型和布局模型的编辑页面中的,可以点击菜单“视图”来选择是否显示标尺,网格等辅助设计的面板,尤其是“工具面板”一定要选择显示。

     

    3)     最外层固定框的属性“打印对象在”必须设置为“第一页”。

    4)     表头的“打印对象在”必须设置为“全部页”。

    5)     要实现自动分页,必须将最外层的固定框或循环框“打印对象在”设置为“第一页”。

    6)     可以在循环框外面加一个固定框,并将固定框的属性更改为“可变”,固定框的输出会紧接着循环框的位置。

    4.     参数表格

    当运行一个报表时,Oracle Reports会弹出一个窗口,称为参数表。可以在此窗口中输入参数值,从而屏蔽原有的缺省值。

    如果没有建立报表参数表格,在运行时,Oracle Reports将会自动建立一个参数表格以供用户输入参数,但当报表运行完后,这个参数表格的内容就会自动地被删除。

    Oracle Reports提供缺省的参数表格样式,可以采用缺省的参数表格,也可以在缺省参数表格的基础上进行修改,或者建立用户自已定义的参数表格。

    建立缺省的参数表格:

    点击菜单“工具”->“参数表单创建器”

     

    修改“标题”、“提示行”和“状态行”的内容,它们将显示在运行参数表的顶端;

    根据需要选中要在运行参数表中出现的参数,被选中参数的背景色为黑色,如上图中,参数“P_ORDER_FROM”被选中,则该参数将会出现在运行参数表中,用户可以为它输入新值,而不使用其缺省值。注意,这里未被选中的参数不会出现在缺省的参数表格中。

     

    建立用户自定义的参数表格:

    双击对象导航器中的“页面参数表单”

     

    在这里,只能建立两种对象:域对象和图文对象。

    Ø 域对象:域对象是用来放置参数值的地方。如果某一参数没有定义与其相应的域对象,则在运行参数表上不会显示该参数。缺省情况下,Oracle Reports会为每一个参数建立一个域对象。也可以通过使用“报表编辑器-参数表格”中的“域”工具建立一个域,然后将一个已有的系统参数或用户定义参数分配到该域。

    Ø 图文对象:图文对象的作用和在布局模型中的作用一样。缺省情况下,Oracle Reports会生成运行参数表的“标题”、“提示行”和“状态行”图文对象,并为每个域建立一个标签图文对象。也可以通过使用“报表编辑器-参数表格”中的“图文”工具建立额外的图文对象以增强运行参数表的可观性。

    5.     Oracle Reports触发器

    在Oracle Reports中,触发器可分为三类:

    Ø 报表触发器:共有5个报表触发器,分别在运行报表的不同阶段被触发。

    Ø 数据模型触发器:包括公式列触发器、组过滤触发器、参数验证触发器。其中,公式列触发器在每次处理列时被触发,组过滤触发器可以由组中的每一条记录触发,参数验证触发器在显示参数表格和用户离开参数域时被触发。

    Ø 布局格式触发器:在处理布局对象时触发。

    1)     报表触发器,是用户在运行报表和设置报表格式时,在指定时刻执行的PL/SQL函数。这些报表触发器允许用户执行以下操作:调整报表格式、执行初始化任务、访问数据库。

    系统定义了五个报表触发器,用户可以修改触发器的内容,但不能创建新的报表触发器。

     

    Before Parameter Form

    在显示运行参数表之前被触发,即使参数表被隐藏起来不显示,此触发器仍然可以被触发。它用于存取并修改参数值、PL/SQL全局变量和报表组列值。通常利用此触发器来检验命令行参数。

    After Parameter Form

    在显示运行参数表之后触发,即使参数表被隐藏起来不显示,此触发器仍然可以被触发。该触发器用于存取、校验和修改参数值。如果在运行中出现错误,则返回到运行参数表。该触发器不能存取数据模型中的列。

    Before Reoprt

    该触发器在分析查询语法和检索数据之后、运行报表之前被触发,用于执行初始化处理各种参数。

    Between Pages

    除去第一页以外,该触发器在每一页报表被格式化之前被触发,用于页的格式化设置。在预览器中,此触发器只在第一次进入该页时被触发,如果后续再进入该页,则此触发器不再被触发。

    After Report

    该触发器在退出预览器后或将报表输出到目的地(如:文件、打印机或Oracle*Mail用户标识)以后初触发,用于清除对参数的初始化处理,如删除临时表。无论报表是否成功执行,此触发器一直是处于激活状态。

    2)     数据模型触发器

    公式列触发器,是指在公式列中编写一个PL/SQL函数,该列又可以构造其他对象,如占位列或公式列本身。

    公式列中的代码必须返回给公式列,此列可以是一个“虚”列,既在报表的布局模型中不被显示出来。

    例:

    目的:希望当员工工资大于3000时,奖金显示的是工资乘以0.1,否则奖金显示出的是工资乘以0.5,并给出提示。

    实现方法:使用公式列构成两个占位列“BONUS”和“BONUS_CHAR”,根据不同条件给这两个列赋值。

     

    1. FUNCTION SET_BONUS RETURN CHAR IS  
    2. BEGIN  
    3. IF :SAL > 3000 THEN  
    4. :BONUS := :SAL * 0.1;  
    5. :BONUS_CHAR := 'ten percent';  
    6. ELSE  
    7. :BONUS := :SAL * 0.1;  
    8. :BONUS_CHAR := 'ten percent';  
    9. END IF;  
    10. RETURN '';  
    11. END;  
    FUNCTION SET_BONUS RETURN CHAR IS
    BEGIN
    IF :SAL > 3000 THEN
    :BONUS := :SAL * 0.1;
    :BONUS_CHAR := 'ten percent';
    ELSE
    :BONUS := :SAL * 0.1;
    :BONUS_CHAR := 'ten percent';
    END IF;
    RETURN '';
    END;

    由于该公式列是一个虚列,因此函数返回一个空字符串。

    组过滤器,组过滤器用于限制出现在报表中的记录的行数。组过滤器对数据的限制是在检索数据之后,在显示数据之前,所有使用组过滤器并不能减少由查询语句检索出来的数据总量,若想减少由查询语句检索出来的数据,可以在查询语句中使用WHERE子句进行限制。

    Oracle Reports提供了两个组过滤器:前几个(First)和后几个(Last)。用户还可以编写自己的组过滤器。

    组过滤器只能由两个返回值:

    Ø TRUE:表示提取组中指定的数据。

    Ø FALSE:表示不提取组中指定的数据。

    另外,组过滤器不能用于交叉分组。

    验证触发器,用户可以在系统参数和用户自定义的参数中编写验证触发器,用于检测输入到运行参数表中的参数值,如果参数不正确,则停止报表运行。

    验证触发器必须返回一个布尔值(TRUE或FALSE)。若返回为FALSE,则光标会停留在参数中,用户可以输入不同的值或则退出报表的运行。

    示例:验证用户输入的订单号范围是否合理

     

    1. FUNCTION P_ORDER_TOValidTrigger return boolean IS  
    2. BEGIN  
    3.  IF :P_ORDER_TO < :P_ORDER_FROM THEN  
    4.    RETURN (FALSE);  
    5.  ELSE  
    6.   RETURN (TRUE);  
    7.  END IF;  
    8. END;  
    FUNCTION P_ORDER_TOValidTrigger return boolean IS
    BEGIN
     IF :P_ORDER_TO < :P_ORDER_FROM THEN
       RETURN (FALSE);
     ELSE
      RETURN (TRUE);
     END IF;
    END;

    3)     布局格式触发器

    大多数的布局对象都含有一个布局格式触发器,它是布局对象的一个公共属性。布局格式触发器存在于以下对象中:框架、重复框、域和图文对象。

    布局格式触发器允许用户在报表运行时根据一定条件动态地修改布局对象的显示或隐藏。

    4)     动作触发器

    动作触发器是在预览器中选中一个按钮时执行的PL/SQL过程。该触发器可以动态地调用另一个报表或执行PL/SQL程序。在动作触发器中输入的PL/SQL过程,可参考Oracle Reports中的封装函数、过程和异常处理。

    6.     Oracle Reports中的PL/SQL

    用户可以将PL/SQL用于Oracle Reports对象中以增加报表功能。

    1)     在PL/SQL中引用报表对象

    在PL/SQL中引用报表对象有两种方法:

    变量值引用,通过在Oracle Reports对象前加一个“:”号来引用Oracle Reports对象值。

    例如,要使ORDER_NUM列的值为1000,则输入:ORDER_NUM:=  1000

    变量名引用,通过用单引号括起Oracle Reports对象来引用对象的名称。

    例如,要使变量FIELDNAME等于F_NAME域的名称,FIELDNAME := ‘F_NAME’

    2)     Oracle Reports中的PL/SQL块

    Oracle Reports中能使用以下9种方法的PL/SQL结构块:

    PL/SQL程序库(external libraries)、附件的程序库(attached libraries)

    程序单元(report program units)、报表触发器(report triggers)

    组过滤器(group filters)、公式(formula)、验证触发器(validation triggers)

    格式触发器(format triggers)、动作触发器(action triggers)

     

    PL/SQL:PL/SQL程序库、程序单元;

    Trigger&Filters:重复框、框架、域、图文、参数、组、报表触发器;

    Formula:公式列;

    Button Triggers:按钮;

    3)     Oracle Reports中的PL/SQL异常处理

    通常有三种类型的异常处理:

    Ø 用户定义的异常处理,具体方法参考PL/SQL技术文档。

    Ø 标准封装的异常处理,是Oracle系统预先定义的例外,同参考PL/SQL技术文档。

    Ø Oracle Reports特有封装的异常处理,Oracle Reports特有的例外定义在SRW包中,具体有:

    SRW.CONTEXT_FAILURE     SRW.RUN_REPORT_FAILURE

    SRW.DO_SQL_FAILURESRW.RUN_REPORT_BATCHNO

    SRW.INTEGER_ERROR SRW.TRUNCATED_VALUE

    SRW.MAXROW_INERRSRW.UNKNOW_QUERY

    SRW.MAXROW_UNSETSRW.UNKNOW_USER_EXIT

    SRW.NULL_ARGUMENTS    SRW.USER_EXIT_FAILURE

    SRW.PROGRAM_ABORT

    异常处理的使用规则:

    Ø 如果用户没有处理一个异常,那么Oracle Reports会替用户去处理它,既在异常处理被激活时,Oracle Reports将产生一个错误,终止报表的执行。

    Ø 用户必须在当前PL/SQL域中测试结构块的失败情况。

    例如,如果用户给公式列编写了PL/SQL代码,那么该公式列必须测试它自己的失败情况,其他对象甚至另一个公式列是不能对它的失败进行测试。

    4)     SRW包

    为了方便用户使用,Oracle Reports提供了一个封装的包,称为SRW。它是一组PL/SQL结构块的集合,包含了许多可在库和报表中引用的函数、过程和异常处理。用户可以在库或报表中参考引用它们。

    当用户在PL/SQL结构块中参考SWR包时,必须加上前缀SRW,例如SRW.DO_SQL。

    SRW包的用途有:控制报表的运行、在运行时输出信息、初始化域对象、执行DDL语句(建立/删除临时表)、调用用户接口、动态地设置布局对象属性、如字体和填充模式等。

    可以在报表中的任何PL/SQL语句中引用SRW包的任何部分,但是,SRW包中的内容只能在Oracle Reports中被引用,不能在其他工具(如Oracle Forms)中被引用。

    SRW包由下列结构块组成:

    SRW.BREAK         SRW.CONTEXT_FAILURE

    SRW.DO_SQL      SRW.DO_SQL_FAILURE

    SRW.GETERR_RUN       SRW.GET_PAGE_NUM

    SRW.INTEGER_ERROR SRW.MAXROW_INERR

    SRW.MAXROW_UNSETSRW.MESSAGE

    SRW. NULL_ARGUMENTS   SRW.PROGRAM_ABORT

    SRW.REFERENCE         SRW.RUN_REPORT

    SRW.SET_ATTR           SRW.RUN_REPORT_FAILURE

    SRW.RUN_REPORT_BATCHNO     SRW.SET_FIELD_CHAR

    SRW.SET_FIELD_DATE  SRW.SET_FIELD_NUM

    SRW.SET_MAXROW           SRW.TRACE_ADD_OPTION

    SRW.TRACE_END        SRW.TRACE_REM_OPTION

    SRW.TRACE_START            SRW.TRUNCATED_VALUE

    SRW.UNKNOWN_QUERY    SRW.UNKNOWN_USER_EXIT

    SRW.USER_EXIT          SRW.USER_EXIT20

    SRW.USER_EXIT_FAILURE

    7.     程序单元和附加的程序库

    1)     程序单元(Program Units)

    程序单元是指从当前报表中的任何PL/SQL库中参考引用的包、函数和过程。程序单元不能被其他程序参考。若想创建一个能被多个程序参考引用的包、函数或过程,需要创建一个PL/SQL程序库。

     

    2)     附加的程序库(Attached Libraries)

    对于一些比较通用的函数和过程,或者逻辑比较复杂的函数和过程,我们可以把它们集合在一起写成一个PL/SQL程序库。一个PL/SQL程序库就是一个PLL库文件。

    在报表中,我们可以采用附加的程序库的方式来引用它。对于附加程序库,用户可以在报表中调用它的包、函数和过程。

    Ø 建立PL/SQL程序库

    PL/SQL程序库,即PLL文件,需要在Reports Builder中去建立。

    详细的建立过程如下:

    a)     在对象导航器中选择“PL/SQL库”节点,然后单击工具栏上的“创建”工具,则在“PL/SQL库”节点下会出现一个新的库结点,该节点下有两个子节点:“程序单元”子节点和“附加的库”子节点。

    b)     选中“程序单元”子结点,然后单击工具栏上的“创建”工具,弹出“新建程序单元对话框。

    c)     在对话框中输入过程、函数、包说明或包主体的名称,接受对话框,则弹出“程序单元编辑器”窗口。

    d)     输入PL/SQL过程、函数、包的代码,编译后关闭“程序单元编辑器”窗口。

     

     e)     点击保存按钮,保存库文件到指定的目录中。

     

    Ø 连接PL/SQL程序库

    建立好PL/SQL程序库后,库中的所有函数、过程都可以在任何Oracle产品中被引用。但在引用前,须将库连接到引用它的报表上。

    连接步骤如下:

    a)     在对象导航器中选择“附加的库(Attached Libraries)”节点,然后单击工具栏上的“创建”工具,则弹出“附加程序库(Attach library)”对话框。

    b)     先在对话框中输入PL/SQL库的名称,或者点击“浏览”来选择要附加的PL/SQL程序库文件。然后再单击“附加”按钮来连接该PL/SQL程序库。

    c)     系统会提示“附加的程序库的名称包含不可移植的目录设置,要删除此路径吗?”,一般我们会选择“Yes”,这样附加的库文件和路径无关,只要把库文件放在REPORTS60_PATH所指定的路径下系统就可以找到。如果选“No”,则附加的库文件带有绝对路径,库文件的位置不能改变,不利于报表安装。

    将建立好的PL/SQL程序库附加在报表上后,程序库库中的所有函数、过程、包就可以在报表的任何地方被调用。

     

    展开全文
  • 题目要求 解题思路 1.一共涉及了5个类,父类是Employee,父类中有个属性定义的是...3.测试中的逻辑要清楚,如,这个地方父类是一个abstract类,不能造对象,但这里只是创建一个Employee类型的数组名字叫p,不

    题目要求

    解题思路

    1.一共涉及了5个类,父类是Employee,父类中有个属性定义的是MyDate类的对象,存储的是生日信息。两个子类HourlyEmployee、SalariedEmployee代表两种不同类型的员工。

    最后一个是测试类PayrollSystem

    2.值得讲一下的地方,是测试类中使用了Calendar类,获取当前时间,以后我们还将提到

    3.测试中的逻辑要清楚,如,这个地方父类是一个abstract类,不能造对象,但这里只是创建了一个Employee类型的数组名字叫p,不是造对象,

    栈里有个emps,指向了堆空间的Employee数组,我们需要给数组再写入对象的时候就需要是子类了,如:

    这里在SalariedEmolyee这个子类的构造器里new了MyDate对象并调用构造器还是第一次见。。。。

     

    具体实现

    父类Employee

    package com.atguigu.exer;
    /*
     * 编写工资系统,实现不同类型员工(多态)的按月发放工资。
     * 如果当月出现某个Employee对象的生日,则将该雇员的工资增加100元。
     * 
     */
    abstract public class Employee {
    	private String name;
    	private int number;
    	private MyDate birthday;
    	
    	public Employee() {
    	}
    	
    
    
    	public Employee(String name, int number, MyDate birthday) {
    		super();
    		this.name = name;
    		this.number = number;
    		this.birthday = birthday;
    	}
    
    
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getNumber() {
    		return number;
    	}
    
    	public void setNumber(int number) {
    		this.number = number;
    	}
    
    	public MyDate getBirthday() {
    		return birthday;
    	}
    
    	public void setBirthday(MyDate birthday) {
    		this.birthday = birthday;
    	}
    	
    	//抽象方法
    	public abstract double earning();
    	
    	public String toString() {
    		return("name:" + name + ",number:" + number + ",birthday: " + birthday.toDateString());
    	}
    }
    

    MyDate类

    package com.atguigu.exer;
    /*
     * MyDate类包含:
     * private成员变量year,month,day ; 
     * toDateString()方法返回日期对应的字符串:xxxx年xx月xx日
     * 
     */
    public class MyDate {
    	private int year;
    	private int month; 
    	private int day;
    	
    	public MyDate() {
    		
    	}
    	//构造器 似乎没用啊
    		public MyDate(int year, int month, int day) {
    		super();
    		this.year = year;
    		this.month = month;
    		this.day = day;
    	}
    	
    	public int getYear() {
    			return year;
    		}
    
    		public void setYear(int year) {
    			this.year = year;
    		}
    
    		public int getMonth() {
    			return month;
    		}
    
    		public void setMonth(int month) {
    			this.month = month;
    		}
    
    		public int getDay() {
    			return day;
    		}
    
    		public void setDay(int day) {
    			this.day = day;
    		}
    
    	public String toDateString() {
    		return(year + "年" + month + "月" + day + "日");
    	}
    
    
    }
    

    两个子类:

    package com.atguigu.exer;
    /*
     * (3)定义SalariedEmployee类继承Employee类,
     * 实现按月计算工资的员工处理。
     * 该类包括:private成员变量monthlySalary; 
     * 实现父类的抽象方法earnings(),该方法返回monthlySalary值;
     * toString()方法输出员工类型信息及员工的name,number,birthday。 //其实父类已经写过了
     * 
     * 
     */
    public class SalariedEmployee extends Employee{
    	private double monthlySalary;
    	
    	public double getMonthlySalary() {
    		return monthlySalary;
    	}
    
    
    	public void setMonthlySalary(double monthlySalary) {
    		this.monthlySalary = monthlySalary;
    	}
    
    
    	public SalariedEmployee(String name, int number, MyDate birthday) {
    		super(name,number,birthday);
    	}
    
    	public SalariedEmployee(String name, int number, MyDate birthday, double monthlySalary) {
    		super(name,number,birthday);
    		this.monthlySalary = monthlySalary;
    	}
    
    	//重写父类方法
    	@Override
    	public double earning() {
    		return(monthlySalary);
    	}
    
    	public String toString() {
    		//super.toString 是抽象父类的非抽象方法,是可以使用的,而且只能子类使用
    		return "SalariedEmployee[" + super.toString() + "]";
    	}
    
    }
    

     

    package com.atguigu.exer;
    /*
     * 参照SalariedEmployee类定义HourlyEmployee类,
     * 实现按小时计算工资的员工处理。该类包括:
     * 		private成员变量wage和hour; 
     * 		实现父类的抽象方法earnings(),该方法返回wage*hour值; 
     * 		toString()方法输出员工类型信息及员工的name,number,birthday。 
     * 
     * 
     */
    public class HourlyEmployee extends Employee{
    	private int wage;	//单位小时的工资
    	private int hour;	//月工作的小时数
    	
    	public HourlyEmployee(String name, int number, MyDate birthday) {
    		super(name,number,birthday);
    	}
    	
    	public HourlyEmployee(String name, int number, MyDate birthday,int wage,int hour) {
    		super(name,number,birthday);
    		this.wage = wage;
    		this.hour = hour;
    	}
    	
    	public int getWage() {
    		return wage;
    	}
    
    	public void setWage(int wage) {
    		this.wage = wage;
    	}
    
    	public int getHour() {
    		return hour;
    	}
    
    	public void setHour(int hour) {
    		this.hour = hour;
    	}
    
    	//重写父类方法
    	@Override
    	public double earning() {
    		return wage * hour;
    	}
    	
    	@Override
    	public String toString() {
    		return "SalariedEmployee[" + super.toString() + "]";
    		
    	}
    }
    

     

    最后是测试类

    package com.atguigu.exer;
    
    import java.util.Calendar;
    import java.util.Scanner;
    
    /*
     * 定义PayrollSystem类,
     * 创建Employee变量数组并初始化,该数组存放各类雇员对象的引用。
     * 利用循环结构遍历数组元素,输出各个对象的类型,name,number,birthday,以及该对象生日。
     * 当键盘输入本月月份值时,如果本 月是某个Employee对象的生日,还要输出增加工资信息。 
     * 
     * 
     */
    public class PayrollSystem {
    	public static void main(String[] args) {
    		//方式1
    //		Scanner scanner = new Scanner(System.in);
    //		System.out.println("输入月份:");
    //		int month = scanner.nextInt();
    		
    		//方式2
    		Calendar calendar = Calendar.getInstance();
    		int month = calendar.get(Calendar.MONTH);	//获取当前月份 一月份是0
    		
    		
    		//栈里有个emps,指向堆空间里的Employee数组,只是创建了Employee类型的数组,不是造对象
    		Employee[] emps = new Employee[2];
    		
    		//关于MyDate这里直接用了构造器,好家伙,我直接好家伙
    		//多态性
    		emps[0] = new SalariedEmployee("马森", 1002, new MyDate(1992,11,28),10000);
    		emps[1] = new HourlyEmployee("潘雨生", 2001, new MyDate(1991,1,6),50,100);
    		
    		for(int i =0;i < emps.length;i++) {
    			System.out.println(emps[i]);
    			System.out.println("月工资为:" + emps[i].earning());
    			
    			if(month+1 == emps[i].getBirthday().getMonth()) {
    				System.out.println("生日快乐!奖励100元");
    			}
    			
    		}
    
    		
    		
    
    	}
    }
    

     

    展开全文
  • 利用springMVC把报表以excel的形式导出 自定义视图的作用 自己定义视图,视图继承view类或者abstractExcelView或者abstractPdfView,将内容以Excel或者PDF格式显示,还可以玩表格啊什么的。 实现的步骤 1、在pom...
  • C语言链表实现工资管理系统

    千次阅读 2020-04-11 19:32:41
    自己的作业,分享一下,自己为了调试方便,又多加入了一些功能 题目;建立工资管理系统,对职工工资的相关信息进行管理。...5、删除每职工的工资相关信息 6、统计某个职工年度总工资 7、对职工的月工资或年度总工...
  • ... 2、选择上节创建的RPD...3、这里会看到如下界面,左侧的树对应的是RPD文件中最左侧【表示】层中的模型-可以把它当成“表“来看,随便在“表“的字段上双击,就可以添加到右侧的“所选列”区域,先参照下图
  • Java使用POI实现数据导出excel报表

    千次阅读 2018-09-17 11:20:40
    在上篇文章中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式。不仅仅简单的读取office中的数据.尤其是在生产管理或者财务系统中用的非常...
  • 所以做了一个odoo模块用于将卡式报表处理成更常规的适合财务统计的普通报表。语言Python,用到的模块xlrd和xlwt。 2.先看效果 如图,左为卡式报表,右用python处理后生成的常规财务报表。 3.使用的工具 xlrd,...
  • 首先准备一个excel模板,这个模板把复杂的样式和固定的内容先准备好并且放入到项目中,然后读取到模板后向里面放入数据。 1、准备工作 准备模板内容 第二个sheet页 把这个模板改一个英文名称比如:userList....
  • XAML的水晶报表打印

    2019-06-08 15:34:50
    例如:工资单、工作表、考勤表等一些打印报表。对于XAML的水晶报表打印和MVC的水晶报表打印有区别吗?答案是差不多,都没什么区别,只不过XAML的水晶报表打印有点麻烦(个人感觉),至于怎么打印...
  • 步骤: ... 2、选择上节创建的RPD...3、这里会看到如下界面,左侧的树对应的是RPD文件中最左侧【表示】层中的模型-可以把它当成“表“来看,随便在“表“的字段上双击,就可以添加到右侧的“所选列”区域,先参照...
  • 用DELPHI编写特殊报表

    2012-02-01 00:44:57
    ====================================================== 注:本文源代码点此下载 ==============================...---- 我用delphi某单位编写信息管理系统时,财务要求工资统计等报表页的最后行都应有合
  • oracle实验报告

    2019-01-10 19:29:58
    3)、创建一个函数,已出版社名为参数,返回该出版社出版的图书的平均价格。 4)、创建一个函数,以客户号为参数,返回该客户可以获得的礼品名称。 5)、创建一个函数,以图书号为参数,统计该图书被订购的总数量。 ...
  • 实验2答案-sql1.sql

    2019-09-21 16:00:44
     分别查询经济性质“国营”和“私营”的法人名称,贷款银行名称,贷款日期,贷款金额,要求将这两个查询结果合并成一个结果集,并以法人名称、银行名称、贷款日期和贷款金额作为显示列名,结果按贷款日期的升序和...
  • Java程序员从笨鸟到菜鸟之(百零四)java操作office和pdf文件(二)利用POI实现数据导出excel报表
  • 中国的企业信息化,已经过去了20年,企业里也产生了大量的数据,IT技术的信息化管理辅助企业经营管理也已经得到广泛地认同,现在就连一个小卖部都可以有收银系统这样的信息化管理介入。但同时也有一个很现实的问题,...
  • sp3是该系统的一个版本号,只有sp4以上的SQL 2000系统才能够支持纯ODBC连接方式。 Vb6.0功能强大的应用程序开发工具,主要支持基于面向对像化的语言的各种开发项目。 2.需求分析 2.1系统需求和功能 工资管理信息...
  • C#桌面办公应用-工资管理系统系列五 接前文系列四,本文将讲解实现工资管理系统的代码的层次结构。主要采用的是MVCS模式的代码...最后是服务层(S):是从模型层(M)中获取数据库访问操作的结果并逻辑控制处理层(C)...
  • 建立员工工资表(转)

    2019-06-22 17:48:04
    建立员工工资表(转)中文Office 2000软件包中提供了一个名为中文Excel 2000软件,这是一个用于建立与使用电子报表的实用程序,也是一种数据库软件,用于按表格的形式来应用数据记录。专业数据库管理系统软件Visual .....
  • easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法 ...
  • 6.3 样式报表打印方案6.3.1 业务报表 业务报表这个概念比较笼统,也很繁杂,在这里笔者只选取了库存明细表这样一个业务进行演示业务报表,库存信息表在企业应用中非常广泛,几乎所有系统中都会有库存信息表业务...
  • 作者 | 孔若诚杏仁产品经理,业余美剧、设计、哲学爱好者。头像是我偶像。你问一名程序员:世界上最好的语言是什么,你可能会得到各种答案。但如果你问一名财务人员,想要了解一家...
  • 获取项目源文件,联系Q:1225467431,可指导毕设,课设 论文是本团队帮同学做过的案例,需要毕业论文设计(论文+源程序+...基于jsp(java)工资管理系统的设计和开发 姓  系 别、 专 业 导 师 姓 、职 称 完 成...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,513
精华内容 1,405
关键字:

创建一个名为工资报表的报表