硕士毕业论文通信系统中的计费及营帐系统的设计与实现.doc
新疆电信BOSS项目融合计费系统实现方案-通信系统中的计费及营帐系统的设计与实现公开 by 硕士 from .电信学院.计算机技术摘要:随着通信企业的逐步发展,行业竞争的不断加剧,用户数量的不断增多,用户需求的不断扩展,原有的通信网络系统需要进一步扩充及改进。建立数据库系统,使通信系统拥有一套稳定的计费、营帐系统已经成为通信企业今后发展的关键因素之一。在通信网络系统的计费及综合营帐系统的应用中,ORACLE的产品和技术具有许多无可争议的优势。可以极好地满足系统性能上的可靠性、安全性、先进性、可管理性等方面的要求。本系统应用ORACLE数据库设计集中式计费系统和综合营帐系统,将计费系统从原服务器上分离出来,重新建立系统并采用新的服务形式。实现系统的连续、稳定运行,给系统提供最大的高可靠性方案。营帐系统对原应用软件进行全面的改造,变成统一的数据库。使原营业系统变成通信业务的统一营帐受理系统,成为统一的数据仓库。系统实现了综合业务系统的统一功能,完成通信业务在结构上的综合,支持多业务的捆绑服务。充分利用ORACLE的特性,联机事务处理、数据分区技术特性在此发挥出很大的作用,保证了数据库查询、运行、处理、故障恢复的良好实现,建立一套安全稳定的数据库,并保证系统软件新旧版本的平稳过渡,实时可靠的进行系统更新,保证主机系统、网络系统在将来可以在不影响生产运行的情况下进行扩容。1 项目背景第一章按照项目背景、国内外技术现状、论文工作和章节安排3小节来组织随着新疆电信行业市场竞争的不断深入,以及中国电信股份有限公司对各省提出业务目标与要求的不断提高,新疆电信为了更好地完成各项业务目标和计划,完成向以产品为主线、以市场为导向,以客户为中心、以效益为目标的现代化企业转变,形成集团化运作,提出了BOSS项目融合计费系统。2 需求分析第2章需求分析按照功能需求、性能需求、安全需求和开发平台和语言4小节来组织新疆电信BOSS项目融合计费系统计费处理过程是一个使用者使用计费系统的进行各项业务处理的过程,流程与功能设计的目标是使得这个过程稳定、准确、及时、高效、灵活。根据CTG-MBOSS规范与新疆电信的业务需求,将融合计费系统的流程分为七个部分,分别是:1. 原始数据处理包括原始数据收集、预处理、数据的交换与提交2. 资料管理包括产品配置管理与客户资料管理3. 计费数据处理包括批价处理、余额反算、出帐处理、帐单生成4. 客服保障管理包括收费管理、欠费管理、呆坏账管理5. 系统保障包括稽核管理6. 其他处理包括信息点布控、平台保障、业务调度、查询统计7、 系统架构与安全管理包括网络架构、主机与存储管理、数据库管理、安全区域划分与管理3 总体设计3.1 设计目标在中国电信新的计费模型的指导下,设计一个多业务融合的、实时的、集中的、灵活的、可扩展的、可管理的综合计费帐务系统。具体目标如下3.1.1 业务上1). 实现融合业务的采集、批价、帐务以及客户服务保障等处理。对于在一定时期内还存在的专业计费系统以及预付费管理平台,系统应能对其进行整合处理。2). 根据各业务平台的具体情况,通过各种模式实现预付费和后付费的融合处理和管理3). 通过产品、产品包、商品等模型的引入,为市场营销以及客户服务提供更加灵活的营销策略以及客户服务策略的支撑,满足企业向用户提供更加优质的服务以及提高市场竞争力的需要;能为新产品、新业务的快速部署提供良好支撑。4). 根据业务平台的具体情况,实现更加实时的业务处理流程以及客户服务响应。5). 能够支持多方计费和结算,将计费帐务服务延伸到合作伙伴,为目前和未来电信所大力发展的增值业务提供良好的计费帐务支撑6). 建立统一的信用控制机制以及防欺诈机制,减少欠费。7). 建立统一的收入监管机制,通过多方组合稽核、校验手段,如各环节信息点布控、基于流程的稽核等,保证计费的准确性,防止收入流失,从而保障企业的收入;提供与财务管理的统一接口8). 为企业经营分析提供实时、完整、准确的数据和信息。9). 为将来3G业务的开展打下基础,为尽快建立中国电信上下一体化的、统一的计费帐务管理系统,构建统一的业务支撑网打好基础。3.1.2 技术上1). 采用统一的数据模型,符合集团公司的统一数据模型规范,并支持企业制定的统一共享数据模型机制,保证数据的完整性和一致性。 2). 完善的功能和流程支持:符合集团公司规范中对功能和流程的定义,并支持特殊的功能和流程需求。对BPR和MR中的市场营销、产品管理、客户服务等流程提供良好的计费帐务支撑。3). 灵活可扩展的架构:遵循分层和复用设计理念,按照组件化、流程化、策略化设计原则,实现应用与数据分离、应用与流程分离、应用与规则分离,保证前后台端到端的业务及时加载能力,形成业务设计与系统开发同步完成的操作模式。4). 支持企业应用集成:基于统一的共享数据模型和企业应用集成平台实现业务集成。3.1.3 管理上1). 全省/区统一业务处理和管理流程以及岗位设置,同时兼容各地市业务处理和管理流程的特殊性,2). IT系统的运行维护管理是IT系统发挥作用的重要保障,是企业信息化的重要工作内容之一,随着企业信息系统、信息数据的集中,建立完善省集中模式下的系统运行维护管理、数据稽核、数据调度等的流程和规程。3.2 设计方法从总体框架上,采用自上而下的设计方法,先从系统的总体框架上确定系统的实现方式,然后对系统进行逐级分析,进行功能设计、模块设计,并在电信模型的集成上对模型进行推演和验证,并进行相应的完善和补充,进行模型的物理设计。系统总体的框架结构如下:3.3 总体流程设计整个的系统都是在处理各种各样的数据,对每一种数据的处理都有一个相对固定的处理流程。不同的数据所经过的处理流程是不一样的。一个流程由多个环节构成,每一个环节点都对应一个模块。环节之间可能是顺序的先后关系,也可以是并列关系,一个环节可以执行的条件是其前面的一个或多个环节已经完成,而同时该环节完成后,可以是一个或多个新的环节,这样并列的多个环节点可以并行执行,而先后的两个环节只能顺序执行。一个环节可以是一个系统自动执行的任务,也可以是一个需要由人工稽核确认的稽核任务。系统中的主要流程有:l 按文件方式控制的实时计费流程l 按话单流方式控制的实时计费流程l 日帐流程l 月帐流程l 3.3.1 文件计费流程计费流程所处理的数据包括:联机采集的计费文件、脱机采集的计费文件、上级公司下发的数据、其他系统提供的数据文件。该流程监控的主体是文件。该流程的任务基本上都是实时运行的,流程的稽核在系统的每一个模块内部自动完成。对稽核有异常的实时告警。该流程的结构图如下:3.3.2 实时话单流计费流程该流程所对应的模块与文件方式基本相同,只是该流程监控的主体是实时采集的话单流。3.3.3 日帐流程日帐流程运行的单位是每天运行一次,控制的主体对象是每天的日帐单。日帐流程的环节较多,每一个环节都有一些自动稽核的模块,也可以在流程中安排需要人工确认的稽核任务,这样增强对流程的稽核控制。在系统稳定的情况下,日帐流程是可以自动运行的。3.3.4 月帐流程月出帐流程是一个月运行一次,处理过程中环节较多,在流程需要比较严格的稽核控制,因此会插入较多的人工稽核环节。3.4 总体功能架构设计计费系统的总体流程图如下:3.5 总体数据模型设计系统的总体数据模型采用了集团的新的计费模型作为基础进行设计的。总体的概要模块如下:3.6 系统接口总体设计与计费系统有关的接口设计如下:3.7 系统部署设计系统部署主要是三方面的部署,在整个部署设计中,主要考虑的时候分布式处理和系统的可扩展性。根据新疆的具体情况,对其数据库和应用的物理部署图如下:系统集成方案系统集成主要有三种方式:用户界面集成(嵌入式集成)、应用系统集成(实时数据交换)和数据集成(批量数据交换)。系统集成方式用户界面集成(嵌入式集成)通过Web 技术或其他客户端调用技术,在不触及底层的应用和数据的情况下,为用户提供完整、易用、灵活的使用者界面,并实现简单的参数传输。应用系统集成(实时数据交换)通过EAI和其他应用接口调用实现复杂的跨系统的业务逻辑和流程。数据集成(批量数据交换)通过数据库层面的同步和传输,实现数据共享。系统融合方案计费系统的建设,主要考虑现有分产品、多计费系统的融合,在当前向以客户为导向的全业务运营商方向发展的情况下,这一点尤为重要,系统融合的目标如下:实现预付费与后付费的融合§ 支持灵活帐期的融合计费§ 支持跨产品线的多种产品进行捆绑的融合计费§ 灵活支持各种优惠和折扣的融合计费系统融合方案示意图4 详细设计4.1 原始数据处理-数据采集4.1.1 数据交换采集处理流程说明 数据交换采集模块用来处理各种模式下的文件采集,包括如下以下几种采集模式:n EAI消息处理采集模式n DB记录控制采集模式n 文件控制采集模式n 自动采集模式这个模块主要是实现各种模式下的采集,对于各种模块他们有各自的特点,例如EAI消息处理采集模式他就是通过IBM中间消息键来实现的,先发消息过来,然后采集系统就根据消息从服务器上面得到具体的文件;DB记录控制采集模式,这个就是根据数据库中的记录得到的所需要采集的文件信息;文件控制模式就是采集某种文件然后根据这个文件的信息来得到所要采集的信息;自动采集模式就是按照一定的规律来检查是否有文件,有文件就采集。数据交换采集过程主要包括加载通用的采集参数信息,分不同的采集模式采集数据,文件级校验,写日志处理几个流程。1. 加载通用的采集参数信息,建立所有采集模式所共享的数据源。数据交换采集过程是具体执行文件采集,与文件采集相关的参数说明文件采集过程中要什么方式采集,采集过程中我们要做什么检测等等。n 服务器参数Ø 从服务器参数表里获取要连接的具体地址、用户名、密码、是否实现断点续传、采集模式、可以连接的日期和时间等信息。n 文件类型参数Ø 得到每种文件服务器下不同文件的具体的命名 ;Ø 得到具体文件的等级,就是说上一等级的数据没有采集下面等级的数据就不能采集,同等级可以同时采集;Ø 得到文件是否可以在中断后是否可以续传;Ø 文件采集过来后要作什么处理标识n 文件名命名参数Ø 从文件名命名参数表里得到各种对应文件的命名方式;Ø 同时知道文件名里的代码是不是特征码,假如为特征码,我们就用“*”来表示其前和后面的代码;假如不是就用”?”来代表其各位的代码;Ø 得到不是特征码其每位的具体代码;n 文件内容格式定义参数Ø 得到文件头、尾、内容要包含的内容Ø 得到文件头或者文件尾包含几行的信息;n 文件服务器目录参数Ø 得到文件服务器作为文件的源和目的地址的目录;Ø 得到文件是否是压缩的、是否是有索引文件;Ø 得到文件的校验方式;Ø 得到序列号的生成方式;Ø 得到错误回馈文件类型;Ø 得到文件的级别是否有效;n 序列号规格定义参数Ø 得到每中文件目录下的序列号的具体生成方式;n 消息内容定义表参数Ø 得到某个服务器发给采集系统的消息格式信息n 日志内容定义表参数Ø 得到每个日志信息表有那些信息;n 校验方式定义参数Ø 得到每重校验方式在某种情况下所要做的校验包含那些校验;2. 分不同的采集模式进行采集文件处理n 自动控制模式这种控制模式就是先得到相应的服务器和所要采集的文件名格式及其参数,然后按照时间规律性来得到文件,和对文件所对应的一些稽核要求来进行做校验。n 文件控制模式这种模式就是先得到具体文件控制形式,假如是根据总控文件或者根据索引文件的方式,我们先得到总控文件的文件及其内容,然后根据其内容来处理得到具体要采集的文件名,然后根据文件名得到具体该文件是什么样的文件,最后来得到对这种文件怎么处理,例如稽核校验,断掉了是否要续传。n DB数据记录控制模式对于这种记录是先从某张表里得到要下载的文件记录,然后根据记录得到其对应的服务地址和文件类型,最后得到其具体的采集处理方式和稽核方式。 n EAI消息控制模式这种方式先通过消息得到要采集文件的一些信息,相当于索引文件的内容,然后我们根据这个信息得到文件的类型,最后我们根据文件类型和所处的目录得到具体采集的处理方式和文件稽核方式。3. 日志处理日志处理对于不同的应用系统他有不同的日志需要写,例如现在我们的一点收费系统,有些文件采集过来的是要先代码转换处理,有些是原始文件,就不用做代码转换这两种就要写不同的日志表。4.1.2 模块类图4.1.3 采集公共基类(CFtpBase)的设计/* * 采集公共基类 */class CFtpBase:public CThreadprivate:/* * 当前采集的服务器信息、文件信息 */CFtpSystemInfo m_CurrentFtpSystemInfo;CIpDirectroyName m_CurrentIpDirectoryName;CFileTypem_CurrentFileType;public: /* * 连接服务器 */BOOL ConnnectCurrentFtp();/* * 校验文件*/BOOLAuditFile(char *szLocalDataFile, CFileDown &sFileDown, char *szAuditDetail);/* * 移动本地文件*/BOOLMoveLocalFile(const char *szDestFile,const char *szSourceFile);/* * 解压本地文件*/BOOLUnZipLocalFile(const char *szLocalFilePath);/* * */BOOLGetLocalDirLs( const char *szListFilePath,const char *szLocalDir);/* * 拷贝本地文件*/BOOLCopyLocalFile(const char *szDestFile, const char *szSourceFile);/* * 删除文件*/BOOLRemoveAFile(char *szFileName);/* * 得到文件的字节数*/BOOLGetFileSize(char *pFileName,double &nFileSize);/* * 更改FTP上面的文件名*/BOOLModifyFtpFile(const char* szFtpDir, const char* szFileName, int nModifyFlag);/* * 更改本机上面的文件名*/BOOLModifyLocalFile(const char* szLocalDir, const char* szFileName, int nModifyFlag);/* * 开始采集一个文件*/BOOLGetOneFile(CFileDown &fileDown);/* * 得到满足条件的文件列表*/BOOLGetFileList();/* * 根据文件序列号排序*/voidSortOne(CFileDown* pFileDown, int begin, int end);voidSort(CFileDown* pFileDown, int nFileCount);/* * 创建采集结果文件*/BOOL CreateResultFile();/* * 写各种日志表*/BOOL WriteAllLog(int nLogId);protected:/* * 检验时间是否有效*/BOOLCheckTimeValid(char *szTime);/* * 检验文件名是否有效*/BOOLCheckFileName(CFileDown fileDown);/* * 检验文件尾格式是否有效*/BOOLCheckFileEnd(const char *szFilePath, CFileDown &fileDown, char *szRet);/* * 检验文件头格式是否有效*/BOOLCheckFileHead(const char *szFilePath, CFileDown &fileDown, char *szRet);/* * 生成MD5信息*/BOOL CreateMD5Info();4.2 资料管理 资料管理包括产品的管理与用户资料的管理。产品管理是指对电信产品、产品包以及商品的定义与维护。用户资料管理包括客户个人信息管理,客户支付信息管理,与费用相关的客户的积分与信用度的管理4.3 计费数据处理计费数据处理包括批价处理、入库、帐务、营收管理四大部分。4.3.1 批价处理批价进程内主要有两种线程,一个是控制线程,用来整体上控制批价的过程,一个是业务线程,用来对具体业务的事件进行批价处理。相应地,在设计时,使用两个类来完成这两个功能,一个为批价控制类,用来做批价整体上地控制,包括对事务的控制,输入输出的控制,接收到的输入话单进行业务线程分派处理,监控服务命令的处理;一个为事件批价类,用来对单个事件进行批价处理。月租事件的处理与话单事件的处理基本上一样,计费为一个单独的进程,月租与帐务优惠为一个进程。月租事件的属性包括如下属性:业务类型,号码,事件类型,时间,时长(天/月)批价完毕后,输出事件中包含一个事件分类字段LS_FLD_EVENT_CATALOG,如果为月租类型和帐务类型,输出模块中将输出事件送给月租和帐务优惠用的消息队列,如果为计费类型,输出模块将输出事件送给入库程序用的消息队列中。4.3.1.1 模块类图4.3.1.2 模块类设计/* * 批价控制类,由控制线程使用 */class CRatingCtrl /* * 输入对象指针 */ CDataInput *m_pDataInput; /* * 输出对象指针 */ CDataOutput *m_pDataOutput; /* * 业务线程个数 */ int nServiceThread; /* * 输入模块传入的FArray*是已经分配好的空间 * 批价控制模块将此事件的地址放入对应处理线程的(数组)缓冲区中 * 当事件批价完后,需要由批价业务线程将此事件的空间删除 * m_pInputEvents在对象初始化的时候根据业务线程的个数 * 分配空间;对象析构时,删除分配的空间 */ ArrayList<FArray*> *m_pInputEvents; /* * 每个线程缓冲区访问互斥信号灯 */ ArrayList<pthread_mutex_t> m_vBufferMutex; /* * 每个线程缓冲区访问条件变量 */ ArrayList<pthread_cond_t> m_vBufferCond;public: /* * 构造函数 */ CRatingCtrl(); /* * 批价控制模块的主控函数 */ void Run(); /* * 开始一个事务 */ bool StartTransaction(); /* * 提交一个事务 */ bool CommitTransaction(); /* * 回滚一个事务 */ bool RollbackTransaction(); /* * 处理事件,将输入事件放入输入事件缓冲区中 */ bool ProcessEvent(FArray* pInputEvent); /* * 批价回退 */ bool RollbackRating(); /* * 更新计费参数 */ bool UpdateParams(); /* * 退出批价进程 */ void ExitProcess(UINT uExitCode = 0);/* * 【类功能的详细描述】 */class 【ClassName】/* 公共函数定义 */public:/* 功能描述: 【函数功能的详细描述】* param 【参数名称1】【参数类别:入参/出参/出入参】【参数功能描述】* param 【参数名称2】【参数类别:入参/出参/出入参】【参数功能描述】* return 【返回值说明】*/ReturnType FunctionName(ParamType1 ParamName1, ParamType2 ParamName2,);/* 私有函数定义 */private:/* 功能描述: 【函数功能的详细描述】* param 【参数名称】【参数类别:入参/出参/入出参】【参数功能描述】* return 【返回值说明】*/ReturnType FunctionName(ParamType1 ParamName1, ParamType2 ParamName2,);/* 成员变量定义 */private:/* 【变量功能描述以及可能的取值说明】*/VariableType VariableName;4.3.2 批价入库正常清单表:UR_存放用户的正常清单,按月份分表;无户清单表:Anony_,因为无户数据比较小,同时无户数据需要一次保持可回收,故不按月份分表;误单表:Error_,存放用户的误单数据,因为误单数据比较大,同时隔月后误单一般不再进行回收处理,故按月份进行分表。入库模块功能:1将预处理模块和批价模块生成的结果数据插入到数据库相应的表中。2入库数据回退,根据回退设定的条件将已经入库的数据从数据中清除掉。3入库数据重做,根据重做设定的条件将已经入库的数据插入到定义的回退。4.3.2.1 模块涉及的表说明表名 功能描述IOID_SEQUENCE_TIOID序列定义表FORMAT_OUT_T输出格式定义表FORMAT_OUT_DETAIL_T文件格式输出定义明细表BILLING_CHECK_DETAIL_T计费稽核信息表BILLING_CHECK_POINT_TINTERVENE_EVENT_TFORMAT_OUT_CONDITION_T输出格式条件定义表FORMAT_RATING_T格式配置表USAGETYPE_T使用记录类型表card_flag_tTREE_STRUCT_ITEM_TFORMAT_OUT_ITEM_T输出格式子清单费用序号定义表入库程序首先创建一个入库总控线程,入库总控线程实现程序的所有流程。入库总控线程流程:1. 打开相应的消息队列;2. 创建一个取队列缓冲线程,取队列缓冲线程从已经打开的消息队列中读取消息,放到模块的内部队列中;3. 读取参数,创建总控线程的数据库事务连接;4. 创建入库对象,入库公共参数初始化;5. 创建一批入库处理子线程;6. 接收调度程序发送的指令,根据指令执行相应的操作;7. 读取内部队列中的消息:如果是入库操作的消息:话单消息转发给入库子线程处理;开始事务消息通知入库子线程事务开始;事务提交消息通知入库子线程对事务进行提交,事务回滚消息通知入库子线程对事务进行回滚。如果是回退操作的消息:创建回退事务;通知入库子线程开始事务;取回退数据,形成回退清单,送到内部队列;事务提交。入库子线程读取内部队列中的消息,根据消息中的内部控制命令执行相应的操作模块类设计类名称功能描述与其他类的关系CImpBase基类CIOID取下一个IOIDCFormatDef从数据库中取出记录格式的定义,根据FormatId查找对应的入库格式CIBASConf读配置文件,设置参数CImpact公共参数的初始化,更新,Cimpact内部参数的初始化,更新;提供入库数据的事务开始,事务提交,事务回滚,入库处理方法;提供回退事务开始,回退事务提交,回退事务回滚,回退数据生成,回退处理函数,事件状态更新方法。从CimpBase继承CImpAudit提供i对入库数据进行稽核的方法CImpBufItem入库缓冲区类,提供两个CimpBufItem对象的比较方法CImpBuffer提供从入库缓冲区中取出相应的格式配置的方法从CimpBase继承CImpCardFlag建立一棵卡类标识的CAVLTree,提供取卡类标识方法CImpConnDB停供数据库连接操作CImpObj常规入库对象类。提供属性设置,消息格式检查,主清单入库,子清单入库,累帐,筛选累帐字段的方法从CimpBase继承CImpObjMeter表底入库对象类。重载了表底对象的属性设置,主清单入库1,子清单入库,累帐的方法从CImpObj继承CImpObjCumul累计资源入库对象类CImpObjRB回退对象类。重载了累帐方法从CImpObj继承CImpPara入库参数类,提供了入库参数初始化的一些方法和根据format_id取得批价输出格式的方法CImpTreeBatch批次树对象。提供把累帐对象累到批次树和巴批次树入累帐天表的方法从CimpBase继承CImpTreeCumul累计资源树对象.重载累积资源累到累计资源树和累计资源树入库的方法从CimpBase继承CImpTreeMeter基础表底树对象。重载方法实现把一条表底记录累到表底树上和表底树入库从CimpBase继承CImpQueue内部消息队列类从CimpBase继承l 文件格式输出格式定义结构 */typedef struct _TFormatDetailTFormatDetail;l 输出格式定义结构 typedef struct _TFormatOut TFormatOut;/*l 子线程信息 */class CSubInfopublic:CSubInfo();CSubInfo();void Init(pthread_t ptid);void Reset();BOOL Check();void Error();void Exit();pthread_t m_ptid;CImpQueue m_ImpQueue;long m_lLoad;/负载统计private:int m_nStatus;pthread_mutex_t mutex;/*l 子线程管理器 */lass CSubDealerpublic:CSubDealer();CSubDealer();/注册子线程void Regist(CSubInfo* pSubInfo);/注册统计线程void RegistStats(CSubInfo* pSubInfo);/消息分发inline BOOL Deal(CImpMSG* pImpMSG);/关闭子线程void SubClose();/检测子线程BOOL SubCheck();BOOL SubCheck(int seq);BOOL StatsCheck();/给子线程下控制命令void SubNotify(int CMD);/清空子线程队列void SubClear();/恢复子线程状态void SubReset();/负载报告void Report();private:int m_nSubCnt;/子线程数量CSubInfo* m_ppSubInfo10;/子线程信息CSubInfo* m_pSubStats;/统计子线程信息;/*l 子清单结构 */typedef struct TSubList;/*l 子时段范围段 */class CSubTodRangepublic:CDayRange *pParentDayRange;DomainId nStartOffset;DomainId nEndOffset;DomainPriority nCalcPriority;4.3.3 帐务统计“源数据获取”是指从统计数据源表将原始数据取到内存中。在一些情形下,获取数据只是从一个数据库中进行简单的查询操作即可。但在一次统计操作中,很可能需要进行两个或更多表的关联,例如,从帐单表和资料表这两个表中分别取出一些字段,构成完成的统计数据源。如果帐单表和资料表在同一个数据库中,则可直接用SQL语句进行两个表的关联,甚至更多表之间的、条件更复杂的关联。如果两个表不在同一个库中,则需要将两个表的数据分别取到内存中再进行关联。本模块对这种跨越数据库进行关联的情形作以下限制性约定(同一个数据库内的不同用户没有限制)1. 最多支持两个表的跨库关联。2. 关联时的条件仅支持“等于”,即类似于以下操作:SELECT * FROM BILL_RENT_DETAIL_ITEM_T A, SERV_T B WHERE A.SERV_ID=B.SERV_ID3. 支持多个字段的“与”运算,即类似于:SELECT * FROM BILL_RENT_DETAIL_ITEM_T A, SERV_T B WHERE A.SERV_ID=B.SERV_ID AND A.SERV_SEQ_ID=B.SERV_SEQ_ID4. 进行关联的表允许定义各自独立的数据过滤条件,即类似于:SELECT * FROM BILL_RENT_DETAIL_ITEM_T A, SERV_T B WHERE A.SERV_ID=B.SERV_ID AND A.SERV_SEQ_ID=B.SERV_SEQ_IDAND (A.CHARGE>0 OR A.CHARGE_MONTH > 0)AND B.EFF_ACCT_MONTH<=200501 AND B.EXP_ACCT_MONTH >= 200501u 数据获取的具体流程:1. 根据参数表中定义的规则构造SQL语句。在参数表中提供了以下信息:² 数据源一。是一个SQL字符串,其中可以定义形式参数,在程序执行时被替换为实参。例如:SELECTSERV_ID,SERV_SEQ_ID,CHARGE,CHARGE_MONTH,BASE_FLAG, ' ACCT_MONTH' acct_month, ACC_DATE' acct_date FROM BILL_RENT_DETAIL_ITEM_T WHERE BASE_FLAG>0 AND REGION_ID=REGION_ID这个SQL语句也可以是两个或更多表的关联,但这些进行关联的表都必须位于同一个数据库内(可以属于不同的用户)。SQL语句中的ACCT_MONTH、ACC_DATE、REGION_ID是形式参数,在统计程序执行时,会被替换成帐务月、帐务日、区域的实际值。这里定义的SQL语句不能有ORDER BY子句。² 数据源一所属数据库ID。该数据库ID指明该数据源是位于哪个数据库,该ID在DATABASE_INFO_T中进行定义。² 数据源二、数据源二所属数据库ID。(可选)² 数据源一、二的关联字段。定义了数据源一、二的记录是通过哪些字段关联的。可以定义多个字段,构成“与”的关系。一般来说,对数据源一、二需要定义若干个字段的关联关系,如果没有定义任何关联关系,关联操作将得到两个数据源的笛卡尔集,对于较大规模的数据源,其笛卡尔集将是非常庞大的,因此统计程序作以下限制:如果两个数据源要进行关联,就必须至少定义一组关联字段,否则认为是参数设置错误。根据参数表中的以上信息构造真实的(将被发送到数据库执行的)SQL语句:对数据源一(或二)执行以下操作:1) 用实际取值替换SQL语句中的形式参数2) 根据属于数据源一的关联字段,构造ORDER BY子句。例如:数据源一和二通过SERV_ID和SERV_SEQ_ID两个字段进行关联,则参数表中有两条记录,分别是SERV_ID和SERV_SEQ_ID,则从数据库中查询数据源一时所用的SQL语句为:SELECT . FROM ORDER BY SERV_ID,SERV_SEQ_ID2. 查询数据库,将结果集取到内存。如果定义了两个数据源,则需要打开两个数据库连接,分别从不同的数据库中获取数据。3. 在内存中进行两个结果集的关联。由于在前面的步骤中构造SQL语句时,分别按关联字段对数据源一、二的结果集进行了排序,在内存中可以简单地进行条件判断,对结果集进行关