这个系统的SQL语句不少写得比较复杂。比如:
SELECT
decode( ?, 0, '(オーダー入力)', '(オーダーキャンセル)' ) TITLE,
decode(a.FAX_HATCHU_FLG, '1', '', a.JUCHU_NO ) JUCHU_NO,
....
FROM
SUE_INC a,
SS_MASTER b,
...
WHERE
a.SS_CODE(+) = b.SS_CODE
...
甚至还有在SELECT句上含有IF/ELSE分支选择语句的(这是我第一次知道ORACLE支持这种语法)。在一个多层WEB MIS系统上,SQL写得过于复杂,是不好的设计。
带来的坏处是:
导致系统业务逻辑分散分布在SQL语句和BO(Bussiness Objects)上。违反了分层设计的初衷,阅读和理解代码变难,系统维护和升级的工作也复杂了。
举例来说,以上的功能模块,进行维护或升级工作的技术人员必须兼顾JAVA和数据库,在这两个方面都要不错才可胜任工作,要不然就需要两个技术人员。
就上面的SQL语句来说,
1.要避免使用DECODE解码语句。将常量和字典的映射写在SQL上是很笨的,首先SQL的设计者必须记一堆编码映射表不要搞错,很多系统有很大的映射参照表,SQL设计者们要经常查阅这个表。另外试想有一天常量的名称需要改变时,需要修改所有有关的SQL语句。(当然我们还有文件批量查找和替换工具可以用,不过那实在是不太优雅的招数)
2.要避免在SQL上使用外联接来查询字典表。联接查询字典表不能算是大的问题,事实上很多系统都一直这么做的,毕竟比起上述的把字典解码直接写到SQL上要进步很多了,它实现了字典数据的集中管理。但我认为,对于系统运行过程中不会改变的全局字典表(SYSTEM MASTER表,比如《邮政编码映射》,《业务分类》,《顾客分类》等字典表)来说,最好的办法是在系统初始化的时候就将其加载到全局内存中,并在JAVA层提供查询的接口。这样可以减少不少SQL句的复杂度,而且对使用频繁的字典表的访问减少到最低,数据库的负荷也减轻了。
按照分层设计的原则,理想的状态,SQL语句因该是纯粹的最简单的SELECT/UPDATE/DELETE语句,不要包含任何逻辑。存储过程和触发器应该避免使用。
但是,世上的事情总是没有那么简单。不可避免地,我们要遇到一些有关性能的问题,比如,需要对大量的记录的每一条进行一些复杂运算,然后更新这些记录。这时候,在JAVA层面上对每一条记录进行循环,做运算,然后写回数据库,效率可能无法满足要求。此时可以考虑存储过程或复杂的批量UPDATE语句。必须记住的是,在整个系统设计中,这是极端状态下的特例,不能以性能为理由来破坏分层设计的原则。(Hibernate有持久对象缓存机制,另外好像在关注批量更新的性能问题,不知现在应付这类任务性能如何。