MIS系统中的数据查询时必不可少的。而且大部分都是多表查询,这时候SQL语句中的Join就显得尤为重要。再加上现在的O-R mapping,更是给查询带来了一个不大不小的麻烦(我不是说O-R mapping的坏话)。以下的部分将用一个本人认为很典型的例子说明一下。
数据库结构如下:

用户界面如下:

由数据库结构和界面的grid可以很容易想到,直接写上
select FACILITY.*, PROJECT.CODE as PROJECT_CODE, PROJECT.CN_NAME as PROJECT_CN_NAME, SITE.NAME as SITE_NAME, SITE.CID as SITE_CID,
FACILITY_CATALOG.CN_NAME as FACILITY_CATALOG_NAME from FACILITY left outer join PROJECT on FACILITY.MASTER_ID = PROJECT.ID left outer join SITE on PROJECT.SITE_GUID = SITE.ID left outer FACILITY_CATALOG on FACILITY.CATALOG_GUID = FACILITY_CATALOG.ID
。然后在后头写上where搜索里选择的条件。这似乎没什么难度吧。
这个项目典型的地方是使用了一个可爱的框架,绑定在grid上的不是DataTable而是一个EntityCollection,而且这里还用了延迟加载,即使在SQL语句中写上了PROJECT.CODE, PROJECT.CN_NAME,由于延迟加载的关系都被忽略了(Facility这个实体对象里包含MASTER_ID,利用延迟加载来获取实体对象Project)。所以SQL语句就得写成了
select FACILITY.* from FACILITY left outer join PROJECT on FACILITY.MASTER_ID = PROJECT.ID left outer join SITE on PROJECT.SITE_GUID = SITE.ID left outer FACILITY_CATALOG on FACILITY.CATALOG_GUID = FACILITY_CATALOG.ID
至于后面的条件还是和前面一样加。我们可以想象一下这么做的问题:1、虽然用户只选择了站点这个条件,但是FACILITY和FACILITY_CATALOG进行了Join。2、如果用户只选择了设备编目,SQL语句就多了FACILITY和PROJECT、SITE的Join。当然啦,看到这里有人可能会说,我们用的框架没有这个问题或者你不会自己用if做判断啊。换框架没有必要,这里只是拿出一个典型的例子,相信就算换了框架,在开发过程中还是会遇到类似问题的。至于用if进行判断,同样也有麻烦,这个例子里的表比较少,写起判断没什么太大问题。关键是用户选择工程名称时你得加入FACILITY和PROJECT的Join,用户选择站点名称时你除了加入FACILITY和SITE的Join外,还必须先添加FACILITY和PROJECT的Join,否则就出错没商量。
不知大家看到这个例子的特殊性没?本人见过一个项目组用这个框架的时候,一个SQL语句里一次性写了28个Join(自己汗一下先,怎么设计数据库的,虽说是该有不该有的都写了,也没有这么多吧)。当然这不排除数据库设计和框架的问题,其中还有一部分原因就是懒人多,表多条件多的时候谁都不喜欢一个if一个if拼SQL语句。说了这么多,总结起来就是“按需Join的问题”。如果能有一个工具能实现,一次性添加所需的所有东西,然后自动根据需要生成SQL语句,该多好(或者说方便多了,至少本人是这么认为的)?
如果SQL语句进行分解。可以划分为显示的字段定义、表关联定义、条件定义、排序、分组等几个部分。因此,本人对SQL语句的各部分进行如下划分,并以以下术语命名:
1、 Fields:输出字段的定义。
2、 Joins:表关联定义。
3、 Filters:查询条件定义。
4、 GroupBys:分组定义。
5、 Having:Having子句
6、 Existis:Exists子句。
7、 OrderBys:排序定义。
8、 SubQuerys:子查询定义
9、 UsedTables:查询中所使用的表。
10、UsedJoins:查询中所使用的联结
11、 QueryInfo:一条完整的SQL查询语句。
12、 QueryBuilder:查询生成器。
因此SQL语句可以用如下形式表示:
select (Fileds) from (UsedTables | SubQuerys| UsedJoins] [where [Exists] Filters] [group by GroupBys] [having Having] [order by OrderBys]
注:黑体字表示SQL保留字。“()”表示必填项。“|”表示可在其中选择一项。“[]”表示可选项。
经过分解后可以得出这样的结论,UsedTables中的表由所有的Fields、Exists、Filters、GroupBys、Having、OrderBys中所使用的表组成,SubQuerys也可以根据Alias从UsedTables判断是否使用。UsedJoins也可以用同样的方法来实现按需选取,复杂的地方是一个Join可能依赖另一个Join,就像例子里的FACILITY和SITE的那样。另外,Fields为空的时候必须转换为“*”,UsedJoins不为空时From部分用Join,UsedJoins为空时from部分则必须用UsedTables或SubQuerys来代替。
暂时先到这,眼花脖子酸,下回给出对象图和实现思路。
posted @ 2008-04-23 09:39
陈鹏(偶是坏人) 阅读(1712)
评论(6) 编辑 收藏 所属分类:
软件开发