Powerdesigner 数据库分析设计与应用.pdf


作者:姜江 error 1 第1章 PowerDesigner 概述及基本操作 Knorr 联合公司产品开发部的副总裁 Peter Singer 表示“建模工具的重点曾经完全放在数据建 模一个方面当中,而随着需求的不断提高,商业流程建模和 UML 已经成为软件开发行业不可缺 少的部分。 现在市场上有很多的工具提供数据建模,包括数据仓库建模、对象建模、业务流程建 模以及 UML 建模,但这些产品都无法与将所有的功能集于一体的 Sybase PowerDesigner 相媲美。 IDC 公司的 Stephen D. Hendrick 指出:“目前更为紧迫的挑战之一就要理解组织需求、现有 IT 系统的功能以及新 IT 系统开发之间的关系,将业务流程建模和数据建模相结合是将商业需求和现 有的以及计划推出的系统相结合的最佳途径。建模是推动依赖于应用架构和以服务为导向的架构 紧密联系的应用开发的最佳方式。” 这一章主要介绍一些 PowerDesigner 的主要特点和基本概念,PowerDesigner 10 的新特性。之 外,还包含了一些常用操作及其使用参考,读者不必先将第一章全部看完,也可以跳过这一章, 直接看自己感兴趣的其他章节,看到相关概念或者需要查看相关操作技巧的时候可以回过头来阅 读第一章,毕竟不是所有概念都适用于有特定需求的用户。 本章主要内容和学习思路如下:  PowerDesigner 特点介绍,PowerDesigner 10 的新特性,PowerDesigner 其同其他 CASE 工 具之间的比较  PowerDesigner 的使用环境介绍  图形显示和布局功能的使用  模型图形的打印  PowerDesigner 中快捷方式的概念,并且通过一个实例介绍快捷方式在图形的布局方面的 应用  对象复制  PowerDesigner 中常用的快捷操作和操作技巧 1.1 PowerDesigner 简介 目前,设计工具市场正在从单一的专用工具逐步转向一整套灵活组合数据库建模、UML 和业 务流程分析建模的技术,这些技术通常要同时提供给企业中的不同人员使用,因此,只有各个部 门密切合作以及对采集的元数据进行更好地集成,在单一灵活的集成环境中提供多种建模技术, 才能最大限度地增强 IT 企业的生产效率和迅速适应变化的能力,提供企业级的附加价值。 PowerDesigner 是“一站式”建模与设计解决方案。企业级用户可以借此创建新应用或对现有 商业应用软件进行反向工程,而整个流程会十分迅速、流畅、经济。那些困扰项目开发的难题—— 使用不同的技术、跨平台运行、以及在大部分企业中常见的混合多种开发语言——都可迎刃而解。 作者:姜江 error 2 这样用户可以在开发流程的各个阶段(从系统分析和设计,到自动生成编码)将精力集中在实现 商业需求上。 本书介绍的 PowerDesigner 10 为 Sybase 发布的最新的软件分析设计工具,具备以下几个特色 ——新的商业流程建模能力,增加了单独的 XML 模型,改善了基于 UML 的对象模型,而且在一 个丰富的图形环境中,可支持传统的和新增的建模技术。因此,那些需要跨平台和使用多种类型 编码的项目,可以大大地缩短开发时间,降低复杂度。 PowerDesigner 是目前最为流行的软件分析设计工具之一,它大致具有以下特点:  为所有 IT 用户提供了一整套用于系统分析和设计的完全集成的建模解决方案,是少数能 在一个环境中支持所有几种建模技术的设计工具之一:数据库建模(概念数据模型 CDM, 物理数据模型 PDM),业务处理模型 BPM,以及面向对象模型 OOM,以及自由模型 FEM。  数据建模方面:利用基于可靠方法、真正的两级(概念上和物理上)关系数据库建模, 设计并生成数据库模式。同时还支持数据仓库特别建模技术。  强大的文档定制自动生成功能(RTF 和 HTML 两种格式),将程序员从大量的文档重复 工作中解脱出来(如生成大规模数据库的数据字典等)  用户可完全自定义的元模型模板(包括 DBMS 定义文件,面向对象语言定义文件等等)、 扩展属性等,为特定需求用户生成特定要求的带马提供了最大限度的可能性。  以结果为导向、以数据为中心的业务处理模型(BPM)可以使业务人员和 IT 员工在设计 和开发中能顺利合作,有助于弥补业务需求创意和 IT 系统开发创意之间的隔阂,从而 确保项目能满足业务目标的要求  提供了对所有 UML 图以及所有主要平台的全方位支持(兼容 J2EE(TM)、ebXML、Web 服务和.NET 等)(10.0 版本中还增加了对 c#语言的反向工程功能)  在基于资源库的单一环境中提供了多种建模技术的元数据集成,包括技术层面和非技术 层面的(在设计时使用诸如对象/关系映射以及使用链接和同步技术将任何一个模型内的 改动传达给所有其它模型)  为所有模型和对象提供了通用的性能、扩展属性和脚本处理,而不仅仅是对数据库的自 定义和开发语言支持。  融入了完整的版本控制功能(Repository), 用来贮存和管理所有建模和设计过程中的信 息,将分析设计和版本控制无缝集成,使得建模团队协作的能够得到有效的管理和控制 库(repository),,并将其中不一致的部分最小化,可以轻易查阅并共享工作组里所有成员 的模型和信息。版本库可升级支持角色安全设置、版本控制、搜索及报告能力,从而极 大地提高了开发者的效率。 如图 1-1,该图为 PowerDesigner 首席架构师 Xiao Yun WAG 于 2002 年在亚太区用户会 议上演示文稿中 PowerDesigner 9.5 的模型,它展示了 PowerDesigner 9.5 的基本模型框架: 作者:姜江 error 3 图 1-1 PowerDesigner 解决方案框架 图 1-2 摘自《ID12 利用 PowerDesigner 快速建立面向对象应用模型 》 张波 (Boris.zhang@sybase.com),它集中体现了使用 PowerDesigner 进行企业建模的生命周期: 图 1-2 PowerDesigner 9.5 建模生命周期图 图 1-3 摘自 PowerDesigner 9.5 系统文档,展示了 PowerDesigner 的全局软件解决方案,及 各种模型之间的关系,同前一张图有很多类似之处,读者可仔细体会其中差别。 作者:姜江 error 4 图 1-3 PowerDesigner 9.5 全局解决方案图 1.2 PowerDesigner 10 的最新特点和功能 目前绝大多数读者和用户还是在使用 PowerDesigner 9.5 或者更早的版本,因此,这里 有必要向大家介绍 PowerDesigner 10。 商业用户通过使用 PowerDesigner 10.0,增强了对业务流程优化控制的能力。新增的 SIMUL8 模拟工具帮助用户调整业务流程,实现效率最大化、运行成本最小化。此外,通过 增加对 BPEL4WS(Business Process Execution Language for Web Services)双向工程的支持,商 业模型与实际实施之间的联系更加紧密。在各种开发环境的开发者,包括使用 C++和 Visual Basic .Net 的开发者都受益 PowerDesigner 10.0 对 UML 的全面支持,从而大幅地提高生产效 率。PowerDesigner 10.0 扩大了现有的 Java, C++, Corba IDL, PowerBuilder 和 XML 的编码生成, 增加了对 Microsoft .Net 平台上的最流行语言的支持,保证了所有企业所用来开发软件服务的 一种语言或多种语言、组件及应用都能够被全面支持。 PowerDesigner 10.0 是 Sybase 领先的、集成化的企业应用分析与设计工具的最新版本, 能够满足企业对所有业务、数据和对象建模的需求。PowerDesigner 10.0 将商业需求与应用技 术紧密结合,不论终端用户的技术水平如何,PowerDesigner 10.0 独特的建模方法都能够促进 商业客户和 IT 公司之间更顺畅的交流与合作。 在保持原有数据建模、UML 建模和业务流程建模的基础上,新版本满足了客户将 IT 技 术与业务需求进一步融合的需求,从而解决了提高项目成功率、降低运营成本的关键问题。 Sybase 企业产品和技术、工具部全球产品线总监 Dimitri Volkmann 表示:“当一个公司努 力将商业需求和 IT 技术需要结合时,建模工具之间的一致性显得尤为重要。通过 Sybase PowerDesigner 10.0,我们开始开发一套完整的工具,让它能够集合三种建模技术--业务流程 建模、数据建模、UML 建模,从而使商业和 IT 部门能够更容易进行项目合作,帮助客户实 施更多连贯的、成功的项目。” PowerDesigner 10 提供了的主要的新功能以及新的特点具体的表现为以下的各个方面: 批注 [e1]: 图 1-1 至 1-4在提法上均为 “摘自„„”,是展示其它权威人士 对 PowerDesigner 的体系结构的理 解,因此个人认为不适合翻译,请斟 酌。其他指出需要翻译的图形都已翻 译。 作者:姜江 error 5  增加了 XML 模型(XSM)  新增加的 XML 模型提供了表示 XML 文档结构的图形界面,可以对 DTD 以及 XML Schema 进行图形建模。由于 XML 结构可能很复杂,所以通过显示的图形方式将 XML 结构可视化,这比直接月度 XML 代码要清晰得多。  可以定义 PDM 中的表和 XML 模型元素之间的映射,也可以定义 OOM 中类和 XML 模型 元素之间的映射,也可以将 PDM 或者 OOM 自动转化为 XML 模型,大大降低 XML 建模 工作量,但不支持从 XSM 到 OOM 或者 PDM 的转化  增加了对 MDA 的支持  MDA,即 Model Driven Architecture,模型驱动体系结构,在 PowerDesigner 中 可以使用 MDA 在生成模型之前或者之后转化对象(Transform objects)  可以使用 VBScript 在模型源文件(Resource file)中的元类型(metaclass)上定 义转化(Transformation)  MDA 可以改进应用程序的集成能力和互操作性,可以在很大程度上节省花费在应用 程序开发以及维护上的时间和精力。  概念数据模型(CDM)  在“域”的属性窗口中增加了属性“Mandatory”, 表示所有使用该域的实体属性值 不可为空  增加了对 IDEF1X 表示方法的支持  增加了一些 PDM 对象的版型(Stereotype)  物理数据模型(PDM)  视图中的列已经成为一个标准的对象,在相应的属性页内,包含 name,code,comment 等属性  可以将事实(Fact)或者维度(Dimension)类型分配给视图,可以通过查询多维对 象在模型中突出事实和纬度视图的概念,并且可以通过重建立方体(Rebuild cubes) 的功能由事实和纬度视图来创建立方体(Cube)和维度(Dimension)  支持 Oracle 中的位图连接索引(Bitmap join indexes)  可以支持 DB2 OS/390 定义多个数据库。  可以在 PDM 中使用某种特定类型的视图来设计查询表(Query Tables),查询表的数 据是源于一个查询的结果,例如,在 DB2 中,可以使用 summary 表或者 Materialized query table 类型,在 Oracle 中则可以使用 Materialized 视图或者快照类型  增加了对 IDEF1X 表示方法的支持  增加了一些 PDM 对象的版型(Stereotype)  面向对象模型(OOM)  增加了将 C#应用程序反向工程为 OOM 的新功能  增加了将 VB.NET 应用程序反向工程为 OOM 的新功能 作者:姜江 error 6  加强了对 Java WebService 的支持,连接到 Webservice 组件的接口可以用于设计不同 组代表不同端口类型的方法(将 WSDL 到如到可执行的 BPM 的时候,需要这种断 口类型)  可以使用一个 Container 和实现类(Implementation)定义 Association 的实现,以前 访问对象元素通常是通过定义 Array 类型,现在可以通过 Container 更复杂的结构可 以提供更多的访问方法。  增加了对 Axis 的支持,现在可以为 Axis 将一个普通的 Java 类部署为 WebService 组 件。  支持 Composite Activity 的 Committee Acitvity 类型  增强了对 PowerBuilder 10 的支持  业务流程模型(BPM)  增加了对可执行 BPM 的支持,可以使用服务描述对象导入 WSDL,从而管理服务、 接口以及操作,在可执行流程中可以引用这些对象。可执行业务流程允许你在分析 级别上查看流程,并且可以通过实现原子流程来细化  全面支持 BPEL4WS 语言,可以生成 BPEL4WS 代码或者做反向工程  可以生成 Sybase Orchestrator 代码  可以使用面向服务的体系结构流程语言设计模型, 而不必局限在具体的语言上  支持模拟,可以通过模拟在模型上执行实验,可以动态执行流程,目的在于通过观 察模拟的过程发现问题解决问题,或者测试问题的理论性解决方案,而模拟的结果 又可以用于制定出可行的模型决策。  ebXML 被集成在流程语言中  文档报告(Report)  可以从报告中移除每个 Item 的 Title(标题),这样可以在生成的报告中把标题去掉  目录的上下文菜单(右键菜单)上的 Hierarchical display 命令可以根据内容的层次在 生成的文档中也可以显示出包的层次结构  Repository  在不连接 Repository 的情况下也可以通过 Drop Repository Table 选项删除本地的 Repository,以前的版本中必须先连接 Repository,然后 Upgrading,然后才可以 Drop  增加了删除 Repository 所有分支(Branch)下文档的所有版本的命令  其他  增加了图形(Diagram)移动向导(Move Wizard),允许将图形移动至单独的包内, 以便重新组织模型  可以在宏.convert_name 中使用新的参数,从而使用特定的命名规则将 name 转化为 code,例如在生成 OOM 的时候,可以选择 Convert Names into Codes 选项,并且使 用 convert_name 宏用这些参数使得对象的 code 适用于生成 OOM 所用的特定语言。 作者:姜江 error 7  扩展连接(Extended Link)在以前的版本中仅仅可用于 Free Model,现在可以用于 任何类型的模型中  可以在复合对象的图符上显示它的内容,例如查看子包、子流程、子活动、子节点 等等  Extended Collection,用于定义元类型(metaclasses)和版型(stereotype)等之间的 扩展连接,可以更好的集成新的对象  略„„ 图 1-4 摘自 PowerDesigner 10 系统文档,可以看出 10 中在模型方面主要增加了对 XML 模型 的支持。 图 1-4 PowerDesigner 9.5 全局解决方案图 1.3 PowerDesigner 同其他 CASE 工具的比较 许多朋友在刚开始学习建模分析软件的时,经常会问道这个问题“我刚开始学软件分析设计, 用哪个软件比较好?”。事实上,网络上可以看到很多见仁见智的答案,但绝对没有标准答案,每 一种建模分析软件都有各自的特点,适用于不同的需求,解决特定的问题。大部分有经验的软件 工程师都会这样建议:“使用哪种工具不是最重要的,关键是掌握思想,就好像 Java 和.Net 两 大阵营的不同程序员都觉得自己的平台优秀一样,没有绝对的标准,也正如有的开发人员是用 Pascal,有的用 C++,但都可以做出很优秀的软件„„”。 笔者认为,掌握分析建模的思想最重要的,否则只会使用工具,最终设计出来的东西就好像 没有思想的灵魂,空洞而又不可靠。在此基础上,读者可以根据自己的特定需求以及软件自身的 特点,选择合适特定应用的工具。甚至有很多优秀的开发人员再尝试过许多不同的 CASE 工具后, 会根据自己特定的需求开发自己的一些辅助工具。 在这里笔者将自己的切身体验归纳在下面的表中,仅代表个人观点,不一定恰当,希望能起 到抛砖引玉的作用。学习使用不同的 CASE 工具可以起到“增长见识”的作用,也可以更全面的 掌握软件建模分析技术。 批注 [e2]: 这里的文字为添加内容 作者:姜江 error 8 表 1-1 为主流建模分析软件在某些方面的比较: 表 1-1 主流建模分析工具比较 工具 名称 易使用性 功能特性 图形 能力 支持平台 生成文档 版本控 制 Pow er Desi gner 常用功能 上手较为 容易,操 作简便, 但高级功 能需要对 PowerDes igner 非 常熟悉, 不易掌握 提供了对多种建模技术 的支持(概念数据模型 CDM,物理数据模型 PDM, 业 务流 程 模型 BPM,面向对象模型 OOM,以及自由模型 FEM)。继承了 Sybase 在数据库方面的一贯优 势,在数据库建模方面 有非常全面的建模和整 合能力。加强了横贯所 有建模技术的元数据集 成,模型之间可非常方 便的互相转化,实现不 同类型模型的无缝连 接。支持对模型元语言 的用户自定义,提供扩 展属性和 VB 脚本处 理,用户可以通过自己 定制源文件生成特定需 求的代码。面向对象建 模和 Rose 相比使用较 为 方 便 , 由 于 PowerDesigner 早期版 本中仅仅支持三种或者 更少的 UML 图形,所 以现在也经常会被误 解,被认为仅仅是数据 库建模工具。 具有 非常 强的 图形 布局 和组 织能 力, 使图 形较 为直 观清 晰, 但美 观性 定制 方面 不如 Micr osoft Visio 支持超过 40 种 ( 包 括 不 同版 本)数据库的建 模,物理数据库 模 型 可 以 随意 在各种 DBMS 之间切换,做到 “ 数 据 库 平台 无关性”。完全 兼容 ebXML、 J2EE、Web 服务 以及.Net 平台 自带 Report 报 告生成工 具,出了 提供标准 的模板之 外,在报 告定制方 面也有着 突出的表 现 自带 Reposit ory,具 有 较好 的 版本 控 制解 决方 案 ,不 过 有一 些 Bug。 Rati 由于软件 属于高端建模分析软 图 具 有 最 好 的软 需要独立 无 自带 作者:姜江 error 9 onal Rose 体系非常 庞大,所 以使用上 手比较困 难 件,功能非常强大,设 计软件分析建模工具的 几乎所有方面,具有非 常庞大的体系,在 RUP 理论框架和 IBM 的强 势支持下,获得最广泛 的认可,在市场上占有 非常大的分额。对 UML 支 持 非 常 全 面 , Rose2003 中又 加入了 设计模式的支持。此外, Rational 套件中包含的 从需求、分析设计到测 试的一系列 工 具 ,对 Rose 的进一步推广也 起到了非常好的强化作 用。在数据库建模方面 和 PowerDesigner 有较 大的差距。 形、 美观 性和 布局 能力 较差 件平台支持性, 得 到 大 部 分厂 商支持,通过一 些 插 件 可 以同 Delphi 等开发 工 具 的 集 成应 用 。 完 美 支持 J2EE,XDE 提 供了同.Net 开 发工具的整合。 安装 Rational Soda,功 能较为强 大,但定 制能力不 够强 的 版本 控 制系 统 ,但 同 Rationa l Clear Case 可 完 美整 合 ,同 时 支持 VSS 等 版 本控 制工具 Toge ther 易于上 手 ,但 Together 本身产品 体系比较 庞大,不 易完全掌 握。 主要应用在面向对象分 析建模方面,支持所有 主要 UML 图形,通过 Together Live Source 可以保持代码与模型的 同步,,支持设计模式, 同时也与领先的需求管 理工具进行了集成,其 中包括 Borland CaliberRM 与 Rational RequisitePro,支持与 大多数主流开发环境集 成,但速度方面与 Rational XDE 一样,过 于缓慢,一般电脑配置 无法承受,此外还在 QA 图形 操作 美观 方 便 , 但在 布局 方面 没有 提供 太强 大的 功 能。 Together ControlCenter 支持 Java , C++ , CORBA , IDL,Microsoft Visual Basic 6, Visual Basic .NET 以 及 C#。在与开 发 环 境 的 继承 方面,Together 目前支持 JBuilder,Ecli pse,SAP Netweaver Studio, 提供了强 大的、可 以定制的 文档生成 能力,其 中包括多 种文档格 式与定制 模板的能 力。 Contro lCente r与SCC 符合型 版 本控 制 系统 进 行了 集 成, 其 中包 括 Borlan d StarTe am® 与 Ration al 作者:姜江 error 10 方面提供了一些方便的 功能。 Visual Studio.NET 以 及 C++Builder 等 主 流 开 发工 具。 ClearC ase。 Erwi n 上手容 易,但同 PowerDes igner 在 操作习惯 方面有一 定区别, PowerDes igner 用 户与 Erwin 用 户相互转 换学习不 易习惯 (仅代表 个人观 点) 。 是一款优秀的数据库设 计软件,有着强大理论 体系的支持,曾经多次 被国外有关方面授予各 种奖项,可以进行逆向 工程、能够自动生成文 档、支持与数据库同步、 支持团队式开发,所支 持的数据库多达 20 多 种。在近几年也加入了 对 UML 的支持。作为以 系统建模为主的工具, ERwn 在最新版本中也 增强了其"一站式"系统 建模的功能。 图形 操作 方 便, 但在 美观 性布 局方 面没 有提 供太 强大 的功 能。 支持大多数(包 括不同版本)数 据库的建模,同 样 的 模 型 能够 生 成 多 个 数据 库,或将应用从 一 个 数 据 库平 台 移 植 到 另一 个数据库平台, 做到“数据库平 台无关性”。 ERwin 的 报表浏览 器提供预 制的和可 定制的报 表格式, 可用多种 格式输 出,如 Word 和 Excel,还 包括易于 使用的图 形化报表 书写器, 控制报表 外观。 Model Web Publishe r 可以发 布 Web 静态模型 信息。 使用 ModelM art 扩 展 Erwin, 可以访 问、共 享、并 重用对 象与模 型,包 括:建 立子模 型、版 本控 制、模 型合 并、影 响分析 和安全 性等。 ModelM art 独 立于平 台和网 络,可 以方便 地集成 到现有 环境 中。 Micr osoft Visi o 继承了 Microsoft Office 一 贯操作方 便的特 适合制作专业的演示图 形,但模型能力不强(例 如:一些版本不支持代 码生成和正反向工程), 设计或分析规模较大的 因为 是专 业作 图工 具, 主 要 用 途 为作 图,建模方面涉 及不多,不支持 面 向 对 象 代码 生成,数据库正 不支持 不支持 作者:姜江 error 11 性,可以 作为入门 级建模学 习工具, 技术门槛 较低,使 用非常方 便 系统时,速度会急剧下 降,同时有很多“Bug” 具有 非常 强的 图形 美化 布局 能 力。 向 工 程 支 持数 据库类型较少 1.4 使用 PowerDesigner 进行数据库建模 PowerDesigner 具有非常强大的数据库建模能力。包括概念数据模型(CDM)和物理数据模 型(CDM)两个部分。独立于 DBMS(数据库管理系统)的概念数据模型,可以将被看作对现实 世界的抽象理解,创建概念数据模型时可以完全不考虑最终选择的 DBMS,脱离物理实现的考虑。 设计数据库通常是从概念模型开始设计。在概念设计这个层次上,不需要考虑物理实现的细节。 设计好 CDM 之后,可以通过 CDM 到物理数据模型(PDM)的转化。然后再根据具体的 DBMS 的特点对物理数据模型进行定制,完成物理实现,这种清晰的思路比较容易理解和控制。 而物理数据模型(PDM)则是对概念数据模型进行物理实现,是需要和 Microsoft SQL Server 、 Oracle 等具体的 DBMS 打交道的模型。因此,PDM 将比 CDM 更加具体、细节,并且具有数据库 相关性。 这里以 PowerDesigner 中物理数据模型为例,列出其主要特点:  方便直观的图形建模功能;  对超过 40 种 DBMS 的广泛支持;  对数据库各种元素建模的全面支持;  不同 DBMS 之间轻松切换,避免了以往不同数据库设计造成的大量重复工作,以及技术 屏障;  数据库建立、修改脚本的自动生成,反向工程以及模型与数据库同步的能力;  定制并生成数据库测试数据;  可以与概念数据模型、面向对象模型之间进行转化;  用户可以修改 DBMS 定义源文件,为生成灵活的可以扩展的脚本提供了强力的支持;  „„ 关于使用 PowerDesigner 进行数据库建模能够为用户带来的价值,可以参考:  前言;  第二章:概念模型的前言部分;  第三章:建立物理数据模型(PDM)的前言部分; 作者:姜江 error 12 1.5 PowerDesigner 的使用环境 启动 PowerDesigner,将看到和图 1-5 十分相似的窗口。 图 1-5 PowerDesigner 建模环境 如上图 1-5 所示,Workspace 是当前用户操作的工作环境,而 Workspace 的子目录则是当前 Workspace 包括的模型,以及模型中的模型元素。 GraphicModel 就是当前用户建模的图形模型,可以通过对该图形操作完成大部分建模工作。 工具栏的含义如表 1-2 所示。 表 1-2 PowerDesigner 各工具栏介绍 工具 描述 Standard 最常用的文件(File)和编辑(Edit)菜单的快捷工具栏 Diagram 最常用的图形管理(Diagram Management)的快捷工具栏 View 最常用的显示管理(Display Management)的快捷工具栏 Layout 最常用的图形布局、图符管理的快捷工具栏 Format 最常用的图符格式化的快捷工具栏 Window 最常用的窗口导航快捷工具栏 作者:姜江 error 13 Palette 一个特殊的工具栏,主要用于操作模型或者包中的模型图形 Report 报告(文档)的窗用快捷工具 Check 模型检查操作的最常用的快捷工具栏 Repository Repository(数据仓库)操作的最常用的快捷工具栏 Predefined Symbols 分配给图符的默认形状的快捷工具,点击之后弹出如图 1-7 所示窗口 在工具栏上点击鼠标右键,弹出工具栏选择菜单,如图 1-6 所示。 图 1-6 工具栏右键弹出菜单 图 1-7 Palette 面板 如图 1-7 所示,在弹出的菜单中选择 Customize,弹出工具栏定制窗口,如图 1-8 所示。 图 1-8 工具栏定制窗口 要显示特定的工具栏,选择名称前面的复选框,如果要创建新的工具栏,点击【New】按钮, 弹出新建工具栏窗口,输入名称,如图 1-9 所示。 作者:姜江 error 14 图 1-9 “New Toolbar”窗口 选择刚刚新建的工具栏,在窗口 Toolbars 中点击【Customize】按钮,弹出如图 1-10 所示的 定制工具栏窗口: 图 1-10 “Customize Toolbars”窗口 选择不同的 Categories,右端显示各个工具栏包含的按钮,将需要的按钮拖放至刚刚建立的新 的工具栏,如图 1-11 所示。 图 1-11 新建工具栏 1.5.1 使用浏览树(Browser) 浏览树中提供了当前 Workspace 的层次结构视图,可以根据树中节点的图标判断模型对象的 类型,树的根节点是 Workspace 节点,Workspace 中可以包含目录,模型,以及多模型报告等。每 个模型又可以包含多个包和图形(Diagram)。 浏览树中主要图标(但不是全部)其含义参考表 1-3。 表 1-3 浏览树主要图标及其含义 Icon 节点含义 Icon 节点含义 Workspace OOM Folder OOM package CDM OOM diagram CDM package BPM 作者:姜江 error 15 CDM diagram BPM package PDM BPM diagram PDM package Multi-model report PDM diagram FEM(free model) FEM package FEM diagram 默认情况下,打开 PowerDesigner 会自动装载最后一次使用的 workspace,如果需要修改这一 参数,选择【Tools】→【 General Options】,弹出 General Options 窗口,去掉 Auto-reload last workspace 前面的复选框后点击【OK】按钮确定,如图 1-12 所示。 图 1-12 “General Options”窗口 在浏览树中创建对象 在浏览树中创建对象的操作方法如下: 1. 鼠标右键 Workspace 节点,或者模型、包和某个对象类型的节点 2. 在弹出的菜单中选择【New】→【Object type】 ,其中 Object type 为具体的对象类型 3. 弹出对象属性窗口,输入 name 和 code 4. 点击【OK】按钮确定,新创建的对象出现在各子类型的节点下。 默认情况下,通过浏览树创建的对象在模型图形中没有创建图符,可以通过直接将浏览树中 的对象拖放至模型图形中。 通过浏览树在模型图形中查找图符 在浏览树中根据对象的类型,选定要查找的对象,鼠标右键,在弹出的菜单中选择 Find in diagram,或者选择对象后直接使用快捷键【CTRL+SHIFT+F】。 作者:姜江 error 16 管理 Workspace Workspace 定义了使用 PowerDesigner 建模时的信息集,workspace 是存放在本地的文件,后 缀名为 SWS,可以创建多个 workspace,但同一时刻只能有一个 workspace 处于打开状态。 默认情况下,PowerDesigner 会打开一个 workspace,创建新的 workspace 时,必须关闭当前 workspace,PowerDesigner 会自动创建一个新的 workspace。 1.5.2 构造 workspace 可以在 workspace 中增加目录和模型来构建 workspace。除了在当前 workspace 中新建对象, 还可以将对象添加到当前 workspace 中。这些对象可能是:  模型:CDM,PDM,OOM,BPM 或者 FEM  多模型报告  其他 workspace(如果希望在当前 workspace 中引用其他 workspace)  可以被引用的外部文件,例如:Word 文档,或者 Excel 表格 操作方法如下: 1. 在浏览树中鼠标右键 workspace 节点 2. 在弹出的菜单中选择 Add,弹出标准的文件打开窗口,如图 1-13 所示,选择后点击【打开】 按钮: 图 1-13 将模型添加到当前 Workspace 1.6 模型的显示和布局 1.6.1 使用图形布局工具调整模型图形 使用过图形分析建模的朋友,可能曾经遇到过模型图形的布局问题,读者也许会发现这些图 形在你的屏幕上显得有些零乱,怎么办呢?一般的建模软件往往没有提供强大的图形布局显示功 作者:姜江 error 17 能,在使用 PowerDesigner 之前,我们不得不用肉眼观察几个图形之间是否对齐,还必须在不大 的屏幕上使用精度不太好的鼠标挪动图形,企图让图形看上去更加整齐有序一些,以便和客户或 者团队内的其他成员交流时不至于给人不好的感觉。 现在,读者将学会如何让图形看看起来井然有序,参考表 1-4。 表 1-4 Layout 工具栏各工具含义 工具 名称 实现的功能 Vertical 选择范围内的连线自动变为垂直线 Horizontal 选择范围内的连线自动变为水平线 Evenly Space Vertically 选择范围内的模型元素之间垂直等间距 Same Height 使选择范围内的模型元素具有相同的高度 Align Bottom 选在范围内的模型元素底部对齐 Align On Horizontal Axis 选在范围内的模型按水平轴中间对齐 Align Top 顶部对齐 Evenly SpaceHorizontally 选择范围内的模型元素之间水平等间距 Same Width 使选择范围内的模型元素具有相同的宽度 Align Right 向右对齐 Align On Vertical Axis 选在范围内的模型按垂直轴中间对齐 Align Left 向左对齐 Auto-Layout 自动布局 Fit to Page 使前模型中的所有模型元素布局在一个页面中 通过使用这些工具,相信你一定可以将看起来乱七八糟的图形变得井然有序。 1.6.2 对图形自动布局 Auto-layout 功能可以自动重新排列图形模型中的图符。模型中的图符将根据各自在图形中 的位置从左到右进行排列。操作的方法如下: 作者:姜江 error 18 1. 选择一个或者多个图符,如果项对所有图符自动布局,可以使用组合键 CTRL+A 全选 2. 选择菜单【Symbol】→【Auto-layout】 1.6.3 图形的组合以及取消组合 在 Word 中,有一个图形组合和取消足和的功能,这样的好处就是在必要的时候同时可以操 作多个图形,不需要的时候也可以再将分组取消,在 PowerDesigner 也有这个功能,在图形模型 中选择需要组合的图形,按住 Shift 选择多个图形,如图 1-14 所示。 图 1-14 选择多个模型图形 选择【Symbol】→【Group】,则上面选择的三个图形就组成为一组,以整体的形式操作,如 图 1-15 所示。 图 1-15 合并模型图形 取消组合时,只需要选择上述图形,选择菜单【Symbol】→【Ungroup】即可。 1.6.4 保护图形和取消保护 如果需要保护一个图形模型,既不修改,又不移动,则可以使用 PowerDesigner 的保护图形 功能,取消保护则返回原始的可修改状态。 操作的方式如下: 1. 选择一个或者多个图形 2. 选择【Symbol】→【Protect Symbols】,如果是取消保护,选择菜单【Symbol】→【Unprotect 作者:姜江 error 19 Symbols】 1.6.5 显示图符 不少使用 PowerDesigner 的朋友都遇到过这样一个问题,PowerDesigner 9.5 创建的模型如果在 PowerDesigner 9.0 中打开,则图形模型中的所有图符中都不显示内容,为了正确的显示图形模型, 有的用户删除 Diagram 中的所有图符,然后再手工从左侧的浏览树中将所有对象拖动到图形中, 实际上除了使用将对象拖动到图形中这个方法之外,还可以先删除所有的图符,在模型空白处鼠 标右键,在弹出的菜单中选择【Diagram】→【Show Symbols】,弹出显示图符选择窗口,选择好 之后点击【OK】按钮确定,如图 1-16 所示。 图 1-16 “Show Symbols”窗口 1.6.6 模型的显示参数选择 修改模型显示参数的方法如下: 1. 选择【Tools】→【Display Preferences】,如图 1-17 所示。 作者:姜江 error 20 图 1-17 “Display Preference”窗口 2. 如图 1-17 所示,其中 Show page delimiter 表示显示页面之间的分页符线,选择 Snap to grid(对 齐网格)和 Display(显示网格),在 Size 编辑框中输入向 Grid 的大小,单位为 Unit 处 3 个单 选框(Inch、Millimeter 和 Pixel)选中的单位,如图 1-18 所示。 图 1-18 选择“Snap to gird”之后的模型图形 3. 如果希望当前显示参数修改对其他模型或者当前模型中其他的 Diagram 应用,点击【Display Preferences】窗口左下角的【Apply To】按钮,弹出 Select Diagram 窗口,如图 1-19 所示。 图 1-19 将显示参数应用到其他模型或者其他图形中 4. 在 Model 下拉列表中选择模型,并且选择要应用的图形,点击【OK】按钮。弹出确认窗口, 作者:姜江 error 21 如图 1-20 所示。 图 1-20 应用显示参数确认框 5. 点击【是(Y)】确定。 可以通过点击【Set As Default】将当前设置的显示参数设置为默认参数,如果要会恢复为默认 参数,点击【Default】。 对象视图参数选择 选择【Tools】→【Display Preferences】,弹出显示参数选择窗口,点击节点【Object View】, 窗口右方显示图形如图 1-21 所示,其中选项含义参考表 1-5。 图 1-21 选择“Object View”节点的参数 表 1-5 表的 Object View 参数的含义 参数 描述 None 截短 Name、code 使得图形显示符合符号的宽度 Truncation 以某个指定的长度截短 name 或 code 选择 Word wrapping 选项,规定 Length 为 4,如图 1-22 与图 1-23 所示为修改前后的图形比 较: 图 1-22 选择“Word wrapping”前的图形 作者:姜江 error 22 图 1-23 选择“Word wrapping”后的图形 要修改各中对象在模型中显示的内容,选择 Object View 中的子项,例如 Table,可以设置在 图形中显示哪些内容,如图 1-24 所示。 图 1-24 模型显示选项窗口 1.6.7 显示格式参数选择 1. 选择【Format】→【Table】(也可以是其他希望规定显示格式的对象),如图 1-25 所示。 作者:姜江 error 23 图 1-25 选择对象修改格式参数 2. 如图 1-25 所示,右方 Preview 部分预览显示格式,点击上图窗口右下角【Modify】按钮,弹 出符号格式修改窗口,该窗口分别包括 Size(图形的大小)、Line Style(线条的格式)、Fill(图 形的填充)、Shadow(图形的阴影)、Font(字体)和 Custom Shape(定制图形)六个 Tab 页 面,如图 1-26 所示。 图 1-26 图符格式的“Fill”页 图 1-27 图符格式的“Custom Shape”页 作者:姜江 error 24 3. 如图 1-26 所示,点击 Gradient 处的【Modify】按钮可以对图形填充设置渐变填充,也可以点 击 Picture 处的【Modify】,在弹出的窗口中选择图片文件填充图形。 4. 如图 1-27 所示,选择 Enable custom shape,在 Shape type 和 Shape name 下拉列表中选择合适 的定制图形 5. Size(图形的大小)、Line Style(线条的格式)、Shadow(图形的阴影)、Font(字体)其余四 个 Tab 页面中分别规定后,点击【确定】按钮,弹出下图确认窗口,如图 1-28 所示。 图 1-28 修改图符格式后弹出的确认建口 6. 选择对所有图形应用该格式变化或者选定的图符,也可以是新创建一个图符,例如,对选定 对象表 Teacher 的 Custom Shape 进行变化后的显示如图 1-29 所示。 图 1-29 修改“Custom Shape”后的图形 1.6.8 修改图形的显示格式 修改图形模型中图符的格式的操作方法如下: 1. 在图形模型中选择需要修改的图符 2. 选择【Symbol】→【Format】,或者鼠标右键点击图形,在弹出的菜单中选择 Format,如果选 择多个图形,则鼠标右键只会对鼠标点击的图形产生作用,因此可以在选择多个图形后使用 快捷键【CTRL+T】,弹出图形格式窗口 3. 弹出窗口同 Display Preference 中对 Format 节点下的特定对象的图形显示格式修改(点击 【Modify】)弹出的 Symbol Format 窗口完全相同,请参考前面内容。 1.6.9 布局 Attach points(接触点) 连接两个对象的线和对象接触的地方称为接触点(Attach points),选择对象之间的连线时, 接触点显示为小的黑色正方形图标,如图 1-30 所示。 作者:姜江 error 25 图 1-30 选择连线显示的接触点 布局接触点可以是连线的两端(接触点)分别移动至两个对象的中心,操作的方法为:选择 需要布局的连线,选择【Symbol】→【Disposition】→【Arrange Attach Points】,也可以在对 象连线上点击鼠标右键,在弹出的菜单中选择【Disposition】→【Arrange Attach Points】,调 整后图形如图 1-31 所示。 图 1-31 将接触点移动到对象的中心 1.6.10 布局 Attached text(附加文本) 布局 Attached text 可以使得用户拖动后的文本能够移回文本的默认位置操作的方法为:选 择需要布局的对象,选择【Symbol】→【Disposition】→【Arrange Attached Text】,也可以在 对象上点击鼠标右键,在弹出的菜单中选择【Disposition】→【 Arrange Attached Text】,调 整前后的后图形对比如图 1-32 和图 1-33 所示。 图 1-32 选择“Arrange Attached text”前的图形 作者:姜江 error 26 图 1-33 选择“Arrange Attached text”后的图形 1.6.11 图形的重叠、层次 图形建模时,有时图形之间会因为某些需要产生重叠,各个图形分别处于不同的层(Layer) 中,默认情况下:  新创建的可以包含文字的图符在的层在所有其他对象之上  新创建的连线所在的层在所有其他图符之后 可以使用表 1-6 所列命令修改特定对象显示的层次: 表 1-6 图形层次的命令及快捷方式 子菜单项 描述 快捷方式 Bring to front 选定对象图符出现在所有其他图符的前面 Ctrl+Page Up Send to back 选定对象图符出现在所有其他图符的后面 Ctrl+Page Down Bring forward 选定对象图符向前移一层 Shift+Page Up Send backward 选定对象图符向后移一层 Shift+Page Down 操作的方法为:选定图符对象,选择【Symbol】→【Order】→【Bring to front】等命令,或 者点击鼠标右键,在弹出的菜单中选择【Symbol】→【Order】→【Bring to front】等命令。 1.6.12 导出模型为图片 可以导出一个或者多个模型中的图符为外部的图片文件,可以导出为 EMF/BMP/DIB/RLE/ JPG/JPEG 等格式的文件,操作的方法如下: 1. 选择一个或者多个需要导出的图符,全选使用快捷键【CTRL+A】 2. 选中【Edit】→【Export in Color】表示导出图片包含颜色信息 3. 选择【Edit】→【Export Image】,弹出标准的文件保存窗口 作者:姜江 error 27 4. 在类型下拉列表中选择一种文件类型,选择保存路径,输入文件名称,点击【保存】。 1.6.13 导入图片文件 PowerDesigner 的模型中,可以导入一个或者多个外部的图片文件,支持 EMF/BMP/DIB/RLE /JPG/JPEG 等格式的文件,操作的方法如下: 1. 选择【Edit】→【Import Image】,弹出标准的文件打开窗口 2. 在类型下拉列表中选择一种文件类型,选择文件保存路径,选择文件,点击【OK】。当前模 型中出现导入的图片。 1.6.14 选择相关联的对象 如图 1-34 所示,选择对象 book,在该对象上点击鼠标右键,在弹出的菜单中选择【Edit】 →【Select Connected Symbols】,如图 1-35 所示,和该图连接的对象也都处于选中状态: 图 1-34 选择对象“book” 图 1-35 显示相关联的对象 1.7 模型的打印 模型创建的过程中,或者创建好之后,经常需要将模型的一部分或者全部打印出来供交流使 用或者备档,不过如果向前面那幅乱糟糟的图形,想必打印出来也起没有太大的用处。 在 PowerDesigner 9.5 中有两种打印模式 A.选择菜单【File】→【Print】,窗口如图 1-36 所示; 作者:姜江 error 28 图 1-36 “Print Diagram”窗口 不难看出,在 Preview 下面的各个页面中另外覆盖一张透明的卷边的纸张,点击这些页面, 会发现页面会在有无“卷边纸”两状态之间切换,有卷边纸表示需要打印,选择你需要打印的页 面,点击【OK】。 B.在图形模型中选择需要打印的图形,然后选择菜单【File】→【Print Selection】,弹出 的窗口中的 Preview 部分如图 1-37 所示。 图 1-37 打印窗口的“Preview”部分 在 Preview 下面的各个页面中和 A 方式相同,选择你需要打印的页面为“卷边纸”的状态, 点击【OK】。 1.8 快捷方式 1.8.1 快捷方式的概念 软件分析和设计时,经常需要在不同的模型之间“共享”某些对象的定义,通常采用的一种 方式就是在不同模型之间复制这个需要共享的对象。但是当这个共享对象的定义发生改变时,因 为不能保证所有复制的对象都能保持同步,所以经常会引起一些对象更新的问题。尤其是在团队 开发中,这种情况造成的后果有时相当严重,这也是目前软件版本控制出现和流行的主要原因, 不过我们这里要讲述的不是版本控制,而是“快捷方式”,PowerDesigner 中,可以使用快捷方式 在不同的对象之间引用对象,对 PowerDesigner 中的快捷方式,完全可以根据 Windows 中快捷方 式来理解。 作者:姜江 error 29 有时我们需要复用某些对象的属性,并且让其他对象继承这些属性。例如:实体 Person 有四 个属性:Name,Age,Nationality 和 Address,当我们创建另外两个实体 Customer 和 Employee 时, 这两个实体都继承 Person 的属性,因此,Person 这个实体有可能会在多个其他的模型中被复用, 于是很多软件开发工具根据这种思路建立了各自的 Library(库),实际上这是一种资源共享库。 在 PowerDesigner 中,我们也可以根据自己的日常积累建立自己的对象复用库(Library of reusable objects),在需要复用的时候,使用快捷方式引用即可。下图为两个不同模型间快捷方式的使用, 快捷方式在图形中的显示和 Windows 的显示风格类似,都是在左下角有一个箭头图标,如图 1-38 所示。 图 1-38 快捷方式的图形显示 这部分讲述 PowerDesigner 中的快捷方式,包括快捷方式的定义、显示、使用以及快捷方式 的使用。 PowerDesigner 中,可以使用快捷方式在不同的对象之间引用对象,也可以在同一个模型中的 不同图形(Diagram)中或者同义图形中的不同位置使用快捷方式。对该共享对象的定义进行修改 后,该对象在任何位置的引用(即快捷方式)的属性都会同步更新。 快捷方式是对“目标对象”(Target object)的一种引用,当然目标对象可能在同一个或者不 同的模型或者包中。创建或者存储目标对象的模型或者包被称为“目标模型”(Target model),通 常情况下,目标模型不是一个工作模型(Working model,即需要实际使用的开发项目的模型), 而是对象复用库(Library of reusable objects)。不同领域的开发人员都可以根据自己的需要建立特 定的对象复用库,最大化的提高工作效率和标准化程度。 实际使用时,只需要在母报模型中拷贝目标对象,然后在引用模型和包中,粘贴为快捷方式。 快捷方式分为两种:  内部快捷方式(Internal):在一个模型的不同的包中使用的快捷方式。  外部快捷方式(External):在不同模型中使用的快捷方式。 PowerDesigner 中的有些对象是模型中的全局对象,因此不能为这些对象创建内部快捷方式, 只能创建外部快捷方式,例如 Business rules 等类型的对象。 如表 1-7 所示,该表列出不支持快捷方式或者外部快捷方式的对象。 作者:姜江 error 30 表 1-7 各模型中不支持快捷方式的对象 模型 不支持的快捷方式的对象 不支持外部快捷方式的对象 CDM — Data Item(数据项) OOM Start,end,decision,synchronization,junction, point,transition,state Message(消息) BPM Start,end,decision,synchronization,resource flow Flow(流) 1.8.2 创建并操作快捷方式 创建快捷方式的方法有两种,一种是先拷贝(Copy),然后粘贴为快捷方式(Paste as shortcut); 另外一种是使用拖放(Drag and drop)的方式。 创建快捷方式必须遵循以下几个规则:  不能在目标模型或包中创建快捷方式  不能在当前命名空间之外创建数据项(Data Item)的快捷方式  在同一个模型或包中不能创建同一个对象的多个快捷方式  不能在两个快捷方式之间创建连接(Link),但是可以保留快捷方式在目标模型中的连接  不能在实体和继承实体之间创建连接 创建快捷方式时,不同的情况结果也不同,请参考表 1-8。 表 1-8 不同情况下创建快捷方式的结果 引用快捷方式的模型或包 PowerDesigner 创建的对象 不包含快捷方式 快捷方式和快捷方式的图符 已经包含快捷方式但是没有快捷方式图符 快捷方式的图符 包含快捷方式和图符 快捷方式的同义词 创建快捷方式的步骤如下: 1. 在目标模型中选择目标对象,例如:Person 2. 选择【Edit】→【Copy】,或者按快捷键【Ctrl+C】,或者在该对象上点击鼠标右键,在弹出 的菜单中选择【Edit】→【Copy】 3. 切换到需要使用快捷方式的模型或者包中(Referencing model or package) 4. 选择【Edit】→【Paste as shortcut】,或者在图形的空白位置上点击鼠标右键,在弹出的菜单中 选择【Edit】→【Paste as shortcut】,也可以使用快捷键【Ctrl+K】,如图 1-39 所示。 作者:姜江 error 31 图 1-39 创建对象“Person”的快捷方式 如图 1-39 所示,因为在前面的例子中,我们已经创建了一个 Person 的快捷方式,因此,这里 快捷方式显示为;“Person:2”,表示同义词。 5. 双击该快捷方式图形,或者鼠标右键,在弹出的菜单中选择 Properties,弹出快捷方式属性窗 口,如图 1-40 所示。 图 1-40 快捷方式的属性窗口 点击【Target Object Properties】工具 ,弹出目标对象属性窗口,如图 1-41 所示。 图 1-41 打开快捷方式的目标对象的属性窗口 作者:姜江 error 32 点击【Target Model Properties】工具 ,弹出目标模型属性窗口,如果目标对象不是在包中, 则点击【Target Package Properties】工具 以后也显示目标模型属性窗口,否则显示包的属性窗 口。 6. 点击快捷方式属性窗口中的【Change Target Objects】按钮,弹出选择目标对象选择窗口,选 择需要改变的对象,点击【OK】按钮,如图 1-42 所示。 图 1-42 改变快捷方式的目标对象 只有当目标模型处于打开状态的时候才可以改变快捷方式的目标对象。通常情况下,发生以 下情况时,快捷方式的属性窗口显示状态部分为“Status:Not Found”:  目标对象被删除  目标对象被复制到另外一个包中,随后在最初的那个包中被删除  目标模型以另为一个模型名称保存 在这种情况下,如果目标模型中已经不存在该对象,则可以删除该快捷方式。如果以前的目 标对象仅仅是该了名称或者被移动到另外的包中,也可以选择另一个目标对象。选择新的目标对 象时,必须遵循以下规则:  新的目标对象不能是现在的目标对象  目标对象的类型必须和以前的目标对象相同,例如实体的快捷方式不能指向数据项  如果当前包中另外一个快捷方式已经指向了某个对象,那么此时这个对象不能被指定为 新的目标对象。 使用拖放方式创建快捷方式: 可以在左侧浏览树或者图形模型窗口部分使用鼠标左键拖放的方式创建快捷方式,操作的方 法是在拖放的时候同时按着 CTRL+SHIFT 组合键。操作方法如下: 1. 在浏览树中选择目标对象 2. 在鼠标左键拖动该对象的同时,按住 CTRL+SHIFT 组合键 3. 在要使用快捷方式的目标模型或者包的模型图形中释放鼠标 也可以在选择目标对象之后,使用鼠标右键拖动目标对象,拖动到使用快捷方式的位置上释 作者:姜江 error 33 放鼠标,此时会弹出一个上下文菜单,在弹出的菜单中选择 Create Shortcut(s) Here,如图 1-43 所 示。 图 1-43 右键拖放目标对象时弹出的菜单 保存 Referencing model 保存使用快捷方式的模型,即参考模型(Referencing model)时,同时也保存了快捷方式的 目标模型的路径,目的是保持引用对象和目标对象之间的数据同步。在保存参考模型之前,必须 先保存目标模型。 连接快捷方式 在参考模型中,不能在两个快捷方式之间创建连接(Link),但是可以在快捷方式和参考模型 的对象之间建立连接。也可以在参考模型中,保留两个快捷方式之间已经存在的连接,但是连接 的快捷的方式不在图形上使用特殊的快捷方式的图形标志。操作方法如下: 1. 选择目标对象和对象之间的连接(选择多个对象的同时按住 SHIFT 键),实例模型如图 1-44 所示。 图 1-44 实例模型 2. 拖动鼠标左键的同时按住 CTRL+SHIFT,在适当的位置上释放鼠标左键,显示图形如图 1-45 所示。 图 1-45 保留连接的快捷方式 更新快捷方式之间的连接 在发生以下几种情况时,可以使用更新参考模型,从而显示快捷方式之间的连接:  如果创建快捷方式时,没有为连接对象的连接创建快捷方式  虽然在参考模型中创建了连接的快捷方式,但是模型的图形中没有显示(有可能 Symbol 被删除)  在创建快捷方式之后,目标模型中的对象之间创建了连接,但是没有被拷贝到参考模型 中 作者:姜江 error 34 操作的方法为:在参考模型中选择【Tools】→【Complete】,则模型图形中会显示快捷方式之 间的连接。 1.8.3 快捷方式的查看 A.显示目标对象的所有快捷方式 可以通过查看目标对象的属性查看当前目标对象的快捷方式,即有哪些处于打开状态模型和 包引用了该目标对象,操作的方法如下: 1. 双击目标对象 Person,弹出目标模型属性窗口 2. 点击 Dependencies 属性页 3. 在该页下方点击 Tab 页面 Shortcuts,如图 1-46 所示。 图 1-46 在 Dependencies 页中的 Shortcuts 页查看对象的快捷方式 注意:只有当前 Workspace 中处于打开状态的模型或者包的快捷方式才会在这里显示,如果 当前模型中唯一使用该目标对象的模型处于关闭状态,则该对象的 Dependencies 属性页中甚至不 会包含一个 Shortcuts 的 Tab 页,关闭包含快捷方式的模型,如图 1-47 所示。 作者:姜江 error 35 图 1-47 如快捷方式所在的模型处于关闭状态“Shortcuts”页不显示 显示某种对象的快捷方式,可以显示当前某行模型或者包中某种特定对象的所有快捷方式, 操作的方法如下: 1. 选择【Model】→【Item】(如 Entity,Relationships 等等),弹出相应了对象列表窗口 2. 点击【Customize Columns and Filter】工具 ,在弹出的窗口中选中 Class Name 复选框,点 击【OK】。 3. 点击【Include Shortcuts】工具 ,则所有该对象类型的快捷方式都显示在该列表中,因为不 能在当前的包中被修改,因此显示为灰色,Class Name 列显示对象的类型(如 Entity 或者是 快捷方式),如果点击【Include Sub-Packages】工具 ,则当前模型中或者包的所有子包的 快捷方式也会显示在列表中,如图 1-48 所示。 图 1-48 选择“Include Shortcuts”后快捷方式以灰化形式列出 B.通过快捷方式列表窗口操作快捷方式 作者:姜江 error 36 除了在模型图形和浏览树中对快捷方式操作之外,还可以选择【Model】→【Shortcuts】,弹 出 List of Shortcuts 窗口,如图 1-49 所示。 图 1-49 快捷方式列表窗口 双击行首的箭头,或者选择行后,点击【Properties】工具 ,可弹出快捷方式属性窗口。 如果需要改变某个快捷方式的目标对象,或者当某个快捷方式的状态列显示为 Not Found 时, 选择需要改变的快捷方式所在的行,点击【Change Target Object】工具 ,弹出改变目标对象窗 口。 如果需要添加新的快捷方式,点击【Add shortcuts】工具 ,弹出 Add Shortcuts 对话框,选 择需要添加为快捷方式的对象,点击【OK】按钮,如图 1-50 所示。 图 1-50 添加新的快捷方式 1.8.4 目标模型 选择【Model】→【Target Models】,弹出目标模型列表窗口,如图 1-51 所示。 作者:姜江 error 37 图 1-51 目标模型列表窗口 如果目标模型在当前 Workspace 处于关闭状态,可以选择目标模型所在的行,点击【Open Model】工具 ,即可在当前 Workspace 中打开目标模型。 如果要切换目标模型,则可以点击该窗口中的【Change Target Object】工具 ,弹出模型选 择窗口,如图 1-52 所示。 图 1-52 选择要切换的目标模型 如果目标模型处于打开状态,则快捷方式会根据当前模型的显示属性显示目标对象的相关属 性,如图 1-53 所示。如果目标模型处于关闭状态,则仅仅显示快捷方式的名称,如图 1-54 所示。 图 1-53 目标模型打开时的快捷方式 图 1-54 目标模型关闭时的快捷方式 作者:姜江 error 38 如果要删除目标模型,则选择要删除的行,点击鼠标右键,在弹出的菜单中选择 Delete 或者 点击窗口中的【Delete】工具 ,弹出警告窗口,提示如果删除目标模型,则当前参考模型中所 有指向该目标模型的快捷方式都将被删除,如图 1-55 所示。 图 1-55 删除目标模型确认对话框 1.8.5 生成快捷方式(Generate shortcuts) 默认情况下,从当前模型转化为其他模型时,模型中的快捷方式会自动生成适当的对象,不 过用户也可以根据自己的需要选择保留外部快捷方式和目标模型之间的连接,而不是生成对象, 即选择 Generate 的方式为 Short,而不是 Object。要设置 Generate 的生成方式,进入快捷方式 的属性窗口,在 Generate as 下拉列表中选择 Shortcuts 或者 Object,如图 1-56 所示。 图 1-56 生成其他模型时将快捷方式生成为对象或快捷方式 外部的快捷方式(External shortcut)依赖另外一个模型中的目标对象。外部快捷方式允许 你在不同模型之间共享对象。可以在 Target Models 属性页中选择生成的模型,并且取出外部快 捷方式相对应的目标对象。这样外部快捷方式才能够被正确的连接到正确的目标模型中。 在 Target Models 属性页中,Target Models 指的是原始的快捷方式的模型(不可编辑); Generated Models 允许你选择该模型生成的快捷方式的目标模型。这个模型生成过程允许你在生 成的模型中定义快捷方式的目标对象。如图 1-57 所示。 正确的快捷方式生成的顺序为:  模型 1 是模型 2 快捷方式的目标模型  模型 1 生成了模型 1.1 作者:姜江 error 39  模型 2 准备通过在 Target Model 属性页中关联恰当的参数,生成模型 2.2 图 1-57 生成快捷方式的实例 如果模型 1 在 workspace 中仍然处于打开状态 目标模型显示原始模型 Model1 以及它的路径。在你第一次用 Model1 生成模型时,Generated Models 列显示最后生成的模型,下此用 Model1 生成模型时,Generated Models 列显示最后选择 的那个模型。可以修改 Generated Models,从而确保快捷方式的正确连接。 如果模型 1 在 workspace 中处于关闭状态 目标模型显示原始模型 Model1 以及它的路径。而 Generated Models 处显示为。当你 点击 Generated Models 列时,原始的目标模型 Model1 自动在 workspace 中打开,以确保能够查 找到从 Model1 生成的模型,可以使用下拉箭头选择模型 Model1.1,新的目标允许在 Model2.2 中 正确的创建快捷方式的连接。 最后,模型 2.2 中的外部快捷方式就通过连接到模型 1.1 而正确的生成。 在生成模型属性窗口的 Target Models 属性页中,可以选择生成的模型作为目标模型,这样 可以的目的是从生成模型各个不同的版本中连接正确的目标模型。 选择【Tools】→【Generate model type】,其中 model type 为 OOM、PDM 或者 CDM,在弹出 的生成模型窗口中进入 Targets Models 属性页,列表中显示目标模型,如图 1-58 所示。 图 1-58 生成快捷方式选项窗口的“Target Models”页 当然,如果模型中所有的快捷方式都是“Generate as Object”,则上图中就不会显示任何目标 模型,因为 PowerDesigner 会自动将所有的快捷方式都生成对象。 作者:姜江 error 40 1.8.6 快捷方式的应用实例 在图形布局上,还有一个困惑很多人的问题:某公司内部系统涉及到 200 张左右的表,但是 几乎所有的表都和“员工”这张表有关系,这就意味着在图形模型上几乎所有的表都要外键引用 “员工”表,所以,最后产生的模型成为蜂窝状,如图 1-59 所示(笔者刚开始使用建模工具进行 数据库建模的一张缩略图): 图 1-59 使用快捷方式调整图形之前的一个模型实例 尽管笔者已经使用了前面刚刚介绍过的十几个布局工具让每个局部看起来都比较有序。但是, 图形从整体上来看却是一团糟,这也使得建模人员的操作效率直接降低。这样的模型根本无法在 一张纸上打印出来,通过图形清晰的了解各个表之间的关系变得十分艰难。 下面使用快捷方式来解决这个问题: 1.选择使用最频繁的表(最有可能导致连线交叉拥挤的那些表),也就是系统中占核心地位 的表,按 Ctrl+C 或者通过右键【Edit】→【Copy】 2.在你需要引用这个表的地方按 Ctrl+K 点击右键,在弹出的菜单中选择【Edit】→【Paste as Shortcut】,这时,图形中会出现与原表几乎一模一样的一张表,只有表的名称有一点区别, 就是名称改为:tablename:n,其中,tablename 为原表的名字,n 表示第 n 个快捷方式。 3.双击该图形,你将会发现不能在该图形中对原表进行修改,因为它仅仅是个快捷方式。 4.把该表当作原表一样看待,对其作相应的外键定义。 如图 1-60 所示,是笔者使用了快捷方式后达到的缩略图的一部分: 作者:姜江 error 41 图 1-60 使用快捷方式调整后的模型图形 这样,就可以把原本复杂的图形分离开来,使得图形之间的关系变得更加清晰。在某些特定 的项目中,可以通过快捷方式将不同部门或者不同涉及不同功能模块的数据表分而治之,既方便 建模人员操作,也方便打印,促进建模人员直接以及与客户的交流沟通。 而实际生成的建库脚本并不会因为图形模型中不同的地方都出现这张表而进行多次的定义, 所以我们不必担心表的重复,PowerDesigner 会自动帮我们检查。 如果刚才选择的不是 Paste as Shortcut(Ctrl+K),而是 Paste(Ctrl+V),那么 PowerDesigner 会自动生成另外一张表:tablenameN,其中,tablename 为原表的名字,N 表示经复制的第 n 个表, 从本质上而言它是同快捷方式完全不一样的。 1.9 对象复制 PowerDesigner 允许在不同模型之间拷贝对象,同时还保留复制对象和目标对象(被拷贝对象) 之间的连接。 快捷方式引用另外一个模型中的对象时,只有目标模型处于打开状态时,快捷方式引用的对 象只能看到一部分定义信息(名称、代码和类型)。而 PowerDesigner 中有些对象的属性十分重要, 因此,使用快捷方式对于某些应用不是很符合实际。例如,CDM 模型中的数据项的不允许使用快 捷方式,因为如果目标模型处于关闭状态,则在参考模型中不能获得数据项的数据类型属性。 快捷方式引用另外一个模型或者包中的对象时,不能直接对这些快捷方式进行改变,只有目 标对象能被修改。这便存在着很大的局限性,例如一个客户(Client)表可能被不同的模型或者包 引用,Client 表包含着尽可能完整的客户信息(姓名、地址、电话号码、手机号码、传真等等)。 在一个模型中,可能只需要该客户表的姓名和地址列,而另外一个表中又可能需要姓名和手机号 码,但是却希望保留这些表同原始的 Client 表的连接关系。而快捷方式显然无法做到这一点。 PowerDesigner 中使用对象复制(Object replication)技术可以满足这一需要。 作者:姜江 error 42 1.9.1 对象复制的概念 PowerDesigner 中可以通过在同一个或者不同模型间复制对象的方法在几个模型之间服用对 象的定义。复制对象时,必须执行一个复制(Replication)动作,该操作会创建一个本地拷贝称作 原始对象的复制品(replica),同时保留该对象和原始对象之间的连接,目的是当源对象被修改时 能够自动更新复制品。 对象复制创建了和源对象完全一样的对象,并且当源对象的属性改变时,这种改变能够自动 传播到复制品中。默认情况下,复制品中的所有属性都会和源对象保持同步,而且在复制品的属 性窗口中也是只读的。如果用户希望某些属性不和源对象同步更新,就可以在复制品属性窗口中 打开复制(replication)属性窗口,在列表中将不需要保持同步的对象的复选框变为不选中状态。 这里有必要对 Replication(复制)的概念进行解释,Replication 是复制品(Replica)和源对 象(Original object)之间的连接的物化。在界面中 Replication 没有图形符号,但是却有属性窗口, 在 Replication 的属性窗口中可以设置不需要同步的复制的对性属性。 大部分对象都可以通过 Browser(浏览树)或者在模型图形中创建复制品,也可以对复制品 创建复制品,表 1-9 列出了可以各种类型模型支持复制的对象: 表 1-9 各种模型支持复制的对象类型 模型 图形 对象 CDM( Concept Data Model) — Entity/Data Item PDM( Physical Data Model) Physical Table/View/User/Role/Group/ADT Test Data Profile/Storage/Tablespace/Procedure Trigger template/Trigger template Item/Join Index /Sequence Database Package/DataSource/Synonym Multidimensi onal Cube/Dimension/Fact/DataSource OOM(Object Oriented Model) Class Class/Interface Use Case Use Case/Actor Sequence Object/Actor Activity Object State/Organization Unit/Object Component Component Object Object Deployment Component Instance Collaboration Object/Actor 作者:姜江 error 43 StateChart Event/Junction Point BPM(Business process Diagram) — Organization Unit/Resource/Message Format/ Data All modules — File/Business Rule/Domain 1.9.2 创建复制品 有两种创建复制品(Replica)的方法:  通过编辑(Edit)菜单使用 Replicate Objects 对话框  是用拖动鼠标的同时按住 ALT+SHIFT 的方式 不能为连接(Links)创建复制,但是可以在参考模型中在两个复制品之间创建连接。 A.通过 Replicate Objects 对话框创建复制品 通过 Edit 菜单中的 Replicate Objects 对话框创建复制对象可以允许选择一个或者多个当前处 于活动状态的模型或者包中的对象。如果选择的对象本身包含子对象(例如表包含列,类包含属 性和方法等),则子对象也会被复制。但是如果希望直接复制子对象,则必须使用鼠标拖动的方式 (因为这些子对象不会在 Replicate Objects 选择窗口中列出)。 在当前 Workspace 中创建或者打开两个模型,分别命名为 Replica From 和 Replica To,在模 型 Replica To 中 1. 选择【Edit】→【Replicate Objects】,或者在图形模型的背景处点击鼠标右键,在弹出的菜单 中选择【Edit】→【Replicate Objects】,弹出 Replicate Objects 对话框 2. 从 Model 下拉列表中选择复制对象源的模型(这里为 Replica From) 3. 从包下拉列表中选择复制对象源的所在的包(这里为默认 Replica From),如果希望显示当前 模型或者包中的所有对象,可以点击【Include Sub-Objects】工具 4. 在不同的 Tab 页中选择需要复制的对象,点击【OK】,如图 1-61 所示。 图 1-61 选择要复制的对象 作者:姜江 error 44 5. 点击【OK】按钮后弹出,在浏览树中模型 Replica To 中就增加了刚才需要创建的三个复制品: book、class 和 country,如图 1-62 所示。 图 1-62 在目录树中查看创建好的复制品 如图 1-62 所示,因为模型 Replica To 中已经有一个 teacher 的表,因此复制过来的表就自动 命名为 teacher2。可以发现,复制品的名称唯一性会在复制对象是自动检查,如果参考模型中已 经存在同名对象,则复制品名称自动重命名。 B.鼠标拖动创建复制品 可以在浏览树中使用鼠标拖放的功能将对象拖放到目标图形窗口中实现对象复制,拖放鼠标 的同时按住 ALT+SHIFT 组合键,操作方法如下: 1. 在浏览树中选择需要复制的目标对象 2. 拖动鼠标左键,同时按住 ALT+SHIFT 组合键,拖放的目的模型或者包中(可以是图形模型 中,也可以是拖放到浏览树中的合适位置上) 3. 释放素标左键,活动的模型或者包中出现了复制的对象 复制子对象(例如表中的列,或者类中的属性和方法)就应该使用鼠标拖放的方式复制。 使用鼠标拖放复制,也可以在选择需要复制的目标对象之后,用鼠标右键将对象拖放到合适 的位置上,释放鼠标右键,弹出菜单,在弹出的菜单中选择 Replicate Here,复制的效果也相同。 1.9.3 复制对象的属性&查看复制 A.复制对象的属性 作者:姜江 error 45 默认情况下,复制的对象的所有属性(attributes)和 collection 以及子对象都被复制,并且保 持和源对象之间存在连接,即可以保证复制对象同原始对象同步(除非因为要确保名称唯一性而 自动修改 name 或者 code)。复制品的属性窗口中的所有属性都是灰化不可以修改的,如图 1-63 所示。 图 1-63 复制对象的属性窗口的“Columns”页 如果不希望复制品中的所有属性都和源对象保持同步(desynchronize),操作的方法如下: 1. 双击复制品,弹出复制品属性窗口 2. 点击 Version Info 属性页,点击下方【Replication from】处的【Replication Properties】工具 3. 弹出 Replication Properties 窗口 4. 进入 Attributes 或者 Collection 属性页,不需要保持同步的对象前的复选框的钩去掉,如图 1-64 所示。 图 1-64 复制品属性窗口的“Attributes”页 作者:姜江 error 46 5. 如果要修改子对象的复制的属性,即规定某些属性步和源对象保持同步,则点击鼠标进入 Sub-Replications 属性页中 图 1-65 在“Sub-Replications”页设定要保持同步的子对象 6. 如图 1-65 所示,该属性页显示的子对象也处于灰化状态,表示不可以修改,选择某个子对象 所在的行,双击最左端的箭头或者点击【Properties】工具,弹出 Sub-Replications 属性窗口, 如图 1-66 所示,将不需要保持同步的复选框去掉,点击【确定】。 图 1-66 设定子对象要同步的内容 B.查看某个原始对象的复制(Replication) 操作方法如下: 1. 双击原始对象,弹出对象属性窗口 2. 点击 Dependencies 属性页,在 Dependencies 的 Tab 页面下方选择 Replication 属性页,如图 1-67 所示。 作者:姜江 error 47 图 1-67 在对象属性窗口的“Dependencies”页查看对象的复制 C.查看某类对象的复制品 可以在通过某类对象的对象列表窗口查看所有当前对象类型的复制品,操作方法如下: 1. 选择【Model】→【Item】,打开相应的列表窗口(例如:Tables) 2. 点击【Customize Columns and Filter】工具 ,在弹出的窗口中选择 Replica 的复选框,点击 【OK】按钮,如果 R 列选中表明该列为复制品(Replica),如图 1-68 所示。 图 1-68 在对象列表中查看某类对象的复制品 细心的读者也许会发现,表 class 没有显示为复制品,这时因为笔者在复制品列的属性窗口中 的 Version Info 属性页中 Replication from 处点击【Delete Replication】工具 ,这样便彻底脱离 和源对象之间的连接关系,修改模型 Replicate From 中原始对象 class 的属性,甚至删除,都不会 它产生任何影响。这说明两个对象之间已经没有任何连接。 D.复制品列表 作者:姜江 error 48 在 PowerDesigner 中大部分对象都会存在单独的列表窗口,Replication 也不例外,选择【Model】 →【Replications】,弹出 Replications 列表窗口,如图 1-69 所示。 图 1-69 复制品列表窗口“List of Replication” 和其他的对象列表的操作方式基本雷同,这里就不再赘述该列表窗口的使用方法,基本上在 这里可以完成对 Replication 的几乎全部操作。 1.9.4 复制的转化生成(Generating Replications) 当前模型转化为其他模型时,如果当前模型中包含复制(Replication),则可以在转化模型 时确保生成的模型中仍然保留复制品和原始对象之间的连接,这样就可以使得生成的模型中的复 制品也可以和原始对象保持同步。这需要第一次生成目标模型时,生成所有的原始对象,目的是 为了确保生成的复制品能够正确引用新的被引用的原始对象。 生成复制(Replication)之前,必须:  在 Replication 属性窗口中选择 Generate 复选框,否则复制品会被生成为普通的对象而 丧失和原始对象之间的连接关系,如图 1-70 所示。 图 1-70 复制属性窗口“General”页  在模型生成的属性窗口的在 Target Model 页面中选择 Generated model,以便能够为每 个复制品正确的取出相应的原始对象 作者:姜江 error 49 选择【Tools】→【Generate model type】,其中 model type 为 OOM、PDM 或者 CDM,在弹出 的生成模型窗口中进入 Targets Models 属性页,列表中显示目标模型,如图 1-71 所示。 图 1-71 在“PDM Generation Options”窗口中查看复制的目标模型 当然,如果模型中所有的 Replication 都没有选择 Generate 复选框,则上图中就不会显示任何 目标模型,因为 PowerDesigner 会自动将所有的复制品都生成对象。 下面的图形显示了从 OOM 生成一个 PDM 的过程,其中:  模型 OOM1 是模型 OOM2 复制品的目标模型  模型 OOM1 生成了模型 PDM1  模型 OOM2 是包含复制品的参考模型(Referencing model)  模型 OOM2 被转化为 PDM2,同时生成的 PDM2 中的复制品还保留了和 PDM1 中原始对象之 间的连接 图 1-72 生成复制的实例 如图 1-72 所示,作为目标模型,这样可以的目的是从生成模型各个不同的版本中连接正确的 目标模型。 1.10 常用快捷操作 1.10.1 系统快捷键 PowerDesigner 集成环境中有一些常用的快捷键可以加速用户的操作,如表 1-10 所示。 表 1-10 PowerDesigner 集成环境中的常用快捷键 作者:姜江 error 50 快捷键 实现的功能 F4 检查模型(Check Model) F5 图形比例恢复到对象实际大小 F6 放大 F7 缩小 F8 查看全局视图 F9 查看上一视图 F10 显示当前图形中已经使用过的页面(可分为多个页面) Shift+F5 重新显示 Shift+F9 下一个视图 按住 Shift 选择对象 连续选择多个对象 Alt+0 显示或者隐藏浏览树(Browser tree)视图 Alt+1 显示或者隐藏输出(OutPut)窗口 Alt+2 显示或者隐藏结果(Result)列表 Alt+F6 在活动窗口之间切换 Ctrl+鼠标双击或 Ctrl+“+” 打开包(Package)中图形 Ctrl+Tab 在文本中插入 Tab,或者切换属性窗口中各个页面 Ctrl+PgUp/PgDn 在对象属性窗口中切换各个 Tab 页面 移动窗口的同时按住 Ctrl 键 使 OutPut 等窗口不具有停靠(Docking)的功能 Ctrl+B 在浏览器中查找选定的对象 Ctrl+D 选择图形(Diagram),弹出选择图形窗口 Ctrl+E 打开报告列表(Report List) Ctrl+F 插找对象,弹出插找对象窗口 Ctrl+J 调整对象图符中的文本 Ctrl+F4 关闭当前图形(Diagram) Ctrl+Alt+F4 关闭当前模型 Ctrl+F6 PowerDesigner 中可同时打开多个对象的属性窗口,给快捷键 可在多个对象的属性窗口之间切换 Ctrl+Shift+F6 反向切换对象的属性窗口 Ctrl+U 跳转到父图形中(Parent Diagram) Shift+F2 打开 Workspace Shift+F3 保存 Workspace Shift+F4 关闭 Workspace 作者:姜江 error 51 1.10.2 对象操作的快捷键 对图形模型中对象(表、类等)操作的快捷键如表 1-11 所示。 表 1-11 对象操作的快捷键 快捷键 实现的功能 Del 删除对象(会弹出确认对话框) Shift+Del 删除对象(不弹出确认对话框,直接删除) Alt+Enter 打开选定对象的属性窗口 Ctrl+K 粘贴为快捷方式 Ctrl+H 使选定的对象之间的连接线(Link),变为水平直线 Ctrl+L 使选定的对象之间的连接线(Link),变为垂直直线 Ctrl+Resize 在改变对象大小的时候保持该对象处于模型区域的中央 Ctrl+Shift+Resize 改变对象大小的同时,保持对象中央位置同时按比例变化 在对象名称上 Ctrl+鼠标右键 重命名对象,也可以使用 F2 1.10.3 浏览器中的快捷键 浏览器,这里指 Browser 资源管理器,相关快捷键如表 1-12 所示。 表 1-12 浏览器中的快捷键 快捷键 实现的功能 * 展开当前对象的所有节点(嵌套展开) + 展开当前选定对象的子节点 — 收缩当前对象的子节点 F2 重命名选定对象 Ctrl+Shift+F 在图形中查找浏览器中选定的对象,并且定位到该对象 1.10.4 拖动对象时的快捷键 使用鼠标拖动对象时可以通过一些快捷键加快操作速度,如表 1-13 所示。 表 1-13 拖动对象时的快捷键 快捷键 实现的功能 移动对象的时候按住 Shift 键 移动对象图符 作者:姜江 error 52 移动对象的时候按住 Ctrl 键 复制对象 移动对象的时候按住 Ctrl+Shift 键 创建快捷方式 移动对象的时候按住 Alt 键 创建一个复制品(Replica) 选择对象后用鼠标右键拖动对象 弹出选择菜单,选择上述操作中的一个或者取消 1.10.5 Palette 中的快捷键 Palette 面板中包含各种建模元素,相关的快捷键如表 1-14 所示。 表 1-14 Palette 面板中的快捷键 快捷键 实现的功能 Ctrl + A 或 者 鼠 标 双 击 Palette 中的 Pointer 图标 选择图形(Diagram)中所有对象 鼠标双击 Delete 工具 删除所有选定的对象,会弹出确认对话框 鼠标双击 Grabber 工具 显示全局视图 鼠标双击对象工具(如 Table 或 View) 在模型图形中选定所有这种类型的对象 按 Shift 键的同时鼠标双击对象工具 保持在此之前的选择,同时选定所有这种类型对象 在空白区域右键鼠标 释放当前的工具,切换到 Pointer 工具 1.10.6 对象列表中的快捷键 对象 List(如属性列表或者 Table List 等)中的快捷键,如表 1-15 所示。 表 1-15 对象列表中的快捷键 快捷键 实现的功能 F2 选定列表中当前窗格(Cell)进行编辑 F4 光标跳转到窗格第一个字符前,为当前窗格(Cell)增加文字 Ctrl+Shift+空格键 选择当前行 Ctrl+A 选择所有 Ctrl+Shift+A 释放所有选择(Deselect All) Ctrl+N 在 List 末尾插入一行 Ctrl+I 在当前行上方插入一行 Ctrl+D 删除行 作者:姜江 error 53 1.10.7 Code 中的快捷键 代码(Code)编辑中的快捷键,如表 1-16 所示。 表 1-16 Code 编辑时的快捷键 快捷键 实现的功能 F2 跳转到下一个书签 F3 查找下一个 Shift+F11 菜单 Ctrl+F2 插入或者删除书签 Ctrl+I 插入文件 1.10.8 图形中的操作技巧 模型图形中的操作技巧 移动接触点(Attach points) 操作方法:选择需要移动的接触点,同时按住 Ctrl 键,移动至目标位置,如果不同时按住 Ctrl 键,则接触点不能被移出该对象。如图 1-73 所示。 图 1-73 移动接触点 在连接上增加拐点 操作方法:选择连接,按住 Ctrl 键,在需要增加拐点的位置点击鼠标左键,同时移动鼠标, 则该位置会自动创建拐点。如图 1-74 所示。 作者:姜江 error 54 图 1-74 在连接上增加拐点 移除拐点(Attach points) 操作方法:选择连接上的拐点,按住 Ctrl 键,同时用鼠标单击该拐点,即可移除该拐点。如 图 1-75 所示。 图 1-75 移动拐点 作者:姜江 error 55 第2章 概念模型(CDM) 建模,是对客观事物加以抽象,提取主要特征,归纳成一个简单清晰的轮廓,使复杂问题变 得易于处理,数据库建模通常包括概念数据模型、数据结构、物理数据模型三个部分,在数据结 构的层次上,目前主要采用关系模型的二维表数据结构,本章主要介绍概念数据模型。 概念数据模型(CDM,Concept Data Model)是通过模型对现实世界的抽象,通常采用 ER 等 模型,设计数据库通常是从概念模型开始设计。在概念设计这个层次上,不需要考虑物理实现的 细节。设计好 CDM 之后,可以通过 CDM 到物理数据模型(PDM)的转化。然后再根据具体的 DBMS 的特点对物理数据模型进行定制,完成物理实现,这种清晰的思路比较容易理解和控制。 本章的主要内容如下:  数据库基本概念,实体关系模型(ER Model)  概念数据模型的基本概念  创建和操作概念数据模型(CDM)  概念数据模型的检查、比较以及合并  概念数据模型的转化 2.1 概念模型基础 这一节中,简单的介绍关系模型的基本概念,并不对关系模型作详细的阐述,读者可以参考 其他相关书籍进行学习。 在数据库技术中,我们用模型的概念描述数据库的结构与语义,对现实世界进行抽象。表示 实体类型以及实体间联系的模型称为“数据模型”。关系模型是目前最为流程的一种数据模型,用 二维表格结构表示实体集,关键码表示实体间的联系。 关系模型由三部分组成:关系数据结构、关系操作集合和关系的完整性,用关系(表格数据) 表示实体和实体之间联系的模型称为关系模型。通俗地讲,关系就是二维表格。 用二维表格结构表示实体集、外键表示实体间联系的数据模型称为关系模型。 1. 关系模型的基本术语 关系模型同传统的数据库技术以及 SQL 语言之间使用的术语有些不同,如表 2-1 所示。 表 2-1 关系模型、数据库、SQL 术语比较 数据库技术的术语 关系模型术语 SQL 术语 记录类型 关系模式 基本表 记录 元组 行 文件 关系、实例 基本表、表格 作者:姜江 error 56 属性、字段、数据项 属性 列 除此之外,关系中属性个数称为元数,元组个数为基数。 2.键 键(关键码)是关系模型的一个重要概念,由一个或几个属性组成,有以下几种键:  超键:在关系中能唯一标识元组的属性集称为关系模式的超键(Super key)。  候选键:不含有多余属性的超键称为候选键。  主键:关系模式中用户正在使用的侯选键成为主键(Primary key), 一般情况下,如果 特别说明,键就是指主键。  外键:某个关系的主键相应的属性在另一关系中出现,此时该主键在就是另一关系的外 键,如有两个关系 S 和 SC,其中 S#是关系 S 的主键,相应的属性 S#在关系 SC 中也出现, 此时 S#就是关系 SC 的外键。 3.关系的定义 用集合论的观点定义关系就是:关系是一个元数为 K(K>=1)的元组的集合。把关系看成一 个集合,集合中的元素是元组,每个元组又有 K 个属性值。 尽管关系与二维表格、传统的数据文件有类似之处,但又有区别。严格地讲,关系是一种规 范化了的二维表格中行的集合。在关系模型中,对关系作如下限制:  关系中没一个属性值都是不可分解的,也不允许出现重复组  关系中不允许出现相同的元组(即不允许出现重复元组)  由于关系模型是一个集合,因此不让用户考虑元组的顺序  元组中属性是有序排列的,用户在使用时应考虑到顺序 4.关系数据库的数据体系结构 关系模型遵循数据库的三级体系结构,名称分别为:关系模式、关系子模式和存储模式。  关系模式:数据库的概念模式定义为关系模式的集合。关系模式实际上就是记录类型。 它包括:模式名,属性名,值域名以及模式的主键。关系模式仅是对数据特性的描述。 这 通常在数据库中表现为一个数据表的结构。由于不涉及到物理存储方面的细节,因此关 系模式仅仅是对数据本身特性的描述。  关系子模式:就是用户所用到那部分数据的描述。 除了指出用户用到的数据外,还应指 出数据与模式中相应的数据的联系,即指出字模式与模式之间的对应性。  存储模式:关系存储时的基本组织方式是文件,元组是文件中的记录。由于关系模式有 键,因此存储一个关系可用散列方法或索引方法实现。如果关系的元组数目较少(一百 个左右),也可以用“堆文件”方法实现(即没有特定次序)。此外,还可对任意的属 性即建立辅助索引。 5.关系的完整性 在关系型数据库中,完整性约束用于确保数据的准确性和一致性。关系模型提供了丰富的完 整性控制机制,允许定义三类完整性:实体完整性、参照完整性和用户定义完整性。其中实体完 作者:姜江 error 57 整性和参照完整性是关系模型必须满足的完整性约束条件,应该由关系系统自动支持。 实体完整性 实体完整性要求关系中组成主键的属性上不能有空值。 一个基本关系通常对应现实世界的一个实体集。例如,学生关系“学生 ( 学号,姓名,性别, 出生日期 )”对应于学生的集合。现实世界中的实体是可区分的,即它们具有某种唯一性标识。相 应地,关系模型中以主键作为唯一性标识。主键中的属性即主属性不能取空值。所谓空值就是“不 知道”或“无意义”的值。如果主属性取空值,则将难以判断该元组与其他元组的区别。 例如,在邮政部门投递信件时,显然通信地址和姓名是作为主属性的,如果这两项中任一项 为空值,那么信件将无法投递。 实体完整性规则:若属性 A 是基本关系 R 的主属性,则属性 A 就不能取空值。 例如,在关系“学生 ( 学号,姓名,出生日期,性别 )”中,学号属性为主键,则学号不能取 空值。 实体完整性规则规定基本关系的所有主属性都不能取空值,若某关系中,( 学号,姓名 )为 主键,则学号和姓名两属性分别都不能取空值。 参照完整性 参照完整性要求不引用不存在的实体。 现实世界中的实体之间往往存在某种联系,在关系模型中实体及实体间的联系都是用关系来 描述的,这样就自然存在着关系与关系间的引用。先看一个例子: 例如,有两个基本关系为成绩 ( 学号,课程编号,成绩 ) 和课程 ( 课程编号,课程名称, 课时,学分 ),其中主键用下划线标识,可以写作: 成绩 ( 学号,课程编号,成绩 ) 课程 (课程编号,课程名称,课时,学分 ) 这两个关系之间存在着属性的引用,即成绩关系引用了课程关系的主键“课程编号”。显然, 成绩关系中的课程编号必须是确实存在的关系课程的课程编号,即课程关系中有该课程编号的记 录,也就是说,成绩关系中的某个属性的取值需要参照课程关系的属性取值。 用户定义的完整性 用户定义完整性规则:由具体应用环境决定,系统提供定义和检验这类完整性的机制。 实体完整性和参照完整性用于任何关系数据库系统,用户定义的完整性则是针对某一具体的数 据库的约束条件,如性别只能是“男”或“女”两种可能,年龄取值只能限制在 0-150 之间才合乎情况 等。它反映某一具体应用所涉及的数据必须满足的语义要求。关系模型应提供定义和检验这类完 整性的机制。 6.关系模型的优点 关系模型同其他模型相比,有以下突出的优点:  关系模型提供单一的数据结构形式,具有高度的简明性和精确性。各类用户都可以很容 易地掌握和运用基于关系模型的数据库系统,使得数据库应用系统的开发效率显著提高。 作者:姜江 error 58  关系模型的逻辑结构和数据操作完全独立于数据存储方式,具有高度的数据独立性,用 户完全不必关系物理存储细节。  关系模型建立在坚实的数学基础上,关系运算的完备性、设计规范化理论为数据库技术 的成熟奠定了坚实的基础。  关系数据库语言与一阶谓词逻辑的故有内在联系,为以关系数据库为基础的推力系统和 知识库系统的研究提供了方便,成为新一代数据库技术不可缺少的基础。 2.2 CDM 基础概念 2.2.1 CDM 的基本概念 A.概念数据模型的概念 概念数据模型:它是独立于计算机系统的模型,完全不涉及信息在系统中的表示,只是用来 描述某个特定组织所关心的信息结构。 设计数据库通常是从概念模型开始设计,也就是从我们常用的 E-R(实体关系模型)开始。 在概念设计这个层次上,不需要考虑物理实现的细节。设计好 CDM 之后,可以通过 CDM 到物理 数据模型(PDM)的转化。然后再根据具体的 DBMS 的特点对物理数据模型进行定制,完成物理 实现,这种清晰的思路比较容易理解和控制。 在 PowerDesigner 中,CDM(Concept Data Model)就充当着概念设计的角色,它可以独立于 任何软件和数据库存储结构,对数据库的全局结构进行描述。通过使用 CDM,可以实现以下供能: 1. 创建实体关系图(Entity Relation Diagrams,即 ERD),以图形的方式组织数据 2. 验证数据设计的正确性 3. 生成物理数据模型(PDM) 4. 生成面向对象模型(OOM) 5. 生成概念数据模型(CDM),从而创建另外一个模型的版本,代表了设计的不同阶段。 B.打开已有的 CDM 模型 举例如下: 选择【File】→【Open】,在弹出的窗口中选择 PowerDesigner 安装目录下\Sybase\PowerDesigner 9\Examples\Tutorial 中的自带的示例文件 cdmbefore.cdm,如图 2-1 所示。 作者:姜江 error 59 图 2-1 PowerDesigner 自带的 CDM 模型 2.2.2 CDM 的操作环境 打开概念数据模型后,可以发现 Palette 工具面板同 PDM 状态下有着诸多的不同,各个工具 的含义如表 2-2 所示。 表 2-2 CDM 模型中 Palette 面板的各工具含义 工具 名称 用途 鼠标/Pointer 选择图形 套索/Lasso 选择某个范围内的图形 抓取器/Grabber 选择并移动所有的图符 放大/Zoom In 放大图形 缩小/Zoom Out 缩小图形 打开包的图形/Open Package Diagram 显示某个包的图形 属性/Properties 显示某个图符的属性 删除/Delete 删除图符 包/Package 插入一个包的图符 实体/Entity 插入一个实体的图符 作者:姜江 error 60 关系/Relationship 插入一个关系的图符 继承关系/Inheritance 插入一个继承图符 关联/Association 插入一个关联图符 关联连接/Association Link 插入一个关联连接图符 文件/File 插入一个文本文件 注解/Note 插入一个注解的图符 连接/扩展依赖(Link / ExtentedDependency) 1.在模型的图符之间建立连接 2.在对象 和 note 之间建立连接 3.在两个支持扩展 依赖的对象之间建立扩展依赖 标题/Title 插入一个标题 文本/Text 插入一段文本 直线/Line 画一条直线 弧线/Arc 画一条曲线 长方形/Rectangle 画一个长方形 椭圆/Ellipse 画一个椭圆 圆角矩形/Rounded rectangle 画一个圆角矩形 多折角线/Polyline 画一个多折角线 多边形/Polygon 画一个多角形 2.2.3 创建新的 CDM 创建 CDM 模型 1. 选择【File】→【New】,弹出新建模型窗口,如图 2-2 所示。 图 2-2 新建模型窗口 2. 选择 Conceptual Data Model,点击【OK】按钮 3. Workspace 中出现一个概念数据模型,如图 2-3 所示。 作者:姜江 error 61 图 2-3 在浏览树中的概念数据模型 4. 选择【Model】→【Model Properties】,或者在 PowerDesigner 图形区域中的空白处点击鼠标右 键,在弹出的上下文菜单中的选择 Properties,弹出模型属性窗口,如图 2-4 所示。 图 2-4 CDM 模型的属性窗口的“General”页 5. 输入概念模型的名称和代码,点击【确定】按钮。 关于模型和 Workspace 的一些常见操作,请参考:3.4.1 创建和操作 PDM 模型 2.3 创建和操作 CDM 学习思路 本章接下来的内容,将主要围绕 PowerDesigner 自带的例子进行分析和设计,根据需求建立 模型,在解决问题的同时,贯穿 CDM 中各个知识点,进行详细的讲解和举例。 下面首先对这个例子的做简单的介绍: 我们将为某出版公司建立信息系统的概念模型。在该模型中使用 Entity(实体)表示一些业务 运营中的概念 Titles(书名),Authors(作者),Books Stores(书店),Discount(折扣),并且描述 实体的相关信息,例如:ISBN(国际标准书号)对书进行描述。 作者:姜江 error 62 2.3.1 实体(Entity) A. 创建和操作实体 新建一个概念数据模型,模型的名称和代码都为 Publish Company。下面开始创建模型中的实 体。 1. 点击 Palette 面板中的【Entity】工具 ,在模型区域点击鼠标左键,在鼠标点击的位置出现 Entity 的图符,默认的命名方式为:Entity_n,其中 n 为当前实体的创建次序。如图 2-5 所示。 图 2-5 新建的 Entity 2. 点击鼠标右键或者点击 Palette 面板中的 工具,使得鼠标返回选择状态 3. 双击该图符,或者鼠标右键该图符,在弹出的菜单中选择 Properties,弹出 Entity 的属性窗口, 输入实体的名称和代码均为 Title,如图 2-6 所示。 图 2-6 实体的属性窗口“General”页 其中,Number 表示物理数据库中该实体中可能包含的记录的数目,该数字主要应用于物理数 据库的大小规模的估计;Generate 表示该实体是否会生成为 PDM 中的表。 4. 进入 Attributes 属性页,点击【Insert a row】 工具或者【Add a row】 工具,为该实体添 加相关属性,并且设置属性的数据类型,选择属性 TitleISBN 为该实体的主要标识符(Primary Identifier),在途中显示为字段“P”选中,如图 2-7 所示。 作者:姜江 error 63 图 2-7 在“Attributes”页中添加属性 其中,“M”表示 Mandatory,即该属性可否为空,D 表示是否在图形模型中显示该属性,如 果读者使用的软件中看不到这些选项,可以点击该属性页中的【Customize Columns and Filter】工 具 ,或者使用快捷键【Ctrl+U】,弹出如图 2-8 所示窗口,可以选择自己软件中看不到的项目, 然后点击【OK】按钮: 图 2-8 在“Customize Columns Filter”窗口中选择要查看的项目类型 5. 点击【OK】。模型中出现如图 2-9 所示结果。 图 2-9 设置好相关属性的 Entity 图形 作者:姜江 error 64 图 2-10 PowerDesigner 自带模型的 Entity 图形 如图 2-10 所示。细心的读者也许会发现,我们创建的模型在内容上虽然和 PowerDesigner 自 带的模型中 Title 完全一致,但是显示出的图形部分却有这一些不同,主要表现在显示的内容的种 类不同。如果需要对显示的内容进行选择,选择【Tools】→【Display Preferences】,弹出显示属 性窗口,如图 2-11 所示。 图 2-11 在“Display Preferences”窗口中修改 Entity 对象视图 如图 2-11 所示,选择【Object View】→【Entity】,可以发现,刚刚创建的模型之所以与 PowerDesigner 9.5 自带模型的图形不一样,是因为在我们的模型中选择了显示标识符(Identifier)、 数据类型(Data types)、强制(Mandatory)等复选框,去掉这些复选框即可使图形一致,不过读 者完全可以自己的需要选择是否显示某些内容。 B. 标识符(Identifier) Identifier 本身是实体的属性,或者属性的集合,它能够唯一确定实体中的一条记录。概念数 据模型 CDM 中的 Identifier(标识符)相当于物理数据模型中 PDM 的主键(Primary Key)或者后 选键(Alternate Key)。每个实体至少要定义一个标识符,如果实体仅有一个标识符,则该标识符 被指定为主标识符(Primary Identifier)。定义了 Primary Identifier 后,Identifier 属性页会自动创建 一个 Identifier,要创建新的标识符,操作步骤如下: 进入 Identifier 属性页,点击空白行,或者 Insert a row 工具和 Add a row 工具,输入 Name 和 Code,选择复选框“P”表示是否为主标识符,点击【Apply】应用设置。双击标识符所在的行, 作者:姜江 error 65 或者点击【Properties】工具 ,弹出标识符属性窗口 Identifier Properties,可以在 General 属性页 中输入 Name 和 Code。 进入 Attributes 属性页,可以指定该标识符所涉及的属性,点击【Add Attributes】工具 ,弹 出属性选择窗口,如图 2-12 所示。 图 2-12 设置 Identifier 相关的属性 这里假设为实体 Title 新创建了一个标识符,则在图形中显示为“”,如图 2-13 所示。 图 2-13 增加标识符后的 Entity 图形 选择需要作为 Identifier 的属性,点击【OK】,确定,即完成对标识符的定义。要对标识符进 行修改,除了通过 Entity 之外,还可以选择【Model】→【Identifiers】,弹出标识符列表窗口,如 图 2-14 所示。 作者:姜江 error 66 图 2-14 标识符列表窗口“List of Identifiers” 2.3.2 定义关系(Relationships) A. 定义关系(Relationship) 建立关系(Relationship) 关系(Relationship)是实体之间的连接,例如在一个人力资源管理的概念模型中,员工 (Employee)必定属于某个团队(Team),因此,实体员工和实体团队之间就存在着这种关系。 在我们的例子中,每本图书可能一个或者多个作者完成,一个作者也可能写一本或者多本书。首 先,创建实体 Author(作者),接下来讲学习如何在实体之间建立联系(Relationship)。 在图形模型中建立关系的步骤如下: 1. 点击 Palette 面板中的【Relationship】工具 ,在实体 Title 上点击鼠标左键,并且按住不放, 拖动鼠标至目标实体 Author 上方,松开鼠标,这样就在两个实体之间建立了关系。如图 2-15 所示。 图 2-15 在实体之间建立关系 2. 点击鼠标右键或者点击 Palette 面板中的 工具,使得鼠标返回选择状态 Relationship 在实体 Authors 处显示为三个接触点,表示同一个 Title(书)可以对应多个 Author(作者),而在 Title 处只有一个接触点,表明同一个作者只有可能写一本书,但是事 实上一个作者也可以写多本书,这显然与显示情况不符合,因此,我们还必须对创建的关系 进一步的修改以满足需求。 作者:姜江 error 67 3. 双击关系(Relationship)的连线,或者鼠标右键该图形,在弹出的菜单中选择 Properties,弹 出 Relationship Properties 窗口,如图 2-16 所示。 图 2-16 Relationship 的属性窗口的“General”页 4. 修改 Relationship 的 Name 和 Code 均为 TitleAuthor,进入 Detail 属性页,如图 2-17 所示。 图 2-17 Relationship 属性窗口的“Detail”页 5. 选择单选框 Many-Many,表示实体的关系是“多对多”,然后进一步规定实体的角色定义:Title to Author(书对作者)的角色为 is written by(表示书是被作者写出来的);Author to Title(作 作者:姜江 error 68 者对书)的角色为 write(表示作者写书) 如果选中 Mandatory,Cardinality(基数)即会变为“1,n”表示某个实体至少对应一个对 应的实体。 如表 2-3 所示,不同的基数关系对应的 Relationship 的端点的显示的图形也不同: 表 2-3 不同基数及其对应的图形显示 端点 存在性 基数 描述 强制 一个 必须存在且仅存在一个 强制 多个 必须存在一个或者多个 可不存在 一个 可以存在一个或者不存在 可不存在 多个 可以存在一个或者多个,也可以不存在 6. 修改后点击【确定】应用。模型显示为如图 2-18 所示。 图 2-18 修改关系属性后的图形显示 7. 但是图中没有显示基数,如果读者有这个需要,可以选择【Tools】→【Display Preference】, 选择【Object View】→【Relationship】,选中 Cardinality,如图 2-19 所示。 图 2-19 选择在图形上显示基数“Cardinality” 8. 点击【OK】按钮,基数正确显示,如图 2-20 所示。 作者:姜江 error 69 图 2-20 显示基数的关系的图形 9. 如果希望图形之间的关系如 PowerDesigner 自带的相似,即为柔和的曲线型,选择【Tools】→ 【Display Preference】,在窗口中选择【Format】→【Relationship】,点击右端的【Modify】按 钮,弹出修改窗口,在 Corners 下拉列表中选择需要的类型,如图 2-21 所示。 图 2-21 选择 Relationship 的连线风格 10. 点击【确定】,应用该修改,会弹出应用格式的确认窗口,询问对那些对象应用该格式修 改,如图 2-22 所示。 图 2-22 应用格式修改的确认对话框 11. 选择适当的应用范围,点击【OK】按钮确定。 B. 依赖关系(Dependent Relationship) 依赖关系表示一个实体在一定程度上由另外一个实体决定,每个实体都必须包含一个标识符。 例如:Royalty Schedule(版税计划),对于不同的书都由不同的版税计划,因此,要确定具体的版 税计划,必须通过标识符“Title ISBN”才能确定某个具体的版税计划。 作者:姜江 error 70 图 2-23 定义实体之间的依赖关系 如图 2-23 所示,定义实体 Royalty Schedule 和实体 Title 之间的依赖关系后点击【确定】。如 图 2-24 所示,三角状所指的方向表明实体的 Royalty Schedule 确定依赖于实体 Title: 图 2-24 定义依赖之后关系的图形显示 C. 支配关系(Dominant Relationship) 在一对一的关系当中,可以定义关系的支配方向。如果定义了关系的支配方向,则当概念数 据模型转化为物理数据模型的时候,Relationship 会转化为一个 Reference,占支配地位的实体变为 父表。如果没有定义支配关系的方向,则一对一的 Relationship 会生成两个 Reference。如图 2-25 所示,在 Dominant role 下拉框中选择 Author→Picture: 作者:姜江 error 71 图 2-25 定义关系的支配关系 定义好支配关系之后点击【确定】,模型中图形如图 2-26 所示。 图 2-26 定义支配后关系的图形显示 请参考:2.6.3 将 CDM 转化为物理数据模型(PDM),通过 CDM 生成 PDM 模型得到如图 2-27 所示图形: 图 2-27 生成相应的 PDM 的模型 如果没有对一对一的关系定义支配关系,则会产生下图所示的 PDM 模型,而这显然不是我们 希望发生的情况,所以,一定要“一对一的关系”定义适当的支配方向。如图 2-28 所示。 作者:姜江 error 72 图 2-28 “一对一支配关系”转化生成的 PDM 模型 D. 关联实体(Associative Entity) 在 PowerDesigner 中可以将一个关系(Relationship)转化为一个关联实体(Associative Entity), 这个关联实体同以前关系的两个实体向关联。在此基础上也可以将实体的属性指派给这个关联实 体,关联实体采用关联的名称,两个因此而新产生的关联将会自动处理基数属性。转化的操作方 法如下: 1. 鼠标右键 Title 和 Author 之间的 Relationship 2. 在弹出的菜单中选择【Change to Entity】→【Standard】,生成结果如图 2-29 所示。 图 2-29 将关系转化为关联实体 3. 也可以在上一步选择【Change to Entity】→【Wizard】,用三步完成生成关联实体,每个一步 都对应一个向导页面,第一个向导页如图 2-30 所示。 图 2-30 使用“Change to Entity”向导生成关联实体 4. 在上图中输入关联实体的 Name 和 Code,点击【下一步】按钮,如图 2-31 所示。 作者:姜江 error 73 图 2-31 定义关联实体和 Title 之间产生的新关联 5. 在上图中定义关联实体和 Title 的即将新产生的关联,完成后点击【下一步】按钮,如图 2-32 所示。 图 2-32 定义关联实体和 Author 之间产生的新关联 6. 中定义关联实体和 Author 的即将新产生的关联,点击【完成】。 7. 双击新生成的关联实体,弹出实体属性窗口,进入 Attributes 属性页,点击【Add Data Item】 工具 或者【Reuse Data Item】工具 ,弹出 Data Item 选择窗口,如图 2-33 所示。 作者:姜江 error 74 图 2-33 为关联实体添加属性 8. 选择适当的数据项作为关联实体的属性,点击【OK】按钮。 E. 自反关系 自反关系是实体和自己的关系(Relationship),例如,管理者负责监督员工,但是管理者本身 也是员工,如图 2-34 所示。 图 2-34 自反关系实例 创建自反关系的步骤如下: 1. 点击 Palette 面板中的【Relationship】工具 2. 在实体上点击鼠标左键,并且按住不放 3. 拖动鼠标至实体外部的空白位置,松开鼠标 4. 在将鼠标移动至该实体上点击鼠标左键,自反关系即成功建立。 根据业务需求建立概念数据模型,如图 2-35 所示。 作者:姜江 error 75 图 2-35 进一步完善后的实例模型 2.3.3 Association 关系 Association 是实体间的一种连接。在 Meris 的建模方法中,Association 用于连接不同的实体, 这些实体都分别代表明确定义的对象,这种实体之间的连接是通过“事件”连接,而这种关系仅 仅通过另外一个实体表达的可能不够清晰。 例如:存在三个实体 VIDEOK7,CLIENT 和 STORE 分别包含碟片、客户以及商店信息。通 过一个 Association 表示碟片的出租(K7RENTED),包含属性 DATE 和 STAFF_ID,分别记录租 碟片的时间和将碟片出租的员工的 ID。如图 2-36 所示。 图 2-36 Association 关系实例 将上述模型转化为 PDM 时,K7RENTED 转化为一个有五个字段的表,除了自身的两个属性 以外,还有其他转化后三张表的主键作为外键。如图 2-37 所示。 图 2-37 转化生成的 PDM 模型 作者:姜江 error 76 概念数据模型中包含两种模型表示方法,一种是:ER 模型,另外一种是 Merise 表示法,两 种表示方法的区别参考表 2-4。 表 2-4 概念数据模型的不同模型表示方式的比较 选项 描述 符号 Entity/Relationship 实体关系模型表示的方法在 实体之间建立连接,其中关 系的属性会应用到每个关联 的实体上 Merise Merise 模型表示方法使用 associations 而不是 relationships Mixed 一个模型中同时使用两种方 法 两种符号 要修改模型中的表示方法,请选择【Tools】→【 Model Options】,弹出模型属性窗口,在 Model notation 下拉列表中选择 Entity/Relationship、Merise 或者 Mixed,如图 2-38 所示。 图 2-38 在模型属性窗口中修改模型表示方法 在 CDM 中创建 Association 的方法如下: 1. 点击 Palette 面板中的【Association】工具 2. 在第一个实体图形上点击鼠标左键,按住不放,拖动鼠标至目标实体上,释放鼠标,如图 2-39 作者:姜江 error 77 所示。 图 2-39 在实体之间创建 Association 如图 2-39 所示,两个实体之间自动创建了一个 Association 3. 双击 Association 的图符,弹出 Association 属性窗口,输入名称和代码,其中 Number 表示估 计记录的行数,如图 2-40 所示。 图 2-40 Association 属性窗口“General”页 4. 鼠标点击 Attributes 属性页,点击空白行或者【Insert a Row】工具 【Add a Row】工具 , 添加属性,输入 Name 和 Code,点击【Apply】按钮应用,如图 2-41 所示。 图 2-41 在 Association 属性窗口“Attributes”页为关联添加属性 作者:姜江 error 78 也可以点击【Add Data Item】工具 或者【Reuse Data Item】,弹出数据项选择窗口,可 以选择当前模型中的数据项添加至 Association 中成为属性。 5. 双击某行行首箭头或者选择某行后点击【Properties】工具 ,在弹出的属性窗口中可以对 Attributes 的属性进行详细的定义 6. 点击【确定】。 在两个实体间拖动 Association Link 可以发现 PowerDesigner 自动创建了 Association,并且将 该 Association 分别和两个实体用两个 Association Link 连接。 另一中方法是,先选择 Association 工具 ,创建一个 Association,然后使用 Association Link 工具 ,将 Association 图形分别和两个实体连接。 双击实体 Store 与 Association 之间的 Association Link,弹出 Association Link 属性对话框,可 以在此修改 Association Link 的相关属性,如图 2-42 所示。 图 2-42 查看 Association Link 属性窗口 这里 Cardinality(基数)的含义参考表 2-5。 表 2-5 基数的含义 Cardinality 描述 0,1 1 个其他实体对应 0 个或者 1 个该实体,Association 不是强制的 0,n 1 个其他实体对应 0 个或者多个的该实体,Association 不是强制的 1,1 1 个该实体对应其他实体的数目也是 1 个,Association 是强制的 1,n 1 个该实体可以对应多个其他实体,Association 是强制的 作者:姜江 error 79 如果希望改变基数(Cardinality)的默认显示格式,可以修改注册表中的值,即修改 HKEY_CURRENT_USER\Software\Sybase\PowerDesigner 9\ModelOptions\Conceptual Options 下的值 CardinalityNotation=1 时显示为 (0..1)类型的格式, CardinalityNotation=2 时显示为 (0,1) 类型的格式。 在上图中如果选择Identifier复选框,则表示该Association为依赖性的,这和依赖性Relationship 类似,生成的 PDM 图形中,被依赖端的主键将作为依赖端的外键,并且和依赖端的 Primary Identifier 共同组成主键。选择 Identifier 复选框后,基数自动变为“1,1”,点击【确定】后,图 形中的“1,1”变为“(1,1)”表示该 Association Link 是 Identifier,如图 2-43 所示。 图 2-43 定义 Identifier 后的模型 转化为 PDM 后的图形如图 2-44 所示。 图 2-44 转化为的相应 PDM 后的模型 除了在图形上创建 Association Link 之外,还可以通过 Association Link 列表创建 Association Link,选择【Model】→【Associations】,弹出 List of Association 窗口,可以在该列表窗口中新创 建 Association。要在 Association和Entity之间创建连接,选择 Association Link工具,连接 Association 和 Entity 即可。 在 CDM 中创建自反 Association(Reflexive Association) Reflexive association 是实体自身的一种关系,例如,管理者(Manager)本身也是员工 (Employee),创建 Reflexive association 的步骤如下: 1. 创建实体 Employee 2. 点击 Palette 中的【Association Link】工具 ,在 Employee 上点击鼠标左键,点住鼠标不放, 然后将鼠标移向实体图形之外,释放鼠标,再次移回到实体 Employee 之上,再次点击鼠标左 键(在实体图形之外点击鼠标左键不起作用,相当于创建了曲线的一个点),则为该实体创建 了自反 Association,如图 2-45 所示。 作者:姜江 error 80 图 2-45 自反 Association 实例 将 Association Link 转化为 Associative Entity 和 Relationship 一样,Association Link 也可以转化为 Associative Entity(关联实体),操作的 方法同 Relationship 中完全相同,请参考:2.3.2 定义关系(Relationships)。 修改 Association 的显示 点击【Tools】→【Display Preferences】,弹出显示内容调整窗口,分别选择【Object View】 →【Association】和【Object View】→【Association Link】,读者可以根据自己的需要调整图形的 显示内容和形式,如图 2-46 和图 2-47 所示。 图 2-46 修改 Association 对象视图 作者:姜江 error 81 图 2-47 修改 Association Link 对象视图 2.3.4 Inheritance(继承) CDM 中可以通过定义继承表示某个实体是另一个更一般的实体的特例。这些实体之间有着共 同的特征,但却是不同的。超类型(或者父亲)指那些包含共同特征的更一般的类。而特例则是 那些子类型(又称儿子),这些实体包含一些更为具体和特殊的特征。父亲和儿子之间的关系从哲 学上理解就是一般和具体关系。 例如,银行的帐户(Account)分为存款帐户(Saving Account)和核算帐户(Checking Account)。 实体 Checking 和实体 Saving 为实体 Account 的特例,先创建三个实体,如图 2-48 所示。 图 2-48 创建继承的对象实例 创建继承连接,操作的步骤如下: 1. 选择 Palette 面板中的 Inheritance 工具 ,鼠标左键点击子表 Checking,按住鼠标不放 2. 一直拖动至父表 Account 中再释放鼠标,如图 1-50 所示。 图 2-49 在对象 Checking 和 Account 之间创建继承 3. 要添加另外一个的儿子实体 Saving,点击【Inheritance】工具 ,从半圆形状拖动鼠标至实 体 Saving 释放,或者从实体 Saving 拖动鼠标至半圆形状释放,如图 2-50 所示。 作者:姜江 error 82 图 2-50 拖动对象 Saving 到半圆形状创建和 Account 之间的继承 图 2-51 直接从 Saving 拖放至 Account 创建继承 当然,也可以直接从实体 Saving 拖放至父实体 Account,如图 2-51 所示。另外一种方法是, 在 Inheritance 的属性窗口中,点击 Children 属性页,点击【Add Children】 工具,在弹出的窗 口中选择该需要新加入的子实体。如图 2-52 所示。 图 2-52 在“Inheritance Properties”窗口的“Children”页添加子实体 4. 双击图形中的继承连接线或者半圆形,弹出继承属性窗口,输入继承的名称和代码,如图 2-53 所示。 作者:姜江 error 83 图 2-53 定义继承的名称和代码 如果选择 Mutually exclusive children,则表示该父实体不能同时是几种子实体,即互斥。这个 设置仅仅是信息的记录,不会对需要转化的 PDM 产生影响。点击【应用】按钮,图形变化为如 图 2-54 所示图形。 图 2-54 定义继承之后的模型 5. 点击 Generation 属性页,如图 2-55 所示。 图 2-55 继承属性窗口的“Generation”页 作者:姜江 error 84 上图中各个选项的含义如表 2-6 所示。 表 2-6 继承关系的不同生成选项 Generation mode 生成的表对应的对象 描述 Generate parent 父实体 继承所有子实体的属性,被子实体的 关系影响,会与任何和子实体有 many-to-one 关系的表创建引用关系 Generate children Inherit all attributes 每个子实体 继承父实体的所有属性 Generate Children Inherit only primary attributes 每个子实体 仅仅继承父实体的标识符(Identifier) 不同的选项导致最终生成的 PDM 模型的不同,如表 2-7 所示。 表 2-7 不同生成选项及生成的 PDM 模型 选择的选项 PDM 中生成的模型 选择 Generate parent 和 Generate children Inherit all attributes 选择 Generate children Inherit all attributes 选择 Generate Children Inherit only primary attributes 选择 Generate parent 和 Generate Children Inherit only primary attributes 选择 Generate parent 如果仅仅选择 Generate parent,窗口下方的 Specifying attributes 可以使用,可以新建数据项或 者选择添加模型中的数据项(Data Item)至生成的 PDM 中的表中。最终生成的 PDM 的表中就包 含这里添加的数据项。 这些选项都不会对转化为 OOM 产生影响,当前 Inheritance 关系的三个实体,转化为 OOM(语 言选择为 Java)的模型如图 2-56 所示。: 作者:姜江 error 85 图 2-56 转化为 OOM 后的继承关系 6. 点击【确定】。 2.3.5 包(Package) 包是模型的一个部分,当系统涉及的模型比较庞大时,一个人处理整个项目就不是十分现实, 因此,可以考虑将模型分为较小的子部分(可以根据模块划分的思想来理解),分而治之。在 CDM 中,包就承担着这样一个职责,代表不同的任务或者问题域,以便分配给不同的研发团队。如图 2-57 所示。 图 2-57 包的实例 包的层次 一个模型中可以创建同层次的多个包,也可以将一个包再分为多个子包,这种层次没有限制, 目的就是更好的实现系统。每个包中可以有一个默认的 Diagram(模型图形)。 创建 CDM 包的方法: 1. 选择 Palette 面板中的 Package 工具 ,在模型中空白的地方点击鼠标左键,或者选择【Model】 →【Packages】,弹出包列表窗口,在列表窗口中创建 2. 点击鼠标右键释放【Package】工具,双击包的图形,弹出包属性窗口,如图 2-58 所示。 作者:姜江 error 86 图 2-58 包的属性窗口的“General”页 3. 输入包的 Name 和 Code 4. 点击 Extended Dependencies 或者 Rules 等属性页,设定包的属性,如图 2-59 所示 图 2-59 包的属性窗口的“Extended Dependencies”页 关于扩展属性,请参考:3.15.5 使用扩展属性。 2.4 域、业务规则和数据项 2.4.1 业务规则(Business Rules) 在该部分中,将向大家介绍什么是业务规则,如何在 CDM 中定义业务规则,以及在 CDM 中如 何使用业务规则。 关于 Business Rules,请参考:3.3.1 业务规则(Business Rules)_业务规则(Business_Rules) 在 CDM 中创建一个新的业务规则(business rule): 1. 选择【Model】→【Business Rules】,将会弹出以下窗口,这个窗口中将以列表的形式 显示模型中目前已经建立好的业务规则。 作者:姜江 error 87 2. 点击列表中的一个空白行 或者 点击窗口上方的第二个按钮 在该行中将会出现一个 箭头 3. 输入 Name 和 Code,并且点击【Apply】应用 4. 双击该行左端,将会弹出业务规则属性的定义窗口 5. 在 Type 的下拉列表中选择业务规则的类型 在属性窗口中还可以对业务规则的表达式(Expression)进行详细的定义,在你创建模 型和分析业务问题的时候,可以通过添加一些技术性的 Expression 将业务规则完整化。当然, 针对不同数据库的 expression 的语法也不尽相同。 每个业务规则包括两种类型的表达式(Expression):  Server:可以被生成到数据库中  Client:这部分 Expression 主要适用于文档的生成。 如图 2-60 所示,创建以下几个 Business Rules : 图 2-60 业务规则列表窗口 6. 在 Notes 中可以对该业务规则进行详细的描述,如图 2-61 所示。 作者:姜江 error 88 图 2-61 在“Notes”页中对业务规则描述 在 PDM 中应用业务规则(BusinessRules) 1. 双击模型中的一个对象,弹出该对象的属性对话框 2. 点击 Rules 的属性页,在这里可以看到已经加载到该对象上的业务规则的列 3. 点击 ,在弹出的对话框中,你将看到模型中现在已经定义好的所有的业务规则,如 图 2-62 所示。 图 2-62 为对象选择业务规则 4. 选择合适的业务规则,点击【OK】按钮。如图 2-63 所示。 作者:姜江 error 89 图 2-63 选择 Rules 后的对象属性窗口 2.4.2 数据项(Data Items) 数据项(Data Item)是概念模型中最基本的信息元素,代表信息系统中的一个事实或者定义, 如果把数据项指定在实体上,则该数据项就成为实体的一个实体属性。将概念数据模型(CDM) 转化为物理数据模型(PDM)时,每个实体属性都相应的转化为表中的一个列。 定义数据好的数据项也可以不指定给某个具体的实体,在需要的时候可以根据需要使用,指 定为实体的属性。选择【Model】→【Data Items】,弹出数据项例表窗口,可以发现,前面定义的 各个实体的属性都作为数据项出现在该列表窗口中,如图 2-64 所示。 图 2-64 数据项列表窗口 例如:出版公司的客户和作者都包含一个重要的信息及 Last Name,因此,可以创建一个 Data Item:LAST NAME,并且分别指定给 Customer 和 Author。另外一个关于 Author 的信息是作者的 生日,创建一个数据项 Data Item:Birth Date,但是,当前并不需要马上使用这个数据项,因 此可以暂时不将该数据项指定给任何实体。 要创建新的数据项,操作方法如下: 1. 选择【Model】→【Data Items】,弹出数据项列表窗口 作者:姜江 error 90 2. 点击空白行或者点击【Add a row】工具 ,输入数据项的 Name 和 Code 均为 Birth Date 3. 在 Date Type 下拉列表选择数据类型为“D”(日期类型),如果是其他的需要指定数据长度和 精度的数据类型,可以在 Length 列指定数据类型长度和精度,点击【Apply】应用。 如果读者不熟悉概念模型中各个数据类型的含义,也可以在 Data Type 列点击工具 , 打开标准数据类型的窗口进行数据类型的选择和设置,如图 2-65 所示。 图 2-65 查看标准数据类型 选择需要的数据类型,点击【OK】按钮确定,PowerDesigner 会自动将标准数据类型转化为 CDM 中的数据类型。关于标准数据类型,请参考:3.3.2 域(Domains)中对标准数据类型的介 绍。 4. 要使用定义好的数据项,打开实体 Author 属性窗口,进入 Attributes 属性页,点击【Add Data Item】工具 或者【Reuse Data Item】工具 ,弹出 Data Item 选择窗口,如图 2-66 所示。 图 2-66 将数据项定义为实体的属性 5. 选择 Birth Date,点击【OK】确定,如图 2-67 所示,实体 Author 新增加一个属性 Birth Date: 作者:姜江 error 91 图 2-67 增加数据项为属性后的实体 Author 为数据项定义 Code 和复用选项,参考表 2-8。 表 2-8 数据项属性含义 选项 选中 未选中 Unique code 每个数据项只能有唯一的 Code 不同的数据项可以包含相同的 Code Allow reuse 数据项可以成为多个实体的属性 数据项可以成为一个实体的属性 如果没有选中 Unique code,则不同的数据项可以包含相同的代码,因此就必须根据使用该数 据项的实体来区别数据项。 1. 选择【Tools】→【Model Options】,弹出模型属性对话框,如图 2-68 所示。 图 2-68 模型属性窗口 2. 根据需要进行选择,点击【OK】。 可能存在的冲突:如果当前概念数据模型中已经有多个实体使用同一个数据项作为实体属性, 而此时又在模型选项中不选择“Allow reuse”复选框,则 PowerDesigner 会弹出图 2-69 所示警告 信息: 批注 [e3]: 此图在上一稿中丢失,改 稿中已添加 作者:姜江 error 92 图 2-69 “Allow reuse”冲突警告窗口 点击【确定】按钮后,又返回模型属性窗口中,如果不希望不同实体间使用相同的数据项作 为实体属性,则必须先对模型中已经使用相同数据项的实体进行相应的修改才可以应用该选项。 详细设置实体属性或者数据项的属性 前面的内容中学习了创建实体属性以及数据项,同时定义了数据类型等属性,同 PDM 中的 列一样,也可以对实体属性和数据项进行详细的属性设置,操作方法如下: 在实体属性窗口中的 Attributes 页面或者 Data Items 列表窗口中,选择需要设置的行,双击行 首的箭头或者点击【Properties】工具 ,弹出属性窗口,如图 2-70 所示。 图 2-70 设置属性或数据项的属性 可以分别定义实体属性或者数据项的 Standard Checks/Additional Checks以及和 Rules进行绑 定。例如,在 Standard Checks 属性页中可以设置属性的取值范围,属性的格式等。 2.4.3 域(Domains) 经常进行数据库建模的设计者可能遇到过这样的情况:很多表中都有一个字段“备注/ Description”,于是在定义数据类型时就不得不一次又一次的输入 varchar(300)或者 varchar(200), 还与许多表中都由相似的字段“地址/Address”,在输入地址的数据类型时,有时候可能输入 varchar(50),有时候也可能输入 varchar(100),这就造成数据类型的标准化控制的非常不好, 在实际的 DBMS 中往往会针对这种情况允许用户自定义数据类型,在 PowerDesigner 的 CDM 和 PDM 中,这种“自定义数据类型”以 Domain(域)的形式出现。请参考:3.3.2 域(Domains)。 作者:姜江 error 93 在 CDM 中创建域的步骤如下: 1. 选择【Model】→【Domains】,弹出域的列表窗口,如图 2-71 所示。 图 2-71 域列表窗口 2. 点击空白行或者点击【Add a row】工具 创建域 Address,输入数据项的 Name 和 Code 均为 Address 3. 在 Data Type 处设置数据列型 VA80,不熟悉概念数据模型中数据类型的形式,可以在 Data Type 处点击 ,打开标准数据类型的窗口进行数据类型的选择和设置 4. 点击【Apply】应用,也可以打开域的属性窗口,对域进行进一步的设置,这和设置实体属性 以及 Data Items 以及 PDM 中列的属性定制类似,这里就不再赘述。 在 CDM 中使用域 双击实体 Author,或者鼠标右键模型中实体 Author 的图形,在弹出的菜单中选择 Properties, 弹出如图 2-72 所示窗口,点击 Attributes 属性页,在 Domain 列为实体属性选择域,点击【确定】。 作者:姜江 error 94 图 2-72 为实体属性设置域 如图 2-72 所示,为属性或者 Data Item 指定 Domain 后,Data Type 列会自动出现域的数据类 型,如果在指定 Domain 后还对 Data Type 进行修改,点击【应用】或【确定】按钮之后,会弹出 如图 2-73 所示确认窗口,询问用户是否确认数据类型和域的数据类型之间的不一致: 图 2-73 域和属性的数据类型不一致确认对话框 如果希望在模型强制数据类型使用指定的域的数据类型,则可以选择【Tools】→【Model Options】,弹出模型属性窗口,选择 Enforce non-divergence,如图 2-74 所示。 选择该选项以后,指定了域的数据项或者实体属性的数据类型就自动采用了域的数据类型, 并且为灰化不可以修改。 作者:姜江 error 95 图 2-74 在模型属性窗口中设置强制数据类型一致 可以对不同实体的多个实体属性指定同一个域(理解为“自定义数据类型”),如果希望知道 域的使用情况,则进入域的属性窗口,点击 Dependencies 属性页,可以看到该域的使用情况,如 图 2-75 所示。 图 2-75 查看域的使用情况 CDM 中的数据类型的格式: CDM 中的数据类型的格式参考表 2-9。 表 2-9 CDM 中数据类型格式含义 Variable Replace with %n Length 作者:姜江 error 96 %s Length with precision %p Decimal precision 修改域的属性 可以在域的属性窗口中修改域的属性,修改后点击【Apply】或者【OK】按钮确认时, PowerDesigner 会弹出确认窗口,询问是否确认修改使用域的 Data Item。 如果在模型属性窗口中选择了 Enforce non-divergence 选项,则如图 2-76 所示。否则,如图 2-77 所示。 图 2-76 选中“Enforce non-divergence”时,修改域属性确认窗口 图 2-77 未选中“Enforce non-divergence”时,修改域属性确认窗口 如图 2-77 所示,Data type 使用该域,则 Data type 自动选择。 2.5 模型的检查/比较/合并 2.5.1 模型检查的选项(Options) 这部分介绍如何验证 CDM 模型的正确性。可以使用 Check Model 功能在任何时候对 CDM 的 正确性进行检查。正确的 CDM 必须复合以下几个规则:  每个对象的名称都是唯一的  每个实体至少包含一个属性  Relationship(关系)必须至少连接向一个实体 选择【Tools】→【Check Model】,弹出 Check Model Parameters 窗口,在该窗口中可以定义 作者:姜江 error 97 模型检查的严重性级别(Error/Warning/Automatic Correction),具体方法为选择某个需要级别 的项,点击窗口上方的【Error】 、【 Warning】 、【 Automatic Correction】 ,进行修 改,如图 2-78 所示。 图 2-78 “Check Model Parameters”窗口 三个图标的含义如表 2-10 所示。 表 2-10 模型检查参数窗口不同图标及其含义 图示 含义 描述 Error 图标为红色,生成数据库时出现了较为严重的错误 Warning 图标为黄色,生成数据库时出现了小错误或者是建议 Automatic 图标为黑框红十字,表明 PowerDesigner 将自动更正这个错误 在 Check Model Parameters 窗口中进入 Selection,可以选择需要对当前模型中检查的对象,默 认为全选,也可以在该页上方的下拉列表中选择检查模型中的某个包进行检查。如图 2-79 所示。 图 2-79 选择要检查的对象 选择好检查的对象之后点击【确定】,Check Model Result List 窗口弹出,显示检查出的错误 和警告,如图 2-80 所示。 作者:姜江 error 98 图 2-80 检查结果列表 2.5.2 模型所检查的涉及的内容 下面是 Check Model Parameters 窗口中 Options 属性页中的各对象及其检查参数: 对象:Package,包的检查参数如表 2-11 所示。 表 2-11 Pakage 的检查参数 参数 含义 手动纠正 自动纠正 Circular dependency 实体之间的依赖关系 形成闭环,包中不可 以包含闭环 删除一个继承连接或者在连接 属性窗口中使得 Dependent 复 选框为不选中状态 — Circularity with mandatory links 实体之间的依赖关系 通过连接形成闭环, 包中不可以包含闭环 在连接属性窗口中使得 Mandatory 复选框为不选中状 态或者删除关系尚的依赖 — Shortcut code uniqueness 同一个命名空间中的 两个快捷方式不能有 相同的代码 改变其中某个快捷方式的代码 — 对象:Domain,域的检查参数如表 2-12 所示。 表 2-12 Domain 的检查参数 参数 含义 手动纠正 自动纠正 Domain name and code uniqueness 域的名称和代码必须 唯一 修改名称或者代码 通过在某个选定对象的 当前名称后面追加数字 修改名称和代码 Inconsistency in check parameters Check Parameters 页 面中输入的最大值、 最小值以及默认值或 者值列表之间不一致 修改Check Parameters 页面中的值,使得各个 值之间保持一致 — Data type 数据类型精度不能大 手动修改使得数据类 — 作者:姜江 error 99 precision and length 于或者等于数据类型 的长度 型长度大于或者等与 精度 Undefined data type 存在没有定义数据类 型的域,所有的域必 须定义数据类型 至少要在在生成 PDM 之 前为域选择数据类型 — Non-valid data type 域的数据类型错误 至少要在在生成 PDM 之 前为域选择正确的数 据类型 — 对象:Data Item,数据项的检查参数如表 2-13 所示。 表 2-13 Data Item 的检查参数 参数 含义 手动纠正 自动纠正 Data item name and code uniqueness 数据项的名称和 代码必须唯一 修改名称或者代码 通过在某个选定对象 的当前名称后面追加 数字修改名称和代码 Data Item not used 数据向没有被任 何实体使用 将数据项添加到某个 实体中使用,如果不 需要该数据项也可以 删除 — Data Item used multiple times 不同的实体都使 用了相同的数据 项 定义数据项的属性时 候保持一致性 — Detect differences between data item and associated domain 数据项和相关连 的域属性不一致 定义数据项的属性时 确保同域一致 域的属性值覆盖数据 项的属性值 Detect inconsistencies between check parameters Check Parameters 页面 中输入的最大值、 最小值以及默认 值或者值列表之 间不一致 修改 Check Parameters 页面中的 值,使得各个值之间 保持一致 — Precision>Maximum Length 数据类型精度不 能大于或者等于 数据类型的长度 手动修改使得数据类 型长度大于或者等与 精度 — Undefined data type 存在没有定义数 至少要在在生成 PDM — 作者:姜江 error 100 据类型的域,所有 的数据项必须定 义数据类型 之前为数据项选择数 据类型 Non-valid data type 数据项的数据类 型错误 至少要在在生成 PDM 之前为数据项选择正 确的数据类型 — 对象:Entity,实体的检查参数如表 2-14 所示。 表 2-14 Entity 的检查参数 参数 含义 手动纠正 自动纠正 Entity name and code uniqueness 实体的名称和代码 必须唯一 修改名称或者代 码 通过在某个选定对象 的当前名称后面追加 数字修改名称和代码 Entity name and code length 模型选项的命名规 范中规定:实体的 名称或者代码长度 最大长度为 254 修改实体的 name 或者 code 的长度 满足这个需求 自动截取实体的名称 和代码使得满足命名 规范中规定的长度 Existence of attributes 实体中至少要包含 一个属性 为实体添加一个 属性或者删除该 实体 — Number of serial types greater than 1 实体不能包含超过 一个序列类型的属 性,序列类型是自 动计算的值 改变适当的实体 属性的类型,使得 实体仅包含一个 序列类型属性 — Existence of identifiers 每个实体至少包含 一个标识符 添加一个标识符 或者删除该实体 — Existence of relationships 每个实体至少有一 个关系 (Relationship) 为该实体添加一 个标识符或者删 除该实体 — Redundant inheritance 实体从另外一个实 体继承不止一次, 这时冗余的 删除冗余的继承 — Multiple inheritance 实体有多个继承, 一般不会出现这种 情况 确认模型中存在 这种情况的必要 性 — 作者:姜江 error 101 Parent of several inheritance 实体的是多个继承 的父亲 确认是否可以将 及各继承合并 — 对象:Entity Attribute,实体属性的检查参数如表 2-15 所示。 表 2-15 Entity Attribute 检查参数 参数 含义 手动纠正 自动纠正 Entity attribute name and code uniqueness 属性名称和 代码不唯一 修改名称或 者代码 通过在某个选定对象的当前名称 后面追加数字修改名称和代码 对象:Entity Identifier,实体标识符的检查参数如表 2-16 所示。 表 2-16 Entity Identifier 检查参数 参数 含义 手动纠正 自动纠正 Entity identifier name and code uniqueness 实体标识符的名称和代 码必须唯一 修改名称或者代码 通过在某个选 定对象的当前 名称后面追加 数字修改名称 和代码 Existence of attributes 实体标识符中至少要包 含一个属性 为标识符添加属性 或者删除该标识符 — Identifier inclusion 标识符不能包含另一个 标识符 删除包含现有标识 符的标识符 — 对象:Relationship,关系的检查参数如表 2-17 所示。 表 2-17 Relationship 检查参数 参数 含义 手动纠正 自动纠正 Relationship name and code uniqueness Relationship 的 名 称 和代码必须唯一 修改名称或者代码 通 过 在 某 个 选 定 对 象 的 当 前 名 称 后 面 追 加 数 字 修 改 名 称 和 代码 Reflexive dependency 依赖表示某个实体通过 另外一个实体来定义, 因此依赖关系不能定义 为自反 改变或者删除自反依 赖关系 — Reflexive mandatory 存在自反强制关系 在关系的属性窗口中 — 作者:姜江 error 102 relationship 不选择强制复选框 Bijective relationship between two entities 两个实体之间存在双向 的一对一的关系时,称 为双射关系,这种情况 应该合并两个实体 合并两个实体或者修 改实体之间的关系 — Name uniqueness constraint for many to many relationship and entities 多对多关系和一个实体 不能使用相同的名称和 代码 修改多对多关系或者 实体的名称和代码, 否则生成的 PDM 会自 动重命名生成的表 — Consistency between dominant and dependent relationships 实体间的依赖关系不能 同时是支配关系 在关系的另一端选择 Dominant 复选框 — 对象:Inheritance,继承的检查参数如表 2-18 所示。 表 2-18 Inheritance 检查参数 参数 含义 手动纠正 自动纠正 Inheritance name and code uniqueness Inheritance 的名称和 代码必须唯一 修改名称或者代码 通过在某个选定对象 的当前名称后面追加 数字修改名称和代码 Existence of inheritance link 继承至少要包括一个从 继承到父实体的继承连 接 定义继承连接或者删 除继承 — 对象:Association, Association 的检查参数如表 2-19 所示。 表 2-19 Association 的检查参数 参数 含义 手动纠正 自动纠正 Association name and code uniqueness Association 的名称和 代码必须唯一 修改名称或者代码 通过在某个选 定对象的当前 名称后面追加 数字修改名称 和代码 Association has at least two links Association 被孤立, 因此没有能够定义实体 之间的关系 至 少 定 义 两 个 Association 和一个或 者多个实体之间的连接 — Association has two 标识符连接导致两个实 删除不必要的连接或者 — 作者:姜江 error 103 links with identifier link 体间出现了依赖关系, 使用这种类型的连接必 须是二元的 使得连接的属性窗口中 的标识符的复选框变为 不选中 Association has no more than one identifier link 标识符连接导致两个实 体间出现了依赖关系, 两个实体之间只能有一 个标识符连接,否则就 会形成依赖环路 在其中一个连接的属性 窗 口 中 使 Identifier 复选框变为不选中状态 — Absence of properties with identifier links 包含标识符连接的 Association 不能包含 任何属性 将 Association 中的属 性移动到依赖实体(通 过一个标识符连接到 Association 的那个实 体)中 — Bijective association between two entities 两个实体之间存在双向 的一对一的关系时,称 为双射关系,这种情况 应该合并两个实体 合并两个实体或者修改 实体之间的关系 — Maximum cardinality links 包含多于一个连接的 association 的连接的 基数只能大于 1 改变这样的连接的最大 基数大于 1 — Reflexive identifier links 标识符连接导致两个实 体间出现了依赖关系, 这 种 类 型 的 Association 不能是自 反 改变实体之间的关系或 者在连接属性窗口中使 Identifier 复 选 框 变 为不选中状态 — Name unicity constraint between many-to-many associations and entities 多对多关系和一个实体 不能使用相同的名称和 代码 修改多对多关系或者实 体的名称和代码,否则 生成的 PDM 会自动重命 名生成的表 — 对象:File Object,文件对象的检查参数如表 2-20 所示。 表 2-20 File Object 检查参数 参数 含义 手动纠正 自动纠正 Embedded file name 在一个模型中不能有 重命名内嵌文件 通过在文件对象的 作者:姜江 error 104 uniqueness 两个内嵌文件对象有 相同的名称 对象的名称 当前名称后面追加 数字重命名文件 Existence of external file location 外部文件对象必须有 一个合法路径 定义一个正确的 路径 — 对象:Replication,Replication 对象的检查参数如表 2-21 所示。 表 2-21 Replication 对象的检查参数 参数 含义 手动纠正 自动纠正 Partial replication 复制品和被复制的对 象之间仅保持部分同 步 在复制属性窗口 中修改复制的属 性列表 强制使不同步的属 性保持与被复制对 象属性同步 对象:Business Rule,业务规则的检查参数如表 2-22 所示。 表 2-22 Business Rule 检查参数 参数 含义 手动纠正 自动纠正 Business rule name and code uniqueness 在一个模型中不能有 两个业务规则使用相 同的名称 修改复制的业务 规则的名称或者 代码 在业务规则的当前 名称后面追加数字 修改名称和代码 Unused business rule 模型中创建的业务规 则没有被使用 应用业务规则到 模型的对象 — 2.5.3 根据检查结果纠正模型 在工具栏上右键鼠标,在弹出的菜单中选中“Check”,各工具的含义如表 2-23 所示。 表 2-23 “Check”工具栏各工具及其含义 工具 功能 含义描述 Manual correction 同双击错误行一样,弹出有问题对象的属性窗口 Display help 显示关于该错误或者建议的帮助信息 Check again 对指定问题重新检查,一般在更正之后执行该操作 Automatic 自动纠正特定的错误 First Error 第一个错误 作者:姜江 error 105 Previous Error 前一个错误 Next Error 下一个错误 Last Error 最后一个错误 也可以 Check Model Result List 窗口的警告和错误上右键鼠标,在弹出的菜单中选择适当的更 正工具。 2.5.4 模型的比较 参考:3.13.4 PDM 模型的比较。 2.5.5 模型的合并 参考:3.13.5 PDM 模型的合并。 2.6 模型转化 CDM 模型的转化 概念数据模型(CDM)可以转化为 PDM(物理数据模型)/CDM(概念数据模型)/OOM(面向对象模 型)。还可以将一个 CDM 中的包转化为其他的模型。当不同的设计人员分别负责同一个模型中的不 同包的时候,这种方法是非常有效的,它能够生成独立的模型。 从 CDM 模型转化到其他模型有两种方式, 如表 2-24 所示。 表 2-24 CDM 模型转化为其它模型的不同方式 转化方式 描述 新建模型(New) 创建一个新的模型,将 CDM 模型中的对象转化至新的模型中 更形模型(Updated model) 创建一个的包含从 CDM 中转化过来的对象的默认模型,然后 将该默认模型(在合并窗口的左侧)和现有的模型(在合并 窗口的右侧)进行合并。可以根据生成的默认模型中的修改 情况,对现有的模型更新、删除或者添加对象。 对于 Updated model 方式,可以理解为:PowerDesigner 根据用户的选择,在内存中生成一个 新的模型,然后弹出模型比较窗口,窗口的左侧是内存中的模型,右侧是已经存在的需要更新的 模型。用户可以在该合并窗口中对需要更新的对象进行相应的设置,从左到右可以理解为“From” 和“To”的关系。 作者:姜江 error 106 2.6.1 从一个 CDM 转化为另一个 CDM 为什么需要从一个 CDM 转化为另一个 CDM? 创建一个模型的新的版本的时候可以从一个 CDM 生成另外一个 CDM,这种转化允许你创建一 个特定模型的拷贝,不同的 CDM 模型分别代表设计的不同阶段,并且定义元模型和生成的模型之 间对象的连接,如果原模型中的对象发生改变,可以使用“Update Existing Model”的生成模式, 直接在生成的模型中反映出来。 从 CDM 模型中生成一个新的 CDM 模型,操作方法如下: 1. 选择【Tools】→【Generate Conceptual Data Model】,弹出生成概念模型窗口,如图 2-81 所示。 图 2-81 从 CDM 生成 CDM 的窗口 2. 选择单选框 Generate New Conceptual Data Model 3. 输入新模型的名称和代码均为:NewCDM 4. 进入 Detail 属性页,可以设置生成的具体选项,例如,是否要检查模型,以及是否生成关系 的依赖性,这里默认都选中,如图 2-82 所示。 图 2-82 设置生成的详细选项 5. 进入 Selection 属性页,在该页中选择需要转化到新模型中的对象,如图 2-83 所示。 作者:姜江 error 107 图 2-83 选择要生成到目标模型中的对象 6. 点击【确定】,当前 Workspace 中生成了新的 CDM 模型。如果需要从模型中的某个包生成新 的模型,则在如图 2-83 所示窗口上方的下拉列表中选择需要转化的包,进行选择。 更新已有的 CDM 模型 如果要更新已有的模型,则在 Generate Conceptual Data Model 窗口中选择 Update Existing Conceptual Data Model,在 Select Model 下拉列表中选择要更新的模型,如图 2-84 所示。 图 2-84 更新已生成过的 CDM 模型 也可以通过点击 Select model 右侧的工具 ,弹出模型选择窗口,进行选择。如果希望保留 现有 CDM 中的对象,请选择 Preserve Modifications,否则所有被更新的 CDM 中的对象都将被删 除,而仅仅保留从当前 CDM 转化过来的对象。其他各个属性页的设置方法同生成新的 CDM 的方 法一致。而 Target Model 则是当前模型快捷方式所指向的目标模型的列表。点击【确定】按钮之 后弹出模型比较窗口,即前面提到的内存中的模型和目标模型之间的比较,用户可以根据自己的 需要对目标模型进行更新,关于模型比较窗口的各种显示和图标的含义,请参考:3.8.3 比较、同 步模型和数据库、通过模型修改数据库。 作者:姜江 error 108 2.6.2 将 CDM 转化为面向对象模型(OOM) 由 CDM 生成 OOM 时,模型中对象转化关系如表 2-25 所示。 表 2-25 CDM 生成 OOM 各对象转化对应表 CDM 中对象 生成 OOM 中对象 Entity Class Attribute Attribute Association Relationship or association Binary association with attributes Association class(关联类) Inheritance Generalization 由 CDM 生成 OOM 时,模型中数据类型转化关系如表 2-26 所示。 表 2-26 CDM 转化为 OOM 时数据类型对应关系 概念数据类型 CDM 中的代码 存储的内容 转化结果(Java) Characters A 字符串 Char Boolean BL 两 个 相 反 的 值 ( true/false ; yes/no;1/0) Boolean Byte BT 256 个值 Bytes Short Integer SI 16 位整数 Short Long Integer LI 32 位整数 Long Integer Integer I 32 位整数 Integer Float F 32 位浮点型数字 Float Number N 固定小数位的数字 Double Text TXT 字符串 String 1. 选择【Tools】→【Generate Object-Orient Model】,弹出生成面向模型窗口 2. 选择 Generate new Object-Orient Model,在 Object Language 下拉列表中选择语言 Java 3. 输入新建模型的 Name 和 Code 均为“NewOOM”, 如图 2-85 所示。 作者:姜江 error 109 图 2-85 从 CDM 生成 OOM 的窗口 4. 点击 Detail 属性页,各选项的含义请参考 CDM 转化为 PDM 部分,如图 2-86 所示。 图 2-86 设置生成 OOM 的详细选项 5. 在 Target Models 中选择当前模型中快捷方式的目标模型 6. 进入 Selection 属性页,选择需要转化的对象 7. 点击【确定】按钮,生成新的模型,如图 2-87 所示。 作者:姜江 error 110 图 2-87 CDM 转化生成的 OOM 模型 更新已有的 OOM 模型 更新已有的 OOM 模型,只需要在 OOM Generation Options 窗口的 General 属性页中选择 Update existing Object-Orient Model,在 Select model 下拉列表中选择需要更新的模型,或者点击 省略号按钮 在弹出的窗口中选择。如果希望保留现有 OOM 中的对象,请选择 Preserve Modifications,否则所有被更新的 OOM 中的对象都将被删除,而仅仅保留从当前 CDM 转化过来 的对象。其他各个步骤的操作方式同新转化为一个 OOM 的步骤相同,最后点击【确定】弹出模 型比较窗口,内存中产生的模型和目标模型之间的比较,用户可以根据自己的需要对目标模型进 行更新,关于模型比较窗口的各种显示和图标的含义,请参考:3.8.3 比较、同步模型和数据库、 通过模型修改数据库。 2.6.3 将 CDM 转化为物理数据模型(PDM) 从 CDM 转化为 PDM 时,PowerDesigner 会自动将 CDM 中的对象和数据类型转化为 PDM 的 对象和支持的数据类型。 CDM 到 PDM 之间概念对象和物理对象之间的转化参考表 2-27。 表 2-27 CDM 转化为 PDM 时各对象对应关系 CDM 对象 PDM 中生成的对象 Entity Table 作者:姜江 error 111 Entity Attribute Table Column Primary Identifier 根据是否是依赖关系确定是主键或者是外键 Identifier Alternate Key Relationship Reference 一张表中的两个列不能有相同的名称,因此如果因为外键迁移而导致列名冲突,则 PowerDesigner 会自动重命名迁移列。新列名由原始实体的名称的前三个字母加属性的代码组成。 由标识符生成键 CDM 中的 Identifier(标识符)最终将转化为 PDM 中的主键、外键或者候选键,一般的 Identifier 转化为候选键,而 Primary Identifier 根据关系的两个方向的基数(Cardinality)和依赖类型转化为 主键或者外键。 非依赖一对多关系(Independent one-to-many relationships) 图 2-88 CDM 中非依赖一对多关系 如图 2-88 所示。在非依赖性一对多关系中,“一”端的 Primary Identifier 将转化为主键,“多” 端将生成一个同“一”端主标识符同名称的外键。如图 2-89 所示。 图 2-89 CDM 中非依赖一对多关系转化生成的 PDM 依赖一对多关系(Dependent one-to-many relationships) 图 2-90 CDM 中依赖一对多关系 如图 2-90 所示。在依赖性一对多关系中,被依赖段的主标识符转化为主键,而依赖端则产生 一个同被依赖端主标识符同名称的字段同时作为依赖端的主键和外键,如果该实体中已经有主标 识符转化为主键,则该键同主键共同组成主键,同时也是外键,如图 2-91 所示。 作者:姜江 error 112 图 2-91 CDM 中依赖一对多关系转化生成的 PDM 非依赖多对多关系(Independent many-to-many relationships) 图 2-92 CDM 中非依赖多对多关系 如图 2-92 所示。在非依赖性多对多关系中,每个实体的主标识符都会被迁移到一个新生成的 连接表中作为外键,同时共同组成主键,如图 2-93 所示。 图 2-93 CDM 中非依赖多对多关系转化生成的 PDM 非依赖性一对一关系(Independent one-to-one relationships) 图 2-94 CDM 中非依赖一对一关系 如图 2-94 所示。在非依赖性一对一关系中,前面在定义 Relationship 的时候讲到,如果没有 定义一对一关系的 Dominant Role 的方向,则每个实体主键都被迁移到另外一个表中作为外键。 如图 2-95 所示。 作者:姜江 error 113 图 2-95 CDM 中非依赖一对一关系转化生成的 PDM 如果定义 Dominant Role 为 Author→Picture(在 Details 属性页中定义), 如图 2-96 所示。 图 2-96 定义一对一关系的支配关系 则 Author 的主键作为 Picture 的外键,即处于 Dominant 角色的实体产生的表的主键被迁移作 为另外一个表的外键。如图 2-97 所示。 图 2-97 定义支配关系后生成的 PDM 模型 CDM 到 PDM 数据类型的转化 PowerDesigner 同时支持概念数据类型和物理数据类型。CDM 模型中选择的数据类型不一定 在所有的 DBMS 中都支持,因此,当从 CDM 转化到 PDM 中时,数据根据具体 DBMS 的特点转 化为支持的数据类型。 在 PowerDesigner 中,每个 DBMS 都包含数据转化的规则。 作者:姜江 error 114 1. 选择【Tools】→【Resources】→【DBMS】,弹出 DBMS 列表窗口, 2. 选择需要查看或者修改的 DBMS,双击或者点击【Properties】工具 ,弹出 DBMS 属性窗口, 如图 2-98 所示。 图 2-98 CDM 和 PDM 数据类型转化对应关系 3. 选择【Script】→【PhyDataType】,如图 2-98 所示,右端显示物理模型和概念模型之间的数据 类型转化关系。 如果用户不熟悉概念模型中数据类型的含义,也可以参考该 Conversion Table 学习。也可以在 适当的时候根据自己的需要对这这个转化表进行修改,但是一般情况下最好对 PDM 采用 Copy: Create a copy of the DBMS definition in model 方式,这样作的目的是防止 PowerDesigner 自带的 DBMS 文件遭到损坏。 将 CDM 转化为 PDM 的操作方法如下: 1. 选择【Tools】→【Generate Physical Model】,弹出生成物理模型窗口 2. 选择 Generate new Physical Data Model,在 DBMS 下拉列表中选择目标 PDM 的 DBMS 3. 输入新建模型的 Name 和 Code 均为“JustTest” 4. 选择 Copy:Create a copy of the DBMS definition in model 方式或者 Share:Use the shared DBMS definition,如图 2-99 所示。 作者:姜江 error 115 图 2-99 从 CDM 生成 PDM 的窗口 5. 点击【Configure Model Options】按钮,在弹出的模型属性窗口中配置新 PDM 模型的属性。 6. 进入 Detail 属性页,定义转化为 PDM 时的选项,如图 2-100 所示。 图 2-100 在“Detail”页设置详细生成属性 该属性页中左侧复选框的含义如表 2-28 所示。 表 2-28 “Detail”页分“Options”部分各选项含义 选项 描述 Check Model 生成 PDM 之前检查模型,如果检查到错误停止模型转化 Save Generation Dependencies 自动记录每个生成对象的身份,合并从同一个 CDM 转化出来的两个 PDM 时,这个选项非常有用,它将使得对象之间能够比较,并且识别 为同一个对象,甚至即使对象在目标 PDM 已经被修改,也可以识别出 来 作者:姜江 error 116 Convert Names into Codes 选择该选项后,对象名称能够使用相应的转化脚本生成代码。当生成 的模型使用相当复杂的命名习惯时,这个选项很有用,例如,一个 Java 类 的 属 性 代码 为 “customerName”,而 PDM 中表 的 列 的 代码 为 “CUSTOMER_NAME”。如果选择这个选项,则每个对象都可以从自 己的 Name 转化为适当形式的 Code,如果不选择,则对象代码直接拷 贝原始对象的代码。 Rebuild Triggers 允许自动重建触发器(with Preservation),生成 PDM 模型后,如果选 择的是更新现有模型,则重建工作会在合并模型后发生。 Table Prefix 表示生成 PDM 中表的前缀,Reference 处的各个参数的含义如下:Update Rule (引用完整性的默认的更新约束);Delete Rule(引用完整性的默认的删除约束);外键命名模板 处,两个选项分别为“Always use template”和“Only use template in case of conflict”,默认情况选 择后者,即发生冲突时采用外键命名模板:“%.3:PARENT%_%COLUMN%”,用户完全可以直接 在模板下拉列表处直接输入自己期望的命名方式,相当于创建了新的命名模板。在命名模板中可 以使用如表 2-29 所示的量。 表 2-29 Reference 命名模板可以使用的变量 变量 值 %REFR% 引用(Reference)的生成代码 %REFNAME% 引用(Reference)的名称 %REFRCODE% 引用(Reference)的代码 %PARENT% 父表的生成代码 %PNAME% 父表的名称 %PCODE% 父表的代码 %COLUMN% 父列的生成代码 %COMNNAME% 父列的名称 %COLNCODE% 父列的代码 %KEY% 和引用相关连的键的约束的名称 %CONSTNAME% 和引用相关连的键的约束的名称,同%Key%等同 %KNAME% 和引用相关联的键的名称 %KCODE% 和引用相关联的键的代码 %PROLE% 生成父表的实体的角色,这个变量从概念环境中获得。 如果 relationship 或者 association 没有定义角色,则% PROLE%会使用%PARENT%的内容代替,目的是为了 避免产生没有名称的列 在索引的各项参数中,Key index names 表示候选键的命名方式,FK threshold 表示:需要在外 作者:姜江 error 117 键上创建索引要求的实体的记录数的最小数目。关于索引的命名模板中可以使用的变量这里就不 再赘述,有兴趣的读者可以查看 PowerDesigner 自带的帮助。 7. 点击 Target Models 属性页,选择当前模型中快捷方式的目标模型 8. 点击 Selection 属性页,选择需要转化的对象,这里选择全部 9. 点击【确定】,生成需要的 PDM 模型。如图 2-101 所示。 图 2-101 CDM 转化生成的 PDM 模型 更新已有的 PDM 模型 更新已有的PDM模型,只需要在PDM Generation Options窗口的 General属性页中选择 Update existing Physical Data Model,在 Select model 下拉列表中选择需要更新的模型,或者点击省略号按 钮 在弹出的窗口中选择。如果希望保留现有 CDM 中的对象,请选择 Preserve Modifications, 否则所有被更新的 PDM 中的对象都将被删除,而仅仅保留从当前 CDM 转化过来的对象。其他各 个步骤的操作方式同新转化为一个 PDM 的步骤相同,最后点击【确定】弹出模型比较窗口,内 存中产生的模型和目标模型之间的比较,用户可以根据自己的需要对目标模型进行更新,关于模 型比较窗口的各种显示和图标的含义,请参考:3.8.3 比较、同步模型和数据库、通过模型修改数 据库。 2.7 将其他软件模型转化为 CDM 2.7.1 将 Erwin 的模型导入 CDM ERwin 也是一种常用的数据库建模工具,除了数据库建模之外,目前 ERwin 也开始逐步支持 业务流程建模、面向对象建模等等。实际工作中使用 ERwin 进行数据库建模的也不在少数,所以 经常会需要把 ERwin 中设计的模型导入到 CDM。 作者:姜江 error 118 ERwin 建立的模型将概念模型和物理模型统一在一个文件中,如图 2-102 所示,该模型为 ERwin4.1.4 中示例模型。本节就以此为例,将该模型导入到 PowerDesigner 中转化为 CDM 模型。 图 2-102 在 ERWin 中打开自带的模型 可以在不损失任何元数据(metadata)的情况下将 Erwin 的模型导入为 CDM 模型或者 PDM 模型,ERwin 模型中对象转化为 CDM 模型对象之间的对应关系如表 2-30 所示。 表 2-30 ERwin 到 CDM 模型转化时各对象对应关系 ERwin 模型中的对象 导入到 CDM 模型中的对象 Model Model Stored display and subject area Diagram Business rule Business rule Domain Domain Attribute Data item,entity attribute Key group Identifier Entity Entity Relationship Relationship Subtype relationship Inheritance link Symbols(including symbol size and position) Symbols(including symbol size and position) Description Description Notes Annotation Text block Text symbol 用户定义的属性 可以被导入为扩展属性,存储在特定的扩展模型 定义中,扩展模型定义的名称就是导入的属性 作者:姜江 error 119 由 ERwin 模型转化为 PowerDesigner 中的模型简单而可靠,PowerDesigner 支持新的 ERwin XML 格式的输出文件,模型转化步骤是不同版本而有所区别,参考表 2-31。 表 2-31 不同 Erwin 版本转化为 PowerDesigner 模型的选项 ERwin 的版本 导入选项 ERwin 3.x 可以在 CDM,PDM 以及 Synchronized CDM 和 PDM 之间选择 ERwin 4.x 如果是概念模型,则导入为 CDM 如果是物理模型,则导入为 PDM 如果是既包含概念模型也包含物理模型模型,可以在 CDM,PDM 以及 Synchronized CDM 和 PDM 之间选择导入为哪一种 导入 ERwin 文件的操作步骤为: 5. 选择【File】→【Import】→【ERwin file】,弹出标准的打开窗口,点击文件类型的下拉 列表,可以发现 PowerDesigner 支持导入的几种文件格式,如图 2-103 所示。 图 2-103 选择要导入 Erwin 文件的格式 6. 图 2-102 中所示的模型为 ERwin4.1.4 中示例模型 Emovies.ER1,因此这里无法导入,所 以,可以先在 ERwin 中将该模型另存为 XML 文件格式,然后在这里导入,弹出格式选 择窗口,如图 2-104 所示。 图 2-104 选择要导入生成的模型类型 7. 选择 PowerDesigner Concept Data Model,点击【OK】按钮确定。 8. 成功导入至 PowerDesigner 后的 CDM 模型如图 2-105 所示。 作者:姜江 error 120 图 2-105 将 Erwin 模型导入到 PowerDesigner 中的 CDM 模型 注意:如果 ERwin 模型为混合模型(Mixed Model),则可以将该模型导入为 Synchronized CDM /PDM 对,这不适用于 ERwin 逻辑模型。PowerDesigner 将自动执行以下步骤  将 ERwin 导入为 CDM1  将 ERwin 导入为 PDM1  将 CDM1 生成 PDM2  合并 PDM1 与 PDM2 在本例中,如果在图 2-104 所示的格式选择窗口中选择 PowerDesigner synchronized CDM/ PDM pair,则转化完毕后,会自动生成一个 CDM 和一个 PDM,如图 2-106 所示。 图 2-106 同时生成 CDM 和 PDM 模型 PowerDesigner synchronized CDM/PDM pair 即 CDM/PDM 两个保持同步的模型。保存两个 模型时,会弹出如图 2-107 所示的确认窗口,表明模型之间的关联(连接、引用、快捷方式等) 图 2-107CDM/PDM 模型同步确认对话框 感兴趣的读者可以自己学习,这里不再赘述。 作者:姜江 error 121 2.7.2 在 CDM 中打开 PAM(ProcessAnalystModel) 早期的 PowerDesigner 6.1 包含 6 个紧密联系的模块:  PowerDesigner ProcessAnalyst,用于数据发现。  PowerDesigner DataArchitect,用于双层,交互式的数据库设计和构造。  PowerDesigner AppModeler,用于物理建模和应用对象及数据敏感组件的生成。  PowerDesigner MetaWorks,用于高级的团队开发,信息的共享和模型的管理。  PowerDesigner WarehouseArchitect,用于数据仓库的设计和实现。  PowerDesigner Viewer,用于以只读的、图形化方式访问整个企业的模型信息。 而 PAM 则为 PowerDesigner 6.1 中 Process Analyst 的流程分析模型,这种模型的主要建模方 法为数据流程图,即 DFD(Data Flow Diagram),扩展名为 PAM。在 PowerDesigner 9.5 以及 PowerDesigner 10 的版本中都支持将 PAM 模型导入为 CDM 模型。 PAM 模型与 CDM 模型中对象对应的转化关系如表 2-32 所示。 表 2-32 PAM 模型到 CDM 对象转化对应关系 PAM 中的对象 导入到 CDM 中的对象 Business rule Business rule Domain Domain Data store Entity Data item Data item 把 PAM 模型导入为 CDM 的操作方法如下: 1. 选择【File】→【Open】,弹出标准的打开窗口 2. 在文件类型下拉列表中选择 ProcessAnalystModel(*.pam),选择存放 PAM 模型的目录 3. 选择要转化的 PAM 文件,点击【打开】按钮,弹出 ProcessAnalyst 模型导入窗口 4. 选择 PowerDesigner Conceptual Data Model,如图 2-108 所示,点击【OK】 图 2-108 导入生成何种模型类型 5. 完成导入,自动显示导入后的模型图形。 作者:姜江 error 122 2.8 PowerDesigner 10 中 CDM 模型的不同表示方法 第一章在介绍 PowerDesigner 10 的新特性的时候提到过,CDM 模型和 PDM 模型都增加了对 IDEF1X 表示方法的支持。 下面我们就以一个模型为例,说明如何使用不同的模型表示方法。如图 2-109 所示。 图 2-109 修改表示方法之前的模型 选择【Tools】→【Model Options】,弹出模型选项窗口,如图 2-110 所示。在 Notation 下拉 列表中可以选择图形模型表示方法为 Entity/Relationship、Merise、E/R+Merise 以及 IDEF1X 四种, 选择需要的 IDEF1X 方法后,点击【OK】确定。 图 2-110 选择不同的 CDM 模型表示方法 如图 2-111 所示,该模型为选择 IDEF1X 转化生成的模型图形。 批注 [e4]: 此处编号错误,已修改 批注 [e5]: 此处缺图已添加 作者:姜江 error 123 IDEF1X 表示方法的含义,参考表 2-33。 表 2-33 IDEF1X 表示方法参考 关系描述 图形表示 一对多,父列可为空 一对多,父列不可为空 一对一或多对多 一对一依赖,显示为连续的直线,并且有一个 实体为圆角矩形 图 2-111 选择 IDEF1X 后的模型图形 不过 PowerDesigner 10 中不支持如图 2-112 和图 2-113 所示的两种表示方法。 图 2-112 PowerDesigner 不支持的第一种表示方法 作者:姜江 error 124 图 2-113 PowerDesigner 不支持的第二种表示方法 作者:姜江 error 125 第3章 物理数据模型(PDM) 前面几章介绍了数据库、PowerDesigner 的基本概念,为我们进一步学习奠定了理论基础,同 时还介绍了如何使用 PowerDesigner 建立独立于 DBMS(数据库管理系统)的概念数据模型,可 以将概念数据模型理解为对现实世界的抽象理解,创建概念数据模型时可以完全不考虑最终选择 的 DBMS,脱离物理实现的考虑。设计数据库通常是从概念模型开始设计。在概念设计这个层次 上,不需要考虑物理实现的细节。设计好 CDM 之后,可以通过 CDM 到物理数据模型(PDM) 的转化。然后再根据具体的 DBMS 的特点对物理数据模型进行定制,完成物理实现,这种清晰的 思路比较容易理解和控制。 而本章中要介绍的物理数据模型(PDM)则是对概念数据模型进行物理实现,是需要和 Microsoft SQL Server 、Oracle 等具体的 DBMS 打交道的模型。因此,PDM 将比 CDM 更加具体、 细节,并且具有数据库相关性,也更能为实际的编程人员创造价值。 在使用 PowerDesigner 等数据库建模工具之前,许多数据库设计的工作不得不在纸面上或者 “人脑中”进行,在整个设计工作中,没有足够的控制能力保证数据库设计的一致性、完整性、 直观性、可恢复性„„。让我们先来听一听数据库设计开发人员的抱怨吧:  概念模型和物理模型之间不能相互转化,模型之间的复用性和整合性不强  数据库的表设计命名不规范,使用时经常需要查看数据字典  数据字典提供的数据库设计直观性不强,而模型以直观的图形方式能够清晰的  数据库和文档(例如:数据字典)之间也无法实现无缝连接,数据库改变时,必须手动 修改数据字典,数据库和文档之间经常不能保持一致,带来很多不必要的麻烦  “为了文档而文档”,因为数据字典的创建工作是手动的,设计人员往往迫于领导在进度 方面的压力而不得不将数据字典等文档创建工作的优先级排到最低,迅速进入实际开发 工作中,项目结束时,又不得不“补文档”,如果数据库非常庞大,甚至需要专门的人员 耗费数月的时间来创建文档。这在中国的大部分软件企业中是相当普遍的情况,文档没 有发挥应有的在沟通方面的作用,反而成为被众人不屑一顾“累赘”和“无用功”,这不 得不说是中国软件业的悲哀之一  当物理数据库(DBMS)因为某些原因不得不改变时(例如:Microsoft SQL Server 2000 切换为 Oracle9i),所有的设计工作或者数据库创建工作必须重新进行,由于数据库设计 和开发人员不可能对所有 DBMS 都熟悉,例如:手动书写 SQL 语句创建数据库表结构 (也可以在 DBMS 提供的图形工具中进行),这些重定义工作不得不根据 DBMS 的具体 特点来进行,因此,会产生一定的技术屏障。同时,如果数据库结构比较复杂,表的数 量(如 300 张数据库表)很庞大,输入工作的效率也十分低下  模型设计和数据库创建无法无缝连接,造成重复输入,模型或者数据库改变时,无法保 证数据库和模型的同步,造成沟通困难,导致延误工期  创建好物理数据库之后,为了便于程序调试,经常需要手动输入一些测试数据(考虑到 作者:姜江 error 126 数据安全等方面的因素,实际的业务数据通常不能被数据库编程人员使用),某些特定的 功能可能还需要大量测试数据的手动输入。当数据库结构有调整后,开发人员可能会面 临着再次输入测试数据的困境,无法专注于真正有价值的工作  当数据库的架构非常庞大时,一个人往往无法控制所有的工作,所以不同数据库设计人 员负责数据库设计工作的不同部分,这些不同的模型之间的比较、同步以及合并非常困 难,造成了许多重复设计和不一致,最终影响项目的进度  有些工具虽然可以解决上述的一些问题,但是扩展性也不够强,当设计者遇到一些新的 问题时,由于模型自身的扩展能力和可定制能力不足,造成了相当的困难  „„ 这些问题都是笔者在和数据库设计人员交流的过程中,发现并且归纳概括出来的典型问题, 它们是困扰着很多程序员,造成效率和沟通问题的罪魁祸首,而 PowerDesigner 的出现使得许多 问题迎刃而解,许多工作将变得非常容易。在这章中,我们将逐步学习 PowerDesigner 的一些强 大功能。 学习思路: 本章将围绕我们假设的一个项目进行分析和设计,根据需求建立模型,以不同的知识点为主 线,以实例为依托,目的是使读者全面了解 PowerDesigner 中 PDM 的相关知识。 项目背景:某学校信息管理系统,需要实现的功能包括管理学生的个人信息和课程、教师、 教材等相关信息的管理,由于该系统为假设的项目,所以许多地方的设计没有非常严格的根据实 际需求来做,模型的建立和修改是为了方便各个知识点的讲解,因此读者不必细究模型的合理性 以及与现实项目之间的差异性。 以下为本章的主要内容:  数据库基本概念和 SQL 语言简介  创建 PDM,定义表、视图、存储过程、权限控制以及触发器等数据库对象  通过 PDM 直接生成数据库脚本(SQL)  创建数据库测试数据  反向工程数据库,数据库和模型之间的同步  模型正确性的检查、模型的转化、比较以及合并  对数据库的规模进行估计  使用 PowerDesigner 中的变量,定义 PowerDesigner 中的 DBMS 源文件 3.1 数据库基本概念 本节主要介绍关系数据库,关系数据库是以关系模型为基本结构而形成的数据集合。一个关 系数据库由若干张数据表(二维表)组成。本书中主要以SQL Server 2000为例,所以这里以SQL Server 2000 为例,简单介绍关系数据库的一些基本概念。 下面简介SQL Server的基本结构。 作者:姜江 error 127 在SQL Server中,数据库存储所有的东西。这些数据库都由物理和逻辑组件两部分组成。逻 辑组件是用户在使用数据库时实际看到的。数据库的物理组件用户不能直接看到,它是SQL Server 与之交互来形成逻辑组件的那部分。 物理数据库组件 SQL Server中的每个数据库都至少包括两部分物理组件。这些组件以文件形式存储在服务器 的硬盘上。这两个文件包含了所有用户输入服务器的内容和SQL Server用来维护自身正常运行所 需的信息。用户很少和这些文件打交道。而数据库管理员正是管理这些文件的人。这些文件有两 种类型:数据文件和日志文件。 数据文件是SQL Server用于存储用户输入数据库的所有信息和在数据库中建立的所有对象。 这些文件可以按所设置的格式,随需要变长或缩短。 数据库中的日志文件是SQL Server用来存储数据库事务日志的。事务日志用来维护数据库的 一致性并藉此来保证对数据库的所有修改要么被完整地执行,要么被取消。如果服务器在意外事 件中被破坏了,SQL Server将检查事务日志来保证用户所有的数据修改都是完整。 逻辑数据库组件 数据库与数据文件的相似之处在于它们都是用来存储数据的。用户可以输入数据到数据库中, 然后再从数据库中找到数据。也像数据文件一样,用户很少直接访问存储在数据库的数据。通常 他们运行一个应用程序来从数据库或数据文件中找到数据,用一种可读的和能理解的格式表示出 来。 数据库和数据文件主要的不同是数据库中的数据是高度组织的,检索起来更容易。在设计正 确的数据库中,很少有冗余的数据存储。这使数据库开发员的工作非常容易,因为如果他们需要 修改一组数据的话,比如地址,他们只要到一个地方便可全部修改。关系型数据库就是这样的。 关系型数据库是最有效的管理数据的方式之一。关系型数据库管理系统是关于数据怎样才能 高效存储的数学理论的应用。在所有的关系型数据库管理系统中,所有的数据都存储在按表分组 的数据库中。一个表,作为数据库理论中的一种关系,是某些批量数据的代表,它对组织收集来 的数据是非常重要的。例如:许多公司要在一个数据库中跟踪公司雇员的情况。数据库的每个表 都包含了对于跟踪雇员情况非常重要的信息。这些表包含列(也称为属性)和行 (也称为组或记 录)。回到雇员跟踪数据库中,你可能有一个表跟踪雇员的基本情况,如雇员的号码、姓名、地址、 电话号码和部门。数据库中另一个表可能包含雇员目前被分配的工作。雇员同时可能有多份工作 任务。关系型数据库设计中最重要的部分之一是表中的重复数据非常少。例如:如果在数据库中 不只一列包含有雇员的电话号码,这个数据库就设计得不好。由于每个雇员可能被分配了许多项 目,你需要通过一个唯一的I D (如雇员号)来连接雇员到这些项目。 数据库对象 现在你对关系型数据库到底是什么有了一些了解,我们需要学习存在于数据库中的东西。这 些东西叫对象,它们可以是从表到在数据库中用来执行应用程序功能的一小段代码的任何东西。 在本节中,将学习并定义这些数据库对象。 作者:姜江 error 128 表 表是由列和行组成的一种简单的数据库对象,它可用来存储数据。在数据库中可以有多达20 亿个表,每个表可以有1024列。唯一限制数据库中行数的因素是你用来放置数据库的磁盘的空间。 在SQL Server的表中每行的长度最多是8060字节。表中每列只能包含一种数据类型。SQL Server 支持两种类型的表:永久表和临时表。 永久表在数据库中建立后一直存在,直到被删除。通常,这些表用来存储永久数据,诸如你 的用户创建的任何东西。这些表建立在指定的数据库中。 另一类表是临时表。这些表通常由用户应用程序创建用来存储临时数据。有两种类型的临时 表。第一类是局部临时表。该表由一个用户建立并且只能供这位用户访问。另一类临时表是全局 临时表。这类表由一名用户建立而本系统中的每个用户都可访问。这些表建在tempdb数据库里。 局部临时表在创建它的用户退出系统时被清除。全局临时表在创建它的用户退出系统时被删除, 而那些正引用它的用户也将退出引用。临时表创建时用前缀#表示局部临时表,用##表示全局临时 表。 视图 视图本质上是与表相关的,因为视图本质上就是虚拟表。视图用另一种方式来代表一个或多 个表中的数据。视图只能建立在你当前正在使用的数据库中。下面是使用视图的一些理 由: 1. 集中到特定的数据上:使用视图的最好理由之一是把用户的注意力集中到数据库工作中 要用的特定的数据上。这对用户来说非常有用,这样他就可以只得到需要的数据而没有 别的。例如,你可以建立一个基于雇员姓名和电话号码的视图来生成一张电话号码表。 2. 简化查询:视图是基于那些通常非常复杂的查询而建立的。那些查询要跨许多表,建立 一个列组合,并执行子查询。因为可以代替执行复杂的查询,所以视图可以使之简化, 这样用户只需要查询视图。例如可以建立一个视图从几个表中找到数据来告诉管理员哪 个雇员在哪个项目管理员管理下干哪个项目。 3. 定制数据:视图允许用户根据他们的需要,用不同的技巧和功能,以不同的方式来查阅相 同的数据。例如可以建立一个只含某个经理领导下的雇员的数据的视图。 4. 安全性:视图在你处理高密级的数据时很有用。可以建立一个视图只允许用户看一个表中 一部分特定的数据,而不允许看到表本身。换句话说,你的用户可以通过视图访问这些 数据,但是如果用户试图访问表本身时,访问将失败。例如工资单信息。你可以建立一 个视图允许人们查阅一些基本情况,如姓名和部门,但是当用户要查阅那些人工资的数 额时,就会受到阻止。 5. 导出数据:可以建立一个基于多个表的视图,然后用SQL Server Bulk Copy Program(批 拷贝程序,BCP)拷贝视图引用的行到一个平面文件中。这个文件可以加载到Excel或类似 的程序中供分析用。 6. 简化对切分数据的访问:许多时候,对于那些很活跃的数据库,你要把其中的大表按某个 作者:姜江 error 129 标准(比如日期)切分成小表。这样在某种程度上会增加查询难度。为了简化,你可以建 立一个视图,然后简单地查询这个视图即可。对你来说非常重要的是,要认识到在视图 中没有存储任何数据。视图仅仅是一种较简单的访问数据库里其他表中数据的方式。 当你和视图打交道时,主要问题之一是什么时候执行插入、修改、删除操作。在一个涉及几 个表的视图中,你不能执行任何这些数据修改操作。 索引 索引是一种特殊类型的数据库对象,它与表直接相关。索引用来提高访问表中数据的速度, 并能使一些数据完整性问题得到强制,如表中行的唯一性。索引包含了由表中至少一列所构成的 键值。这些键值使得SQL Server能很快地指向表中的行而无需扫描全表。如果你创建一个没有建 立索引的表,SQL Server在存储数据到表中时不会有什么特别的顺序。 如下所述,SQL Server中可以建立两种类型的索引: 聚簇索引(clustered):在簇索引中,SQL Server按它被索引的顺序来存储数据。例如:在一 个包含姓氏的表中,如果按姓氏索引,SQL Server就会依字母顺序来存储姓名。如果这个键值是 基于数值类型列建立的,SQL Server将按数值大小顺序来存储数据。这类索引对查找指定行或指 定范围的行是非常有用的。只有当表中有了簇索引后,表中的数据才可以按某种顺序来存储。在 每个表中你只能建立一个簇索引,因为数据不可能同时按不同的顺序存储。 非簇索引(nonclustered):非簇索引与簇索引按完全不同的结构对数据排序。非簇索引有一 个索引键值与行中的值相关联,这样就有一个指针可指向该行在数据库中的实际位置。表中的数 据并没有按非簇索引指定的顺序存储。你可以经常看到这种类型的索引在表中使用,如在一组列 中有一个簇索引,而表却要经常搜索另一组列,所以在这些值上建一个索引是很重要的。使用索 引时,一定要记住经常用来查找的那些列(如雇员的ID号或姓氏)应该用作索引。这样会大大加速 查找数据的进程。 数据类型 数据类型用来定义你要放进表中的数据或变量的类型。通常有几种目的。第一,它将告诉SQL Server将有什么类型的数据,这样可为该数据类型优化存储空间分配。第二,它可让开发人员去 决定采集哪种类型的数据—例如,数值型或字符型,并强制用户输入相同类型的数据。任何输入 不同于该类型的数据的尝试都会出错。最后,数据类型确保了表中所有行的一致性。 SQL Server中有许多不同的数据类型可选用。如果这些数据类型对你来说不够用,你也可以 创建自己的数据类型,但必须要基于SQL Server所提供的原始数据类型。 约束 约束是确保数据库中的数据按你所需的形式存在的一种方法。约束可用来定义数据格式的规 则、在一个表中确保唯一性、保证数据能实际填入一列、保证多表间的列的完整性。如下所述, SQL Server用到五种类型的约束: 1. 非空(NOT NULL):这种类型的约束用来迫使用户一定要在表中指定的列中输入一个值。 每个表中你可以有多个非空约束。例如:在一个电子电话号码簿应用程序中,你想要保 作者:姜江 error 130 证每一个新名字增加时,都要有一个名字和一个电话号码。你可以注明这些列的约束条 件是数据为非空。这样,如果用户试图向表中输入这些列包含空值(NULL)的行时,都将 失败。 2. 检查(CHECK):检查约束用来指定一个布尔操作,它让SQL Server限制可输入到表中的值。 如果布尔表达式值为假,则该行被拒绝并产生一个错误。例如:检查约束可以用来告诉 SQL Server奖金列的值必须限制在2%到15%之间。这样,不管什么时候,只要有值输入该 列,都会用该约束来检查以保证数据有效。在每个表和每个列中你都可以建立多个检查 约束。 3. 唯一性(UNIQUE):唯一性(UNIQUE)约束用来迫使用户的应用程序都必须向列输入一个唯 一的值。如果用户试图输入一个该列中已经存在的值,此行将被拒绝并产生一个错误。 如果该列有允许空值的约束,唯一性(UNIQUE)约束也允许空值。 4. 主键(PRIMARY KEY):主键约束用来建立一列或多列的组合供SQL Server在表中来识别每 行。主键用来强制所谓的实体完整性,这意味着主键的列必须具有唯一性。每张表中只 能有一个主键,并且构成主键的每一列不能允许空值。如果主键由几列定义,一定要记 住这些列的组合值必须是唯一的。 5. 外键(FOREIGN KEY):外键约束用来在两张表中建立一个链接。当在一个表中作为主键的 一列被增加到另一个表中,链接就建立了。外键约束的主要功能是阻止用户键入在另一 个表中没有相关行的数据到表中。例如:在一个订货处理环境中,你可能有两张表分别 为客户表和订单表。订单表有一个引用客户表的外键约束。其中的原因是你总希望订单 表中每条记录在客户表中都有对应行。否则,你的运输部门有一批货要运,但是却不知 道往哪里运。如果能正确使用,约束将是一个非常强大的工具。 存储过程 存储过程是一组已被编辑在一起的执行某种功能的SQL语句。它们可以用来向用户返回 数据并且可以获得对应用逻辑的统一执行。如下所述,使用存储过程大有益处: 1. 人们可以把用于完成相同任务的SQL语句和逻辑在一个地方进行设计、编码、测试。然后, 需要用到该功能的应用程序都可以执行该存储过程。 2. 存储过程可以节省因执行大块SQL脚本而增大的网络通信量,从而提高服务器效率。这样, 所有的客户机只需要执行这个单独的存储过程就行了。 3. 存储过程能使你的用户不必去了解有关表结构的每件事。他们只需要知道去执行一个存 储过程来得到明确的结果。 触发器 触发器与存储过程相似,因为事实上它们都是一组SQL语句。主要区别在于触发器是怎样执行 的。当表中的一行被插入、修改或删除时,触发器被执行,这要依赖于触发器是怎样创建的。当 数据被修改时,触发器是保证业务规则的非常强大的方法。一个表可以有最多三个不同的触发器。 你可以有一个在修改发生时进行触发的触发器,一个由插入来触发的触发器,一个由删除来触发 作者:姜江 error 131 的触发器。触发器可以是SQL Server自动执行业务处理的一种方式。例如:当一名作者的书已经 卖掉足够多已达到预付版税款对应的数量时,触发器可以用来自动开始计算版税报酬。触发器可 以在表中记录被成功地修改后才开始触发。如果因语法错误或违反约束导致修改失败,则触发器 不启动。处理触发器时,你要小心一点。尽管触发器功能很强大,但是常常会大大降低服务器的 效率。注意不要试图在触发器上放太多的功能,这样会减慢响应而使你的用户着急。 假设我们设计了一个功能复杂的触发器,那么该触发器最大的问题是导致触发器的运行要花 费大量时间。如果触发器有太多的功能,它将导致其他用户等待。一个用户在执行任何数据修改 后,都会引起触发器启动,触发器影响到的行将会被持有,直到触发器运行结束。例如:如果触 发器要花10秒钟运行,其他用户必须要在最初访问的用户运行后再过10秒,才能访问这些行。 3.2 SQL 语言简介 SQL 语言是数据库的基础,学习本书虽然不一定要求精通 SQL 语句,但为了更好的理解 PowerDesigner 在数据库建模中的应用,这部分将简单介绍结构化查询语言(SQL,Structured Query Language)。结构化查询语言是发给你问关系型数据库的标准语言,通常分为:  数据操作语言(DML,Data Manipulation Language):读取、增加、修改、删除数据库中 存储的数据  数据定义语言(DDL,Data Definition Language):生成 SQL 语言的特点 SQL 语言具有以下特点: 1. 一体化的特点: SQL 能完成定义关系模式、录入数据以建立数据库、查询、更新、 维护、数据库重构、数据 库安全控制等一系列操作要求另外,由于关系模型中实体以及实体间的联系均用关系来表示, 这 种数据结构的单一性带来了数据操纵符的统一性。因为信息仅仅 以一种方式表示,所以想完成的 每种操作(如插入,删除等)都只 需一种操作符,从而克服了非关系系统由于信息表示方式的多 样性带来的操作复杂性。 2. 两种使用方式,同一的语法结构: SQL 有两种使用方式。一种是联机交互使用的方式,另一种嵌入 某种高级程序设计语言的程 序中,以实现数据库操作。前一种方式下,SQL 语言为自含式语言,可独立使用。在两种不同的 使用方式下,SQL 语言的语法结构基本上是一致的。因此,具有极大的灵活性和方便性。 3. 高度非过程化 非关系的数据操纵语言是面向过程的语言,用其完成某项请求,必须指定存取路径。而在 SQL 语言中 ,只要求用户提出“干什么”,而无需指出“怎 么干”,因此用户不必了解存取路径的选 择,存取路径的选择和 SQL 语句操作的过程由系统自动完成。有利于提高数据的独立性。 4. 面向集合的操作方式; 5. 语言简洁,易学易用; 作者:姜江 error 132 3.2.1 SQL 语言的基本概念和使用 SQL 支持关系数据库三级模式结构。其中;  外模式:视图和部分基本表  模式:基本表  内模式:存储文件  视图:是从一个或几个基本表导出的表。是一个虚表。 基本表的定义和修改 一.定义基本表的格式为: CREATE TABLE <表名>(<列名> < 类型>[列约束条件] [,<列名>< 类型>[列约束条件]]„ [,<表约束条件>]); 二.修改基本表定义的语句格式为: ALTER TABLE <表名> [ADD <新列名> <类型>[约束条件]] [DROP <完整性约束名>] [MODIFY <列名><类型>]; 三.删除基本表的语句为: DROP TABLE <表名>; 把一个基本表的定义连同表上的所有记录、索引以及由此基本表导出的所有视图全部都删除, 并释放相应的存储空间。 四、建立索引的语句格式为: CREATE [UNIQUE] [CLUSTER] INDEX <索引名> ON <表名> (<列名>[<次序>][,列名[<次序>]]„ ); 五、删除索引的语句格式为: DROP INDEX <索引名>; 六、查询语句一般格式: SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>]... FROM <表名或视图名>[,<表名或视图名>]... [WHERE <条件表达式>] [GROUP BY <列名 1>[ HAVING <条件表达式>]] [ORDER BY <列名 2>[ASC|DESC]]; 整个语句的含义是: 根据 WHERE 子句中的条件表达式,从 FROM 子句指定的基本 表或视图中找出满足条件的元组, 再按 SELECT 子句中的目标列表达式,选出元组中的属性值形成结果表。如果有 GROUP 子句,则 将结果按<列名 1>的值分组,该属性列值相等的元组为一个组。通常会在每组中作用集函数。如 果 GROUP 子句带 HAVING 短语,则只有满足指定条件的组才予输出。如果有 ORDER 字句,则结果表 作者:姜江 error 133 还要按<列名 2>的值的升序或降序排序。查询举例: 例 1 查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名 SELECT Sname, ‘Year of Birth:’,1996-Sage, ISLOWER (Sdept) FROM Student; 例 2 查询考试成绩有不及格的学生学号 SELECT DISTINCT Sno FROM Student WHERE Grade<60; 例 3 查询以“DB_” 开头,且倒数第三个字符为 i 的课程的详细情况 SELECT * FROM Course WHERE Cname LIKE ‘DB\_%I__’ESCAPE’\’; 例 4 查询所有有成绩的学生学号和课程号 SELECT Sno,Cno FROM SC WHERE Grade IS NOT NULL; 例 5 查询选修了 3 号课程的学生的学号及其成绩,查询结果按分数的降序排列 SELECT Sno,Grade FROM SC WHERE Cno=‘3’ ORDER BY Grade DESC; 例 6 查询选修了 3 门以上课程的学生学号 SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*)>3; 例 7 SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student,SC WHERE Student.Sno=SC.Sno(*); SQL 更新语句: 一.修改(UPDATE) 一般格式为: UPDATE <表名> SET <列名>=<表达式>[,<列名>=<表达式>]··· [WHERE <条件>]; 二.删除(DELETE) 作者:姜江 error 134 一般格式为: DELETE FROM <表名> [WHERE <条件>]; 三.插入( INSERT) 一般格式为: INSERT INTO 表名[(字段名[,字段名]···)] VALUES (常量[,常量] ···); 或: INSERT INTO 表名[(字段名[,字段名]···)] 视图的定义: 建立视图的语句格式为: CREATE VIEW <视图名>[(<列名>[,<列名>]···)] AS <子查询> [WITH CHECK OPTION]; 删除视图的语句格式为: DROP VIEW <视图名>; SQL 数据控制功能 GRANT 语句的一般格式: GRANT <权限>[ ,<权限>] „ [ ON <对象类型><对象名> ] TO <用户>[,<用户> ]„ [ WITH GRANT OPTION]; REVOKE 语句的一般格式: REVOKE <权限>[,<权限>]... [ON <对象类型><对象名>] FROM <用户>[,<用户>]„ ; 3.3 PowerDesigner 中 PDM 相关概念 在使用 PowerDesigner 9.5 进行物理数据模型(PDM)建模之前,有必要先对以下几个概念进行 简单的介绍:业务规则、域和抽象数据类型。不过要在 PDM 中创建业务规则、域以及抽象数据类 型,必须先创建 PDM,关于如何创建 PDM,请参考:3.4 创建和操作 PDM。 3.3.1 业务规则(Business Rules) 在该部分中,将向大家介绍什么是业务规则,如何在 PDM 中定义业务规则,以及在 PDM 中如 何使用业务规则。 A.什么是业务规则(BusinessRules) 业务规则就是业务进行必须遵循的一些规则,它们可能是政府颁布的法律,可能是顾客的需求, 也可能是内部的工作规范。 业务规则往往是通过一些简单的观察得到的。例如:“客户可以拨打免费热线订购货物”。在设 计的过程中,就需要将这个过程更加详细的描述出来。比如说,客户订购货物的时候需要提供什 么样的信息,或者是根据客户的信用等级来判断客户能够订购多少货物。 作者:姜江 error 135 业务规则能够指导并且将模型的创建文档化。例如,“一个员工仅仅从属于一个部门”,这个规 则能够帮助你在图形中建立一个员工和一个部门之间的连接。 业务规则的好处就在于它以一种图形方式不易表达的方式补充图形模型所能够表达的信息。例 如,有些规则以公式和验证规则的方式来描述物理问题,这些技术表述方式通常不能够以图形的 方式显示出来。 在 PDM 中你可以在业务规则和具体的对象之间建立联系。如果你建立验证规则与列或者域(随 后介绍)之间的联系,你也可以把业务验证规则当作检查参数。 B.在 PDM 中定义业务规则(BusinessRules) 业务规则的定义如表 3-1 所示。 表 3-1 业务规则主要属性 属性 含义 最大长度 名称(Name) 规则的名称 254 代码(Code) 规则的引用名称 254 描述/备注 (Comment) 对规则的描述 — 类型(Type) 指明规则的类型:定义/事实/方程公式/需求/验证 — 其中业务规则的类型又包括以下几种,但是只有“验证规则”能够在生成数据库时导入到数 据库中,如表 3-2 所示。 表 3-2 业务规则类型、含义及示例 规则的类型 含义 例子 定义 (Definition) 信息系统中对象的特征或者属性 顾客就是能够通过姓名和地址 来识别的购买货物的人 事实(Fact) 信息系统中存在的或者真实的情况 每个客户可以一次或者多次订 购货物 方程公式 (Formula) 信息系统中使用的计算 总价格=sum(单价*数量) 需求 (Requirement) 信息系统中的功能性描述 模型所要达到的目标是:总损 失量不能超过总销售额的 10% 验证 (Validation) 某个值的约束。验证性业务规则可以生成到 数据库中 某客户各订单的总和不能超过 该客户的定量供应值 约束 (Constraint) 一个特定的值的额外的约束。可以给一个表 或者列分配多个约束业务规则。约束业务规 则也可以生成到数据库中。 项目的起始日期不能超过结束 日期 作者:姜江 error 136 在你定义 business rule 之前应该尝试着问自己以下问题,它们将有助于你建立业务规则:  你将解决什么样的业务问题?  我的系统中有必须遵循的过程吗?  我的项目有关于范围的说明书吗?  我的选择有限制吗?  我如何描述这些过程,说明,和约束吗?  我如何对这些描述分类:定义、事实、方程公式、验证规则? 在 PDM 中创建一个新的业务规则(business rule): 1.选择【Model】→【Business Rules】,将会弹出如图 3-1 所示窗口,这个窗口中将以列表 的形式显示模型中目前已经建立好的业务规则。 图 3-1 业务规则列表窗口 2.点击列表中的一个空白行 或者 点击窗口上方的第二个按钮 在该行中将会出现一个箭 头 3.输入 Name 和 Code,并且点击【Apply】按钮应用 4.双击该行左端,将会弹出业务规则属性的定义窗口 5.在 Type 的下拉列表中选择业务规则的类型 在属性窗口中还可以对业务规则的表达式(Expression)进行详细的定义,在你创建模型和 分析业务问题的时候,可以通过添加一些技术性的 Expression 将业务规则完整化。当然,针对不 同数据库的 expression 的语法也不尽相同。 每个业务规则包括两种类型的表达式(Expression): Server:可以被生成到数据库中 Client:这部分 Expression 主要适用于文档的生成。 但是对触发器或者存储过程你可以同时使用两种类型的表达式(Expression) 例如,再新创建一个业务规则 DateConstraint,它的类型为 Constraint,它的 Server 类型 的 Expression 为:BeginDate is null or EndDate is null or BeginDate <=EndDate。 在接下来的部分中,你将学会如何使用自己创建的业务规则。 C.在 PDM 中应用业务规则(BusinessRules) 1.双击模型中的一个对象(假设是表 Table1),弹出该对象的属性对话框 作者:姜江 error 137 2.点击 Rule 的那个属性页,在这里可以看到已经加载到该对象上的业务规则的列表 3.点击 ,在弹出的对话框中,你将看到模型中现在已经定义好的所有的业务规则。如图 3-2 所示。 图 3-2 为对象选择业务规则 4.选择刚才创建的业务规则 DateConstraint,点击【确定】 5.在对象的属性对话框中点击【Apply】按钮应用 6.然后点击 Preview 属性页,可以看到,我们创建好并被应用的业务规则已经被生成了脚本。 如图 3-3 所示。 图 3-3 在 Preview 属性页中查看业务规则产生的代码 值得注意的是,这种约束型的业务规则不能够在多个对象之间复用,因此,就必须创建足够 多需要的约束业务规则。 3.3.2 域(Domains) A.什么是域(Domains) 域能够帮助你确定模型中信息的类型。使用域将使得在不同表中对列的数据特点标准化的工 作非常容易。读者可以把域(Domains)理解为用户自定义的数据类型。在接下来的部分中,读者 作者:姜江 error 138 将逐步学习如何使用域为建模提供方便。 B.在 PDM 中定义域(Domains) 域的定义如表 3-3 所示。 表 3-3 域的主要属性及其含义 属性 含义 最大长度 名称(Name) 域的名称 254 代码(Code) 域的引用名称 254 描述/备注(Comment) 对规则的描述 — 所有者(Owner) 表的所有者,可以从用户列表中选择,一个表只能有 一个所有者,通常为表的创建者 254 数据类型(Data Type) 域对应的数据的形式,比如说,数字型,文字数字型, 布尔型,或者其它的 — 长度(Length) 字符串的最大长度 — 精度(Precision) 小数点后的位数,用于带小数点的数据类型 — 是否强制(Mandatory) 所有使用这个域的列是否一定强制性的采用域的值 — 标志(Identity) 在 MS SQL Server 2000 以及 Adaptive Server Enterprise 等 DBMS 中,表示使用本域的字段的值自 动增加 — 有默认值(With Default) 在支持该特性的 DBMS 中,如果插入的是 Null(空) 值,那么系统会自动给使用该域的列分配一个默认值 — 摘要文件(Profile) 该域所对应的测试摘要文件 — 标 准 检 查 ( Standard Checks) 域的检查参数 附加检查(Additional Checks) 在域的检查参数没有定义的域约束,验证规则 规则(Rules) 对域指定的业务规则 在 PDM 中创建一个新的业务规则(business rule): 1. 选择【Model】→【Domains】,将会弹出域列表窗口(和业务规则窗口相似),这个窗口中将 以列表的形式显示模型中目前已经建立好的业务规则 2. 点击列表中的一个空白行 或者点击窗口上方的第二个按钮 在该行将会出现一个箭头 3. 输入 Name 和 Code,并且点击【Apply】按钮应用 4. 双击该行左端,将会弹出域属性的定义窗口 5. 在 Data Type 的下拉列表中选择域的类型。如果需要,同时规定长度和精度。 注:如果你不想马上为域选择数据类型,你可以选择的数据类型。当你生成数据 作者:姜江 error 139 库时,该数据类型会自动的分配为 DBMS 的默认数据类型。 除了在 Data Type 下拉列表中选择数据类型以外,还可以点击 Data Type 旁边的 从标准 数据类型的列表中选择域的数据类型,如图 3-4 所示。 图 3-4 查看标准数据类型 下面的几个表格将向你介绍各种标准数据类型: 表 3-4 数字型数据类型 数据类型 内容 长度 是否要规定精度 Integer 32 位 整数 — — Short Integer 16 位 整数 — — Long Integer 32 位 整数 — — Byte 256 个值 — — Number 为数固定的带小数点的数字 固定 Decimal 位数固定的带小数点的数字 固定 Float 32 位 浮点型数字 固定 — Short Float 少于 32 位 Decimal — — Long Float 64 位 浮点型数字 — — Money 位数固定的带小数点的数字 固定 Serial 自动增加的数字 固定 — Boolean 两个相反的值(0/1;true/false;yes /no) — — 表 3-5 字符型数据类型 数据类型 内容 长度 Characters 字符串 固定 作者:姜江 error 140 Variable Characters 字符串 Maximum Long Characters 字符串 Maximum Long Var Characters 字符串 Maximum Text 字符串 Maximum Multibyte 多字节字符串 固定 Variable Multibyte 多字节字符串 Maximum 表 3-6 时间类型的数据 数据类型 内容 Date 月,日,年 Time 小时,分钟,秒 Date & Time 日期和时间(Date 和 Time) Timestamp 系统日期和时间 表 3-7 其它数据类型 数据类型 内容 长度 Binary 二进制字符串 Maximum Long Binary 二进制字符串 Maximum Bitmap BMP 格式的图像文件 Maximum Image 图像文件 Maximum OLE OLE 连接 Maximum Other 用户定义的数据类型 — Undefined 未定义数据类型 — 6.此外,还可以进一步定义域,以 Standard Check 属性页为例,如图 3-5 所示。 图 3-5 在“Standard Checks”页中定义域的参数 作者:姜江 error 141 在这里可以定义 Domain 的数值范围,以及值的列表等属性,然后,可以通过 Preview 属性页 查看代码的变化(这里以 SQL Server 2000 为例,Domain 的 code 为 Currency,数据类型为 money): ====================================================================== if exists(select 1 from systypes where name='Currency') sp_unbindrule Currency go if exists(select 1 from systypes where name='Currency') begin execute sp_droptype Currency drop default D_Currency end go if exists (select 1 from sysobjects where id=object_id('R_Currency') and type='R') drop rule R_Currency go create rule R_Currency as @column is null or (@column between 100 and 10000 and @column in (100,200,300,400,500,600,700) ) go /*==============================================================*/ /* Domain: Currency */ /*==============================================================*/ execute sp_addtype Currency, 'money' go create default D_Currency as 50 go sp_bindefault D_Currency, Currency go execute sp_bindrule R_Currency, Currency go ====================================================================== 通过研究这段代码,发现 Domain(域)和 MS SQL Server 2000 中的“用户定义的数据类型” 的概念是基本一致的,此外,对于域的 Standard Check 的定义和默认值最终在 MS SQL Server 2000 中体现为“规则”(Rule)和“默认值”( Default)。 关于域的应用、产生的问题,以及解决方法, 作者:姜江 error 142 请参考:第 7 章 高级应用&网友常见疑难解答(FAQ)7.10 问题十。 C.在 PDM 中使用域(Domains) 1.双击模型中的一个表,弹出对话框,进入 Columns 属性页 2.点击该窗口右上方的【Customize Columns and Filter】按钮 ,或则通过快捷键【Ctrl +U】,即可调出窗口“【Customize Columns and Filter】” 3.选中 Domain 的复选框后确定,此时,便可在 Columns 属性页中看到有一列 Domain 出现 4.在 Domain 下拉列表中选择刚才定义的域 Currency,将会发现该列的 Data Type 自动变为 money 注 1:对 Column 应用 Domain 还可以直接双击该列,在 General 属性页中的下放 Domain 下拉 框中选择已经定义好的 Domain。点击旁边的 可以查看 Domain 列表。 注 2:假设现在改变该列的数据类型为 int,然后点击【确定】,就会弹出警告窗口,如图 3-6 所示。 图 3-6 列数据类型和域的数据类型不一致确认窗口 PowerDesigner 会提示是和域中定义的数据类型保持一致或者是 diverge(不一致),如果点 击【确定】按钮,可以改变数据类型。 可以通过选择【Tools】→【Model Options】,在弹出的窗口中选中手所指的复选框(Enforce non-divergence),即可强制使用 domain 的字段的数据类型不可以改变,如图 3-7 所示。 图 3-7 在模型属性窗口中强制数据类型一致 作者:姜江 error 143 之后,当我们再次对表中的列进行操作的时候就会发现,使用了 Domain 的列的数据类型会自 动和 Domain 保持一致,并且灰化不可以修改。 D.修改域(Domains)的属性 选择【Model】→【Domains】,双击需要修改的域,修改某个域(假定修改 currency 的数据 类型为 int), 点击【确定】按钮。如果已经有某些表的列使用了这个 Domain,会弹出如图 3-8 所示窗口: 图 3-8 更改域属性的确认窗口 该窗口向你提示 Data Type/Check/Rules/Mandatory/Profile 中有哪些已经使用了该 Domain,复选框选中的表示使用了该 Domain,在这里你可以选择你要更新哪些使用该 Domain 的 模型元素,然后点击【确定】按钮,PowerDesigner 会自动更新相关的元素,这里会自动更新所 有使用该 Domain 的数据类型为 int 型。 如果在 PowerDesigner 菜单【Tools】→【Model Options】中选中 Enforce non-divergence, 就会发现这个窗口的 Data Type 的复选框为灰化不可以修改。这表明,只要 Domain 发生改变,数 据类型会强制自动改变。如果在 Model Options 的对话框中也选中了 Enforce non-divergence 下的 Check/Rules/Mandatory/Profile 中的任何一个复选框,那么,在域的更新对话框中对应 元素的复选框就是灰化的。 3.3.3 抽象数据类型(AbstractDataTypes) 抽象数据类型 Abstract data type(ADT)是一类有用户自定义的能够封装一些列数据和功 能函数的数据类型。这些功能函数不仅能够定义还可以操作一些列值。 例如:罗马教皇的日历包含下列定义的功能:  能读和写罗马数字  将 Julian(朱利安)日历转化为罗马教皇的日历  将罗马教皇的日历转化为 Julian(朱利安)日历 PowerDesigner 中使用的抽象数据类型,随着 DBMS 的不同而不同,主要包括下列几组 ADT, 如表 3-8 所示。 表 3-8 不同类型的抽象数据 作者:姜江 error 144 类型 描述 例子 Array 固定数量的元素的集合 VARRAY(Oracle8 或者更高的版本) List 不固定数目的对象的集合 TABLE(Oracle 或者更高的版本) Java Java 类 JAVA(Adaptive Sever Anywhere 以及 Adaptive Sever Enterprise) Object 包含一些列的属性 Object(Oracle8 或者更高的版本) Structured 包含一些列的属性 NAMED ROW TYPE(Informix9.x 和 IBMDB2 5.5) A.如何在 PowerDesigner 中使用 abstract data types: 可以在 PowerDesigner 中创建 DBMS 支持的抽象数据类型,另外抽象数据类型也可以被反向工 程到当前 PDM 中。可以在 Abstract Data Types 列表中创建 ADT,如果反向工程包含 ADT 的数据 库,那么生成的 ADT 也可以在 Abstract Data Types 列表中找到。 在 PDM 中不可以创建 Java 类。可以在 Abstract Data Types 列表中规定 Java 类的 name 和 code,然后在 PowerDesigner 的面向对象模型(OOM)中将之与 Java 类连接,而且 OOM 必须处于 打开状态。抽象数据类型连接到 Java 类上就可以访问它的属性。 可以将包含 Java 类的数据库反向工程到 PDM 中。如果要访问这些 Java 类的属性,则必须反 向工程到 OOM 中。PDM 中使用 Java 类作为数据类型的字段或者 domain 就会被自动连接到 OOM 中 相应的 Java 类上。 B.创建抽象数据类型: 有些 DBMS(包括 SQL Server 2000)不支持 ADT,如果我们的 DBMS 为 SQL Server 2000 则在 Model 菜单下看不到这个菜单。因此,我们把 DBMS 切换为 Oracle version 9i,选择【Model】→ 【Change Current Database】,在弹出的窗口中选择自己需要的 DBMS-Oracle version 9i,点 击【确定】按钮)。创建并使用 ADT 的步骤如下: 1. 选择【Model】→【Abstract Data Types】弹出 ADT 列表窗口 2. 点击列表中的一个空白行 或者点击窗口上方的第二个按钮 在该行中将会出现一个 箭头,输入 Name 为“地址”,Code 为“Address”,并且点击【Apply】按钮应用 3. 双击该行或者选中该行后点击属性工具 ,弹出 ADT 属性窗口 4. 在 General 属性页的 Type 下拉列表中选择 ADT 的类型为 Object,在 Attribute 属性也中 分别添加三个属性,点击【确定】按钮。如图 3-9 所示。 作者:姜江 error 145 图 3-9 为表添加属性 可以发现 Oracle9i 支持 OBJECT、TABLE、VARRAY,选择不同的类型,相关的属性输 入框也会显示出来,假定选择 VARRAY,则显示 Data Type、Size、Length、Precision; 如果选择了 OBJECT,则会出现相应的 Attribute 属性页,可以添加一个或者多个属性, 包括属性的 name、code、数据类型等。 5. 双击图形模型中的表“学生”,进入 column 属性页,电解“住址”列的 Data type 处的 下拉列表,选择我们刚刚建立的抽象数据类型“Address”。至此,抽象数据的创建和使 用就已尽完成。 C.连接抽象数据类型到 Java 类上 在 PDM 中,可以指定一个 Java 类,然后和 OOM 中的 Java 类连接起来,其中,需要连接的这 个 OOM 必须在当前 Workspace 处于打开状态。当 Java 类和抽象数据类型连接时,PowerDesigner 会自动创建一个快捷方式,以便存取 Java 类的属性。 创建连接的步骤如下: 1. 选择【Model】→【Abstract Data Types】,打开抽象数据类型的列表窗口 2. 点击一个空白行,为 Java 类创建一个抽象数据类型,该行行首出现一个箭头 3. 双击行首箭头,或者选择该行后,点击属性工具 ,弹出抽象数据类型属性窗口,如图 3-10 所示。 作者:姜江 error 146 图 3-10 抽象数据类型属性窗口 4. 在弹出的窗口中指定 ADT 的 name 的 code 等属性,并且在 Type 下拉框中选择 Java 作为 ADT 的类型 有的读者可能会很奇怪,为什么它建立 ADT 不能选择 Java,甚至在 Model 菜单中没有 Abstract Data Type 菜单,这是因为读者没有选择合适的 DBMS,首先不是所有的 DBMS 都支 持 ADT(参考表 3-8),因此,如果读者的 DBMS 是 SQL Server 2000 就自然没有这个菜单项, 同理,支持 Java 作为 ADT 类型的只有 Sybase 的 Adaptive SQL Anywhere。所以,必须切换 DBMS。 5. 点击 Class 框后面的省略号按钮,弹出一个 Java 列表窗口,该窗口列出了当前 Workspace 中 打开的 OOM 中的 Java 类,选择一个 Java 类,点击【确定】按钮,抽象数据类型就和 Java 类 建立了连接。弹出的选择窗口如图 3-11 所示。 图 3-11 选择 Java 类 注意:如果当前 Workspace 中没有打开的 OOM,则弹出的窗口中内容为空白。 6. 点击 Class 框后面的 Properties 工具 ,弹出了目标 Java 类的属性窗口,但该 Java 类作 为一种快捷方式,点击该窗口中各对象后面的属性工具按钮 ,弹出这些对象的属性窗口, 可以进行修改和查看。如图 3-12 所示。 作者:姜江 error 147 图 3-12 查看 Java 类快捷方式属性窗口 7. 如果需要改变目标类,仅需点击该窗口中的【Change Target Object】按钮,在弹出的选择 窗口中选择合适的目标 Java 类,点击【确定】按钮即可。 8. 点击该窗口中的【确定】按钮。 反向工程后自动连接到 Java 类 在反向工程包含 Java 类的数据库到 PDM 时,Java 类被逆向工程为 Java 类型的抽象数据类型, 同时,该 PDM 的 Java 类型的抽象数据类型会被自动连接到 OOM 中的 Java 类上。实现的步骤大致 如下:  将数据库中的 Java 类(通常用作列和域的抽象数据类型)逆向工程到 OOM 中  将数据库逆向工程到 PDM 中  PowerDesigner 会自动搜索打开和 OOM 中的 Java 类和 PDM 中的 Java 抽象数据类型,建 立相应的连接 3.4 创建和操作 PDM 3.4.1 创建和操作 PDM 模型 A.创建 PDM 模型 如果读者要创建一个自己的物理数据模型(PDM),那么: 1.选择【File】→【New】或者点击工具栏中的【新建】按钮,在弹出的对话框中选择 Physical Data Model,点击【确定】按钮 2.如 图 3-13 图所示,在 DBMS 的下拉列表中选择 Microsoft SQL Server 2000,在 First Diagram 的下拉列表中选择 Physical Diagram,然后点击【确定】按钮,这样,我们自己的物理数据模型 就建立起来了。我们还可以在 workspace 中通过右键点击模型,对模型进行重命名。 作者:姜江 error 148 图 3-13 新建 PDM 模型 3.点击 Extended Model Definitions 可以为模型选择扩展模型定义,关于扩展模型定义,请参 考:3.15.5 使用扩展属性,如图 3-14 所示。 图 3-14 为 PDM 模型选择扩展模型定义 4.创建好 PDM 之后,可以选择【Model】→【Model Properties】,或者在图形模型的空白处 右键鼠标,在弹出的菜单中选择 Properties,弹出模型属性窗口,如图 3-15 所示。 图 3-15 “Model Properties”窗口 5.在该窗口中输入模型的 Name、code、Comment、Author 以及 Version 等属性,可以在 Preview 属性页中预览模型的生成脚本。 B.PDM 和 Workspace 作者:姜江 error 149 前面提到过,对模型的操作必须在 Workspace(工作空间)中进行,因此可以将模型加入到 Workspace 中,或者从 Workspace 分离出来。 Palette 面板是当前用户建模可以使用的模型元素,各图标含义如表 3-9 所示。 表 3-9 PDM 中 Palette 面板的各工具含义 工具 名称 用途 鼠标/Pointer 选择图形 套索/Lasso 选择某个范围内的图形 抓取器/Grabber 选择并移动所有的图符 放大/Zoom In 放大图形 缩小/Zoom Out 缩小图形 打开包的图形/Open Package Diagram 显示某个包的图形 属性/Properties 显示某个图符的属性 删除/Delete 删除图符 包/Package 插入一个包的图符 表/Table 插入一个表的图符 视图/View 插入一个视图的图符 引用/Reference 插入引用的图符 文件/File 插入一个文本文件 注解/Note 插入一个注解的图符 连接/扩展依赖(Link / ExtentedDependency) 1.在模型的图符之间建立连接 2.在对 象和 note 之间建立连接 3.在两个支持 扩展依赖的对象之间建立扩展依赖 标题/Title 插入一个标题 文本/Text 插入一段文本 直线/Line 画一条直线 弧线/Arc 画一条曲线 长方形/Rectangle 画一个长方形 椭圆/Ellipse 画一个椭圆 圆角矩形/Rounded rectangle 画一个圆角矩形 多折角线/Polyline 画一个多折角线 多边形/Polygon 画一个多角形 将模型加入到 Workspace: 要将一个模型加入到某个 Workspace,只需要在该 Workspace 中打开模型,然后选择【File】 →【Save workspace】或者【Save workspace as】保存 Workspace,下次打开工作空间的时候,该 作者:姜江 error 150 模型就会列在 Workspace 的目录下。 将某个模型从 Workspace 中分离的步骤如下: 1. 在左侧的 Workspace 浏览树中,右键鼠标,在弹出的菜单中选择 Detach from Workspace 2. 如果模型被修改过,则弹出确认窗口,询问是否要保存该 PDM 3. 如果希望保存对该 PDM 的修改,点击“是(Y)”保存 这样,就将 PDM 成功的从当前 Workspace 中分离,也可以在弹出的右键菜单中选择关闭模型 或者保存模型。右键菜单中还包括检查模型、合并模型以及同 Repository 配合使用等功能,这些 内容将在后面的章节中陆续介绍。 切换 PDM 的 DBMS 建立好 DBMS 之后,如果想改变模型的目标 DBMS,只需要选择【Model】→【 Change Current DBMS】,在弹出的窗口中选择合适的 DBMS,点击【确定】按钮。 存档 PDM 文件: 存档 PDM 模型可以可保存模型中所有的约束的名称(name),而不会区分用户定义的和计算 约束(calculated constraint)的区别。而标准的模型(*.pdm)有可能丢失约束名称。这些存档模 型还可以用于修改数据库的功能(Modify database feature),请参考:3.8.3 比较、同步模型和数 据库、通过模型修改数据库。 可以使用以下方式将 PDM 存档为后缀名为 APM 的文件:  将 PDM 模型另存为存档模型 选择【File】→【Save As】,在类型下拉列表中选择 Archived PDM(bin)( *.apm;*.mpa) 或者 Archived PDM(xml)( *.apm;*.mpa),然后点击【保存】。  在生成数据库后自动存档 PDM 模型 选择【Database】→【 Generate Database】,点击 Options 属性页,在 After Generation groupbox 中选择 Automatic Archive 复选框,点击【确定】按钮。生成数据库后,会自动弹出窗口,提 示用户输入保存路径和文件名,然后点击【保存】。 3.4.2 创建表 A.创建基本的表 从这部分开始读者将开始学习如何在 PowerDesigner 9.5 中创建表,并且进行相关操作。以 一个项目为例,学会如何创建一个新表,在表中创建列,定义主键,创建域,将列和域对应起来, 创建索引等对表的常用操作。 项目背景:该项目为某学校学生信息管理系统,需要实现的功能包括管理学生的个人信息和 管理学生的相关考试成绩等。 下面开始学习如何添加一个新的表,并对其进行定义: 1.点击 Palette 面板的【Table】工具 2.在右边的空白区域点击鼠标左键,一个表的图符会出现在鼠标点击的位置上,并且自动命 作者:姜江 error 151 名为 Table_1。新建表的时候,PowerDesigner 会自动将表命名为 Table_n,这里的 n 代表当 前表为该模型中的第 n 个表 3.点击 Palette 面板的【Pointer】工具(或者点击右键,即可使当前工具变为 Pointer) 4.双击这个表的图符弹出表的属性的窗口,如图 3-16 所示。 图 3-16 表属性窗口“Table Properties” 在 Name 和 Code 输入框中分别输入表名称和生成代码时的代码名称。 在该属性页中各选项的含义参考表 3-10。 表 3-10 表“General”属性页各属性含义 属性 含义 最大长度 Name 表的名称,使用该名称有助于使得模型容易理解 254 Code 表引用的代码,数据库的脚本生成将使用这个代码 254 Comment 对表的描述备注 - Owner 表的所有者,可以从用户列表中选择,一个表一般只能有一个所 有者,通常为表的创建者 254 Number 对物理数据库中表的记录的大概估计,该数字用于估计数据库的 大小规模 - Generate 指明是否在数据库中生成该表 - Type 表的类型,可以是纬度表或者事实表(参考数据仓库) - 接下来,我们开始对该表的添加列。点击 Column 属性页,点击列表空白处或者 或者 , 建立需要的列,如图 3-17 所示。 作者:姜江 error 152 图 3-17 在“Columns”页中为表添加列 输入列的 Name,Code,在 Data Type 中选择该列的数据类型。 其中,I 表示 Identity,在 SQL Server 2000 中表示自动增加的列,这里没有选择;P 表示 Primary key 主键;M 表示 Mandatory,用以表示是否必须,是否可以为空;F 表示 Foreign key 外键 也许有的读者会发现自己的窗口中没有 I 这个选项,不必着急,你可以点击该窗口右上方的 【Customize Columns and Filter】 按钮,或则通过快捷键【Ctrl+U】,即可弹出窗口,如 图 3-18 所示。 图 3-18 定义要在属性窗口中显示的项目类型 在该窗口中,你可以选择你需要的对列进行全面定制的各个选项,其中自然包括 Identity, 我们还可以通过 Preview 属性页预览生成的代码。 B.候选键(Alternate key) 候选键有一个或者多个列组成,它可以唯一确定表中的行,但却不是主键。候选键可以是一 作者:姜江 error 153 个外键。每个候选键能够在目标 DBMS 中生成一个唯一索引或者一个唯一性约束。 例如:表“学生”的主键是“学号”,但是列“身份证号”也可以唯一确定一行,因此可以定 义该列为 Alternate key。 创建候选键的步骤如下: 1. 在“学生”表中增加一个列“身份证号”(code 为 idCard,数据类型为 varchar(20); 2. 双击图形模型中的表,弹出表的属性窗口 3. 进入 Keys 属性页,该属性页中列出表中已经定义的键 4. 点击列表中的空白行,或者点击 或者 ,在该行左端出现一个箭头只想该行 5. 输入 name 和 code 分别为 AK1_idCard()。候选键的习惯命名方法为:AK 后面加键的次序 “_”再加列的 code。注意:这里和索引的命名方式为 ColumnName_AK 6. 点击【Apply】按钮应用。 7. 双击该行或者选中该行后点击属性工具 ,弹出候选键属性窗口 8. 在该属性窗口中进入 Columns 属性页,点击 添加列,在弹出的列的列表窗口选择列“身 份证号”,确定。 可以发现在图形模型中,“身份证号”这列的末端出现了“”,表明该行为候选键。 C.对列的详细定义 创建好列之后我们可以进一步对列的属性进行定义,双击 Columns 属性页中需要进一步定义 的列所在的行,或者选择某列然后点击属性工具 ,弹出列的属性窗口。 在 General 属性页中,可以修改列的 name、code、数据类型以及域等属性,其中复选框 Display 表示该列是否在图形模型中显示,还可以在该属性页中为列加入备注。 进入 Standard Checks 属性页,可以为列定义标准约束,如果是数字类型值则可以定义最大 值(Maximum)和最小值(Minimum)以及默认值(Default)。如果列的值必须是某些特定的值, 则可以在 List of values 中添加值的列表(本例中添加了字段“年龄”的列表)。如果列为字符 型数据,还可以规定是否将所有字符转化为大写小,是否不可修改等属性。如图 3-19 所示。 作者:姜江 error 154 图 3-19 在“Standard Checks”页中定义列的检查约束属性 在属性页 Additional Checks 中,可以进一步使用 Rules 定制约束,修改列的约束的名称,修 改后,名称框后的 User-Defined 按钮自动按下,如图: ,表明已经过用户定义。 如果我们在 General 属性页中选择复选框“Computed”,则表明该列的值是通过其他列的值通 过一定的计算而产生,因此,可以在 Detail 属性页中的 Computed expression 编辑框中键入相应 的计算表达式(例如:销售额的计算表达式为:sale.salNum*sale.price),或者点击【Edit】工具 ,弹出 SQL Editor 编辑窗口,在 SQL Editor 编辑窗口中可以使用该表的列,并且使用已经预 定于的各种函数和算子(),如图 3-20 所示。 图 3-20 在“SQL Editor”窗口中编辑计算列表达式 关于 Detail 属性页中其它部分的含义,请参考:3.7.1 创建测试数据摘要文件,Rules 属性页 的使用,请参考: 3.3.1 业务规则(Business Rules),如果模型中包含了扩展属性的定义,则列的 属性窗口中还会包含 Extended Attributes 属性页,请参考:3.15.5 使用扩展属性,扩展属性的 应用,以及如何为列创建序列(Sequence)或者标识(Identity)请参考:第 7 章 高级应用&网友常 见疑难解答(FAQ)(7.6 问题六) D.表的物理选项 作者:姜江 error 155 关于物理选项的含义,请参考:3.15.6 定制和使用物理选项。 表的物理选项的定制方法如下: 1. 双击图形模型中的表,打开表的属性窗口 2. 进入 Options 属性页 3. 在左侧 Syntax 页中选择需要定义的项,点击【Add selected item】工具 4. 在右侧下方的编辑框中设置默认值 如果模型中已经定义了 Storage,那么也可以点击编辑框右侧的 ,弹出 Storages 列表,亦 可选择【Model】→【Storages】,定义模型中的物理存储选项,定义好的 Storages 都会出现 在这里的编辑框的下拉列表中 ,如图 3-21 所示。 图 3-21 在“Options”页中定义表的物理选项 这时,可以点击右侧窗口的 SQL 页面,有代码:on "PRIMARY"产生。 5. 如果要将该定义应用于模型中的其他表,点击该窗口左下角的“Apply to...”按钮,在弹出 的选择窗口中选择需要应用该物理选项的表格,点击【确定】按钮。如图 3-21 所示。 图 3-22 将物理选项应用到模型的其他表上 作者:姜江 error 156 例如,我们对前面创建的模型中的表“学生”应用这个物理选项,生成的代码如下: ========================================== create table 学生 ( 学号 int not null, 姓名 varchar(20) not null, 性别 smallint not null, 电子邮件 varchar(50) null, 手机 char(11) null, 住址 varchar(50) null, 年龄 smallint null default 25 备注 varchar(50) null, constraint PK_STUDENT primary key (studentID) ) on "PRIMARY" ========================================== 其他对象的物理属性的定义也可以参考这里表的物理属性的定义方法。请参考:3.15.6 定制和 使用物理选项。 3.4.3 对列的操作的常见问题及其解答 这部分中,主要介绍一些操作列时经常遇到的问题,以及解决方案。 A.重复输入 现在假设还要建立一个关于教师的表,我们发现,除了“学号”这个字段需要改为“教师编 号”以外,我们不得不在“教师”这个表中重复输入“姓名”,“年龄”„„等字段,在假设我们 还不得不建立一个“管理人员”的表,我们还要重复的输入这些字段,以及重新定义他们的类型, 在现实的数据库建模中,我们发现这是一项乏味为无趣并且容易出错的工作,但是有什么办法呢, 我们还得老老实实的挥动我们双手敲打一边又一遍敲打。 接下来,将向你介绍 PowerDesigner 一个极具人性化的功能,它将解决我们上述的那个问题。 假设我们建立一个“教师”表,添加我们需要的列:教师编号,并定义为主键,然后在 Columns 属性页中点击【Add Columns】,弹出窗口:如图 3-23 所示。 作者:姜江 error 157 图 3-23 为表添加其他表中的列 我们可以通过点击【Select All】 或者点击【Deselect All】 进行快速选择,如图 所示,然后点击【确定】按钮,我们惊奇的发现,这些相关的列的 Name,Code 以及字段类型统统 出现在“教师”这个表中。在笔者曾负责的一个项目中,通过该方法建立类似的 20 张表,至少为 笔者节省出来看半部 DVD 的时间。 紧接着,可能又会有一个相关的问题出现,就是当着若干个表的某个字段的名称或者类型都 需要改变,例如“电子邮件”这个字段需要改为“伊妹儿”(也许不太合理,但我们假设客户就喜 欢这么称呼,为了方便双方沟通,要求我们一定要改),是不是我们要点开一张张表重新进行定义, 或者重新进行选择?这显然也不是一种好的方法。于是我们可能又要在这个无聊的工作上花费很 多时间。 B.重复修改 前面的问题既然出现了,就该解决。既然这种情况经常有可能发生,那么我们就应该学会如 何预防,建模本身的目的之一就是能够重构,最大可能的减少重复劳动。我们还是假设我们需要 建立一张“教师”的表,和刚才不同的是,我们选择的不是 Add Columns ,而是 Replicate Columns ,这时候,我们只需要按前面的方法操作一遍即可,然后点击【确定】按钮。然后你 就会发现复制过去的 column 是灰化的,并且不能修改。 然后,通过修改“学生”这张表的“电子邮件”为“伊妹儿”,我们就会发现“教师”中的这 个字段也发生了相应的改变。这很像 windows 中的“快捷方式”,不同的是,这里不允许修改快捷 方式。通过这种方法,PowerDesigner 为我们提供了最大可能的方便。还是那个项目,笔者又在 20 张表中节省出来上一会 QQ 的时间。 C.为什么 Code 总是随着 name 变化 使用 PowerDesigner 的用户经常会遇到一个问题,就是在定义列的时候,列的 code 总是随着 name 的改变而改变。一般而言,我们总是把 name 定义为中文或者英文全称,而 code 则往往是英 文,甚至英文缩写。当我们需要修改 name 的时候,code 总是相应的和 name 一模一样,于是就不 作者:姜江 error 158 得不再次输入一边 code。 解决方案:选择【Tools】→【General Options】,如图 3-24 所示。 图 3-24 取消 Name 和 Code 之间的自动映射关系 只需要把该 checkbox 的钩去掉即可。 D.如何在模型中不显示 name,而显示 code 有时候,建模人员为了方便,可能更希望看到的是 code 而不是 name,但是,PowerDesigner 默认显示的是 name 解决方案:选择【Tools】→【Model Options】,如图 3-25 所示。 图 3-25 通过修改模型属性在图形中显示对象的 Code 只需要在这里将 name 改为选择 code 即可。 作者:姜江 error 159 E.如何改变默认数据类型 默认的情况下,数据类型都没有定义,都为,这样我们就不得不对所有的字段都 选择数据类型,并且进行相关长度的定义。假设系统中有很多的字段数据类型是 int 型的或者是 archer(20),那么,我们可以通过修改默认字段类型显著地减少数据库建模的工作量。 解决方案:选择【Tools】→【Model Options】,如图 3-25 所示,在左侧的 Category 中选择 Model,然后在窗口右方的左下角有下拉列表 Default Data Type,在这里选择或者定义你最常用 的字段类型,就可以为你省去很多敲键盘或者点击鼠标的工作。 3.4.4 定义外键/引用(ForeignKey/Reference) Reference(引用)是父表(parent table)和子表(child table)之间的连接。它定义了 数据库的引用完整性。当两个表中的列通过一个 reference 连接起来时,子表中的每个值必须指 向父表对应的列中一个相同的值。 现在,在我们的模型中开始创建外键/引用,操作如下: 1.新建表“班级”,如图 3-26 所示。 图 3-26 新建表实例 2.选择 Palette 面板中的 Reference 工具 3.点击子表“学生信息”,不要松开鼠标,然后移动至父表“班级”上,松开鼠标,此时表“学 生信息”如图 3-27 所示。 图 3-27 建立 Reference 后的表“学生信息” 这时候,我们发现“学生信息”表中会自动增加一个列“班级编号”,并且定义为(Foreign Key),表示为外键 注:(Primary Key),表示为主键 通常情况下,我们使用和定义外键都是现在子表中建立相应的和父表主键名称相同的列,然 后用 Reference 工具与父表连接,PowerDesigner 会在子表中自动查找到和父表主健名称相同的 列,建立连接。 4.双击两张表之间的连线(Reference)会弹出 reference 的属性窗口,可以在 General 属 性页中定义 reference 的 name 和 code 等属性 作者:姜江 error 160 5.在 Joins 属性页中可以对 reference 进行进一步的规定,如表 3-11 所示。 表 3-11 “Joins”属性页各按钮的功能描述 按钮 名称 功能描述 Reuse Columns 在子表复用现有的列(使用与父表中的列相同的 code) Migrate Columns 将键列移植到外键中,如果列不存在则自动创建 Cancel Migration 在子表中删除与父表形成外键对应的列 Join(连接)是在引用中定义的在父表列和子表列之间的一个连接。Join 可以用于连接主键或 者候选键和外键,或者是用户定义的独立于键的父表和子表之间的规定的列的连接。在 Model Options 窗口中的选择将决定 Join 的创建,如表 3-12 所示。 表 3-12 Join 创建的方式 Default Link on Creation Auto-migrate Columns 结果 Primary Key 选中 主键和外键之间创建了连接 未选中 创建了连向主键列的连接,但不完整,外键需要 手动指定 User-defined 选中 没有创建连接,需要手动指定父表和子表中的列 未选中 没有创建连接,需要手动指定父表和子表中的列 在 Joins 属性页的下方,可以在 ChildTable 列选择与父表主键相对应的外键的列,如图 3-28 所示。 图 3-28 引用属性窗口的“Joins”页 作者:姜江 error 161 6.定义引用完整性 引用完整性(Reference integrity)是管理主键、候选键和外键之间数据一致性的一系列规 则。引用完整性规定了当父表中被引用的列被更新或者删除时,将会如何影响子表。可以以两种 方式实现引用完整性:  Declarative,引用完整性通过引用来定义。当引用生成到目标 DBMS 中时,该引用完整 性评估引用的正确性并生成相应的错误信息。  Trigger,通过基于完整性约束的触发器实现。触发器将衡量引用的正确性并生成相应的 错误信息。 注意:不是所有的 DBMS 都支持使用引用完整性作为生成数据库的选项,对于这些类型的 DBMS, 生成的 SQL 脚本中不包含引用完整性的定义。 修改引用完整性的属性请进入 Integrity 属性页,如图 3-29 所示。 图 3-29 “Refernence Properties”窗口的“Integrity”页 其中各个属性的含义如表 3-13 所示。 表 3-13 “ Integrity”页个属性及其含义 属性 含义描述 Constraint name 引用完整性的约束名称,最大长度为 254 个字符 Implementation 指定通过触发器实现或者 Declarative 方式实现 Cardinality 基数,表示父表中每个实例对应于子表中实例的最大数目和最小数目 User-defined 表明是否是用户定义的约束名 Update constraint 修改父表中的列之后,子表的外键列以何种方式受到影响 Delete constraint 删除父表中的列之后,子表的外键列以何种方式受到影响 作者:姜江 error 162 Mandatory parent 每个子表种外键的值必须与附表中键的值相对应 Change parent allowed 外键值可以改变,选择引用中对应的父表的其他的值 Check on commit 在提交时检查引用完整性,而不是在插入某行后检查,可以通过使用该 特性控制循环依赖(仅适用于 Sybase SQL Anywhere 5.0 和 5.5) 其中,选择 Update constraint 和 Delete constraint 后,对子表的影响方式又有如下几种,如表 3-14 所示。 表 3-14 不同约束选择对字表的影响方式 选项 父表的改变 子表的结果 None 更新或者删除父表中的值 无影响 Restrict 如果子表中有一个或者多个对应的值 存在,就不能更新或者删除父表中的值 无影响 Cascade 更新或者删除父表中的值 更新或者删除父表中的值 Set null 更新或者删除父表中的值 将对应的子表的值设置为 NULL Set default 更新或者删除父表中的值 将对应的子表的值设置为默认值 请参考:3.5.1 创建触发器。 7.在 Integrity 属性页中修改 Constraint Name 为“FK_Student_Class”,在 Preview 中可 以看到相应代码: ========================================== alter table studentInfo drop constraint FK_Student_Class go alter table studentInfo add constraint FK_Student_Class foreign key (班级编号) references Class (classID) go ========================================== 点击【确定】按钮,图形模型中的连线上的文字也相应的改为“FK_Student_Class” 如果需要删除图形模型上的外键,只需要点击相应的联系,然后按下“Delete”键,会弹出 一个对话框,如图 3-30 所示。 图 3-30 删除引用确认对话框 作者:姜江 error 163 Delete objects 会将子表中和父表对应的字段自动删除,实际上 PowerDesigner 做了两件事 情,第一件事情就是删除外键引用的关系,第二件事情是删除子表中相应的列。 Delete symbols only:仅仅删除图形模型中的图符,而实际上的外键引用关系仍然存在 为引用定义相关的模型选项 在 PDM 中可以规定模型选项,包括 Model 和 Naming convention,其中 Naming convention 表示习惯命名方式,可以在这里定义命名的方式,以及通过这里定义各对象的 name 和 code 之间 的自动转化等。参考:第 7 章 高级应用&网友常见疑难解答(FAQ)以及 3.4.3 对列的操作的常 见问题及其解答。 而 Model 中可以定义模型的整体选项,包括表、视图、列、域、默认数据类型和引用等,其 中,引用的模型选项参考表 3-15。 表 3-15 模型选项中引用的部分参数及其含义 选项 选择后的结果 清除后的结果 Unique code 在命名空间中每个引用的代码 (code)都唯一 除非两个引用共享相同的子 表,否则不同的引用也可以使 用相同的代码(code) Auto-reuse columns 发生以下的情况时,子表中现有的 列会被自动用作外键列:  子列和迁移主键具有相同的代 码(code)  子列目前还不是外键  数据类型之间兼容 子表中的列不会被自动用作外 键的列 Auto-migrate columns 在引用创建时或者主键的定义改变 时,主键列被自动迁移到子表中成 为外键列,该选项选定才可以选择 下面的 Domain, Check 和 Rules 主键列不会被自动迁移 Domain 主键的域自动被迁移到外键上 域不会随着主键列自动迁移 Check 主键的检查参数自动被迁移到外键 上 检查参数不会随着主键列自动 迁移 Rules 主键的业务规则自动被迁移到外键 上 业务规则不会随着主键列迁移 Default link on creation: Primary 创建时引用连接主键列和外键列 - Default link on creation: User-defined 创建时不会连接列,也不会创建 join - 作者:姜江 error 164 Default implementation 指明引用完整性在引用中的实现。 如果希望为某个特定的引用定义完 整性请选择 Declarative,如果希望 通过触发器实现则选择 Trigger - Default implementation 的选择还会影响触发器的自动重建,选择了 Trigger 的 Reference 相关 的表才会自动重建触发器,请参考:3.5.1 创建触发器。 要定义引用的模型选项,选择【Tools】→【Model Options】,弹出模型选项窗口,如图 3-31 所示。 图 3-31 定义 Reference 的实现方法 模型选项其他选项含义如表 3-16 所示。 表 3-16 模型选项中引用的其他参数及其含义 选项 含义 All Objects : Name/Code case sensitive Name 和 Code 是否区分大小写 Table&View:Ignore identifying owner 如果选择该复选框,表示所有用户都可以修改表和视图, 如果没有选中表明只有表或者视图的创建者才可以修改 表和视图 Columns & Domain : Enforce non-divergence 选中表示列与域不可以有分歧,选中该选框后可以进一步 选择 Data type、Check、Rules、Mandatory、Profile, 如果选中,那么修改域的这些属性后,表中的这些属性也 会相应的发生改变。 作者:姜江 error 165 Default data type 创建列和域的默认数据类型,同时还可以规定精确度 (Precision)以及 Length(长度)属性 列的自动重用和自动迁移 如果在 Model Option 窗口中选择 Auto-migrate Columns,和 Default Link on Creation: Primary key,自动将主键列迁移到外键列中。如果同时选择 Auto-reuse Columns 和 Auto-migrate Columns,则在引用创建时会自动重用子表中已有的列作为外键列(前提条件是子表列的 code 和 需要迁移的主键列具有相同的 code,并且当前还不是外键列)。PowerDesigner 不会自动重用已经 存在的外键列,如果需要使用,可以手动在引用的属性窗口中的 Joins 属性页中手动修改。 下面举例说明这些选项对于创建引用(Reference)所产生的影响,来加深对这些选项的理解。 A. 创建两个表,子表“课程成绩”包含和父表中的主键匹配的列,如图 3-32 所示。 图 3-32 创建引用的实例 使用迁移的结果如表 3-17 所示。 表 3-17 不同迁移产生的不同结果实例一 Auto-reuse Auto-migrate 结果 对子表的影响 选中 选中 重用了列:学号 创建了列:姓名 不选中 选中 创建了列:学生_学号 创建了列:姓名 选中 不选中 重用了列:学号 未创建列:姓名 不选中 不选中 未重用列:学号 未创建列:姓名 B. 创建两个表,子表“课程成绩”包含和父表中的主键匹配的列,但是已经是外键,如图 3-33 所示。 图 3-33 迁移后的表“学生”和“课程成绩” 使用迁移的结果如表 3-18 所示。 作者:姜江 error 166 表 3-18 不同迁移产生的不同结果实例二 Auto-reuse Auto-migrate 结果 对子表的影响 选中 选中 创建了列:学生_学号 创建了列:姓名 不选中 选中 创建了列:学生_学号 创建了列:姓名 选中 不选中 未重用列:学号 未创建列:姓名 不选中 不选中 未重用列:学号 未创建列:姓名 重建引用(Rebuild Reference) 在物理模型中重建引用(Rebuild Reference)可以在表之间的匹配的键列之间创建默认的引 用。如果反向工程不能将所有的引用都反向,那么可以使用重建引用。重建的方式有以下两种, 如表 3-19 所示。 表 3-19 重建引用方式 Rebuild Option 描述 Delete and rebuild 删除所有现存的引用,然后根据匹配键列创建引用 Preserve 保留所有现存的引用,然后根据匹配键列创建新的引用 重建引用的方法如下: 1. 选择【Tools】→【Rebuild Object】→【Rebuild References】,弹出重建引用对话框 2. 在 General 属性页上选择 Delete and rebuild 或者 Preserve 单选按钮 3. 进入 Selection 属性页,选择需要为那些表重建引用,默认情况下全选,如图 3-34 所示。 图 3-34 选择需要重建引用的表 4. 点击【确定】按钮。如果选择 Delete and rebuild,会弹出确认窗口,点击【是(Y)】按钮。 作者:姜江 error 167 选择引用的图形显示方式 选择【Tools】→【Display Preference】,或者在图形模型的空白处点击鼠标右键,在弹出 的菜单中选择【Display Preference】,弹出 Display Preference 定义窗口,选择【Object View】 →【Reference】,如图 3-35 所示。 图 3-35 在“Display Preferences”设置引用的对象视图 如图 3-35 所示,Center text 表示在连线上显示的文字,可以是以下几种:Name(引用的名 称);Constraint name(引用完整性约束的名称);Join(连接,如图 3-36 所示); Reference integrity(显示引用完整性,如图 3-37 所示)。 End text 则表示在引用线一端显示的文本,包 括 Cardinality(基数,如图 3-38 所示),以及 Implementation(实现方式,如图 3-39 所示),。 图 3-36 在引用连线上使用“Join” 图 3-37 在引用连线上使用“Reference integrity” 图 3-38 在引用连线上使用“Cardinality” 作者:姜江 error 168 图 3-39 在引用连线上使用“Implementation” 上面的第二张图中的各种符号的含义如下:upd()表示更新,del()表示删除,cpa 表示 Change Parent Allowed。括号中的字符的含义如下:括号为空表示 None,R 表示 Restrict,C 表示 Cascade, N 表示 Set null,D 表示 Set default。 除此之外,还可以定义 Reference 的三种不同的显示模式,如表 3-20 所示。 表 3-20 Reference 的不同显示模式 Label 显示特征 图形 Relational 箭头指向主键 CODASYL 箭头指向外键 Conceptual 基数以 IE(信息工程)格式显示 (Crow‟s feet 表示方法,该方法 通常用于表示一对多的关系) 学习了引用的图形显示方式后,可以根据自己的需要定义其他图形的显示方式。此外,还可 以修改图形的具体样式,操作的方式如下: 选择【Tools】→【Display Preference】,或者在图 形模型的空白处点击鼠标右键,在弹出的菜单中选择 Display Preference,弹出 Display Preference 定义窗口,选择【Format】→【Reference】(还可以是其他对象) ,如图 3-40 所示。 作者:姜江 error 169 图 3-40 设置引用的显示格式 可以在上面的窗口中一些图形的格式属性,如果要进一步修改图形的格式,点击上面窗 口右下角的【Modify】按钮,弹出以下样式的窗口,如图 3-41 所示。 图 3-41 引用图符格式的“Line Style”页 可以在该窗口中设置图形的样式(Line Style)、字体(Font)、影子(Shadow)以及填充(Fill), 读者可以根据自己的需要定制出漂亮的模型图形。 3.4.5 定义索引(Index) A.索引的基本概念及其优化 索引是一种和表相关的数据结构,它根据键的值进行逻辑排序。可以提高数据库运行效率和 存取速度。通常,会在那些经常被访问的列以及响应时间也非常重要的列上创建索引。索引使用 在那些大多数值是唯一值的列上是最有效的。 例如:有一张表 Author,为主键 Author ID 和列 Author name 创建索引,但是不包括 City, 作者:姜江 error 170 因为 City 列中的值不太可能是唯一,而且不是经常被查询,不能通过在该列上创建索引来减沙查 询时间。 下面,将向读者介绍一些使用索引需要注意的问题,以及如何有效地调整索引提高数据库的 整体性能,优化数据库设计。 索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率。现在大多数的数据 库产品都采用 IBM 最先提出的 ISAM 索引结构。索引的使用要恰到好处,其使用原则如下:  在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化 器自动生成索引。  在频繁进行排序或分组(即进行 group by 或 order by 操作)的列上建立索引。  在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索 引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立 索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。  如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。  使用系统工具。 如果使用索引时不认真考虑其实现过程,索引既可以提高也会破坏数据库的工作性能。尽管 任何索引的目的都是用来提高检索和更新数据的速度,但每种类型的索引对于某种特定的任务有 更高的效率。大多数情况下,各种类型的索引有相近的数据检索速度,但是查询稍作变化时那些 相同索引的性能却有很大的不同。绝大多数的数据库开发人员都知道将索引设在表的主键字段中, 也可以设在相关表的外键字段。尽管如此,还是有许多问题需要考虑,如用户应该使用什么类型 的索引?可以将索引设在某个表中其他非主键字段吗?何时应该使用复合索引?这部分我们将学 习如何解决这些问题,不过要学会如何使用索引,应该首先了解索引的实际结构。这里主要以 SQL Server 2000 为例,SQL Server 2000 提供了两种索引:聚簇索引(clustered index)和非聚簇索 引(nonclustered index)。 a.非聚簇索引 非聚集索引与课本中的索引类似。数据存储在一个地方,索引存储在另一个地方,索引带有 指针指向数据的存储位置。索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存 储(这可以由聚集索引规定)。如果在表中未创建聚集索引,则无法保证这些行具有任何特定的顺 序。 b.聚簇索引 聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,后者按姓氏排列数据。由于聚 集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含 多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。 聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后, 便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行的一个查询经常检索某一 日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的 作者:姜江 error 171 行,直到到达结束日期。这样有助于提高此类查询的性能。同样,如果对从表中检索的数据进行 排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行 排序,从而节省成本。因为数据用聚簇索引来组织物理存放顺序,因此,每张表只能创建一个聚 簇索引;而非聚簇索引则可以多个。 c.聚簇索引和非聚簇索引的比较 1. ORDER BY 和 GROUP BY 短语 如果用户经常选择数据和使用 ORDER BY 和 GROUP BY 短语,任何一种索引都有助于 SELECT 的性能提高。如果用户选择的是顾客并按其姓名分类,两种索引都能快速检索数据。但是不同的 情况下不同的索引的性能差距也可能很大。 2. 返回范围内的数据 例如,如果用户希望返回在 Adam 和 Johnson 之间的所有顾客姓名,或者返回在日期“11/1/03” 和“11/30/03”之间的订货量,并且用户经常做这类事情,那么最好在该范围所在的指定列使用 聚簇索引。因为聚簇索引已经包含了经过分类排序的数据,这对于在指定范围内检索数据更为有 效。聚簇索引只需找到要检索的所有数据中的开头和结尾数据即可;而不像非聚簇索引,必须在 数据层中查找来自叶层的每一个数据项。 3. 列中有一个或极少的不同值 在用户表中的某些列中含有极少的不同值,例如状态列中只包含 Inactive、Active 或者 Terminated。在这种情况下,在该列上使用任何类型的索引都是不明智的,原因很简单:如果用 户表包含 15000 行,大概有三分之一的行即 5000 行在状态列中含有 Active。扫描整个表,如果 不是更高效,至少也是同先在索引页面中查找每个数据项而后寻找到包含有 Active 状态的行所在 的数据页面有相同的效率。下面的清单创建一个表,它在有很多重复值的列上进行索引,而该列 具有很少的不同值。 ====================================================================== CREATE TABLE TestTable ( tableId int IDENTITY(1,1) NOT NULL, Status char(10) NULL ) GO SET IDENTITY_INSERT TestTable ON DECLARE @intCounter int BEGIN TRAN SELECT @intCounter = 1 WHILE @intCounter <= 15000 BEGIN 作者:姜江 error 172 INSERT TestTable (tableId, Status) VALUES (@intCOunter, 'Active') SELECT @intCounter = @intCounter + 3 END SELECT @intCounter = 2 WHILE @intCounter <= 15000 BEGIN INSERT TestTable (tableId, Status) VALUES (@intCOunter, 'Inactive') SELECT @intCounter = @intCounter + 3 END SELECT @intCounter = 3 WHILE @intCounter <= 15000 BEGIN INSERT TestTable (tableId, Status) VALUES (@intCOunter, 'Terminated ' ) SELECT @intCounter = @intCounter + 3 END COMMIT TRAN SET IDENTITY_INSERT TestTable OFF GO DUMP TRANSACTION pubs WITH NO_LOG GO CREATE INDEX inTestTableStatus ON TestTable (Status) GO 接下来运行下面两个 SELECT 语句: ====================================================================== --Force the Query Optimizer to use a table scan SELECT * FROM TestTable WITH(index(0)) WHERE Status = 'Inactive' --Force a particular index to be used by the Query Optimizer SELECT * FROM TestTable WITH(index(inTestTableStatus)) WHERE Status = 'Inactive' ====================================================================== 这段代码的 Stats I/O 信息显示了两种不同的结果。第一个 SELECT 语句引起表的全扫描并只 需执行 45 个该内存操作,而第二个 SELECT 语句则需要执行 5018 个读操作。 当使用索引选择数据时,系统必须读统计页面、索引根、索引节点和数据页面。这通常会减 少读操作的数目,但要返回的记录数目很大时,仍需要更多的读操作。 作者:姜江 error 173 4.不同值的数目比较少 当索引列中不同值的数目增加时会怎么样呢?或者如果表很庞大时又会怎样呢?随着表中行 的数目和列中不同值的数目的增长,使用索引会得到越来越多的好处。我们观察以下代码: ====================================================================== DROP TABLE TestTable GO CREATE TABLE TestTable ( tableId int IDENTITY(1,1) NOT NULL, Status char(10) NULL, Col3 char(20) NOT NULL, Col4 char(50) NOT NULL ) GO DECLARE @intNum int SELECT @intNum = 0 BEGIN TRAN WHILE @intNum <= 1300 BEGIN INSERT TestTable VALUES (CHAR(@intNum % 26 + 65), 'test3', 'test4') SELECT @intNum = @intNum + 1 END COMMIT TRAN GO ====================================================================== 执行下面两个查询语句 ====================================================================== --Force the Query Optimizer to use a table scan SELECT * FROM TestTable WITH(index(0)) WHERE Status = 'B' --Create and Force a particular index to be used by the Query Optimizer CREATE CLUSTERED INDEX icTestTableStatus ON TestTable (Status) GO SELECT * FROM TestTable WITH(index(icTestTableStatus)) WHERE Status = 'B' 作者:姜江 error 174 ====================================================================== 使用聚簇索引在检索其中的数据时更加有效。由于数据驻留在索引的叶节点上,在读数据时 就不需要再转向数据页面进行操作。因此,只需执行较少的读页面操作。下面是这两条查询语句 执行的 Stats I/O: ====================================================================== --Stats I/O from table scan access (comment was added) Table 'TestTable'. Scan count 1, logical reads 16, physical reads 0, read-ahead reads 0. --Stats I/O from clustered indexed access (comment was added) Table 'TestTable'. Scan count 1, logical reads 3, physical reads 1, read-ahead reads 2. ====================================================================== 5.有大量数目的不同值和更新索引列数据 当要搜索的列含有较少的不同值时,使用聚簇索引是有帮助的。但当不同值的数目增加并达 到表中行的数目时,最好选择使用非聚簇索引。尽管读页面的数目在使用非聚簇索引和聚簇索引 访问时不会有很大变化,但对表进行写操作的性能却是一个需要研究的问题。无论何时,当用户 对索引列作修改时, SQL Server 2000 都要使用该列对索引进行修改。当使用聚簇索引时,这可 能需要改变索引根,改变索引节点,甚至可能需要在数据层/叶层插入一个数据行,并引起潜在的 数据行移动。当用户修改使用非聚簇索引的列时,索引根、索引节点和叶层都将会发生改变,但 与叶层相分离的数据层则不需要移动,因为数据行可以在需要时添加到后面。由于数据页面的处 理与索引页面的处理相分离,所有的数据行需要较少的移动。这样就能够更快地修改数据。要经 常更新统计信息和重构索引,否则,时间太久索引就会分成碎片,这和硬盘的情况类似。重构索 引实际上是一种索引碎片整理过程。重构助于查询优化器更好地决定如何处理查询。 6. 频繁更新列 如果用户使用索引列是为了找到需要更新的行,使用聚簇索引会更快地找到数据。如果用户 不修改聚簇索引所在的列,当更新数据时不会影响执行效率,因为不涉及索引数据。 7. 返回某范围内的数据 大多数时候,聚簇索引总是更好些。但绝大多数情况下,使用聚簇索引来检索某范围内的数 据更好一些,下面的脚本创建有许多不同值的表 ====================================================================== DROP TABLE TestTable GO CREATE TABLE TestTable ( Id int IDENTITY(1,1) NOT NULL, 作者:姜江 error 175 status char(20) not null ) GO DECLARE @intNum int SELECT @intNum = 0 BEGIN TRAN WHILE @intNum <= 5000 BEGIN INSERT TestTable VALUES ('test' + convert(char(6),@intNum)) SELECT @intNum = @intNum + 1 END COMMIT TRAN GO ====================================================================== 下面的脚本检索某范围内的行 ====================================================================== SELECT Status FROM TestTable WITH(index(0)) WHERE TableId BETWEEN 1000 and 1500 GO CREATE CLUSTERED INDEX icTestTableId ON TestTable (TableId) GO CREATE INDEX inTestTableId ON TestTable (TableId) GO SELECT Status FROM TestTable WITH(index=(nTestTableId)) WHERE TableId BETWEEN 1000 and 1500 SELECT Status FROM TestTable WITH(index=(cTestTableId)) WHERE TableId BETWEEN 1000 and 1500 ====================================================================== 以下为执行的 Stats I/O 结果 --Stats I/O from table scan access (comment was added) Table 'TestTable'. Scan count 1, logical reads 22, physical reads 0, read-ahead reads 8. --Stats I/O from nonclustered indexed access (comment was added) Table 'TestTable'. Scan count 1, logical reads 1060, physical reads 2, read-ahead reads 0. 作者:姜江 error 176 --Stats I/O from clustered indexed access (comment was added) Table 'TestTable'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0. ====================================================================== 即使是表扫描也比非聚簇索引更有效。正如前面所指出的那样,如果返回多行查询结果,使 用非聚簇索引通常是一种很差的选择。聚簇索引要求使用的读操作最少。SQL Server 2000 仅搜 索索引节点页面中的开头和结尾两个值,并找到数据所在的首页面和尾页面,而后在它们之间顺 序地读出数据/叶节点页面,便可得到所需要的信息。 8. 主键和外键 选择在主键上创建聚簇索引应取决于其他列的聚簇索引能否带来更大的好处。创建聚簇索引 并非一定要在主键上进行;其他索引,例如频繁进行范围检索的索引可能是更好的聚簇索引候选 项。如果存在这种情况,用户应当做出很好的判断并将主键作为非聚簇索引。 对于外键,也可遵循与上述相同的规则。并注意外键经常包含重复值,因为它是作为“一对 多”关系中多的一方。这样经常符合作为聚簇索引的标准。用户不必将外键强制为聚簇索引;但 如果它是最好的候选项,则不存在任何问题。如果表既包含主键也包含外键,则决定谁作为聚簇 索引的问题稍有麻烦。注意例如,数据库 pubs 中的 titles 表,设计成在 pub_id 字段使用聚簇索 引;在 title_id (主键)字段使用非聚簇索引。因为大多数出版商生产多种图书,titles 表中的 pub_id 并不是单值数据集。将聚簇索引应用于 pub_id 列比应用于 title_id 列更好,因为后者没 有重复副本。因此当用户从 titles 和 publishers 中检索数据时会得到更好的总体性能。如果 publisher 表很少与 titles 表作联结运算,或者当 titles 与 publisher 表联结时只能选择出少 数几个书名;则在 title_id 字段使用聚簇索引和在 pub_id 字段使用非聚簇索引是一种较好的方 案。 对用户检索什么样的信息了解得越多,就越容易对使用什么类型的索引做出选择。在使用索 引时请参考表 3-21。 表 3-21 选择索引建议原则 描述 使用聚簇索引 使用非聚簇索引 列经常被分组/排序 推荐 推荐 返回某范围内的数据 推荐 不推荐 小数目的不同值 推荐 不推荐 大数目的不同值 不推荐 推荐 一个或者极少不同值 不推荐 不推荐 返回行数量较小 不推荐 推荐 频繁更新的列 不推荐 推荐 外键列 推荐 推荐 作者:姜江 error 177 主键列 推荐 推荐 频繁修改索引列 不推荐 推荐 此外聚簇索引还适合在以下几种情况使用:1.被连续访问的列;2. OLTP 类型的应用程序, 这些程序要求进行非常快速的单行查找(一般通过主键)。应在主键上创建聚集索引 而非聚簇索引还在以下情况适合使用:1. 返回精确匹配的查询的搜索条件(WHERE 子句)中 经常使用的列;2. 在特定的查询中覆盖一个表中的所有列。这将完全消除对表或聚集索引的访问。 索引有助于提高检索性能,但过多的索引会导致系统低效。用户在表中每加进一个索引,维 护索引集合就要作更多的工作。标准的维护任务如更新表统计数据和重构索引,对每个新创建的 索引都要花更多的时间。如果在需要更新的列上建立索引,用户对该列的每次更新,SQL Server 就要作额外的工作去执行。 实际使用时可以根据测试每种类型的索引来决定使用哪一种方案更能够提高数据库的整体性 能。标准数据库测试的其中一部分应该包括对聚簇索引和非聚簇索引的各种不同组合都考察到。 一些方案表明有些索引既适合于聚簇,也适合非聚簇索引。找出它们中最好索引类型的唯一方法 就是试验每种类型,使用每种索引类型对查询进行测试,从而得出哪种最有效。而后对每种测试 运行几天,和用户一起检查它们在性能上有什么不同之处。 d.复合索引 在创建复合(composite)或多列索引时,列的顺序对于索引的效率和查询优化器如何使用索引 起着重要的作用。列数太多也会显著地增加索引的大小,占用更多的空间并需要更多的时间来查 找信息。 下面是一些使用复合索引的规则: 1.不要包含那些不能形成单值数据集的列:例如,如果使用lastname和firstname的索引包含 很少的重复副本,就不要再将middlename加进去。这只会增加查找相同信息所要搜索的页面数目。 2.不单独进行搜索的列决不要首先排列在索引中:例如,如果用户经常使用lastname和 firstname,或者只使用lastname进行搜索,那么firstname就不要出现在复合索引lastname和 firstname的起始列中。如果确实将firstname放在lastname之前,那么只对lastname进行搜索时 就永远不会使用索引;如果用户强制使用lastname作索引,这样作的效率是很低的。 3.如果用户经常从表中的一个或少数几个字段中检索数据,当非聚簇索引包含要检索的所有 字段时,就会减少所需读操作的数目:这种查询方法称为“覆盖查询” (covered query)。覆盖 的查询可以提高性能。 覆盖的查询是指查询中所有指定的列都包含在同一个索引中。例如,如果在一个表的 a、b 和 c 列上创建了组合索引,则从该表中检索 a 和 b 列的查询被视为覆盖的查询。创建覆盖一个查 询的索引可以提高性能,因为该查询的所有数据都包含在索引自身当中;检索数据时只需引用表 的索引页,不必引用数据页,因而减少了 I/O 总量。尽管给索引添加列以覆盖查询可以提高性能, 但在索引中额外维护更多的列会产生更新和存储成本。如果索引包含要检索的所有数据,就没有 必要到数据页面中去获取数据,因为索引本身已经提供了检索所需的所有信息。覆盖查询只应用 作者:姜江 error 178 于少数相同的列被频繁使用的情况。另外,当用户修改数据时,不要忘记考虑性能问题。如果这 些列经常被更新,用户和SQL Server都要对索引作更多的维护。当SELECT语句执行效率的提高不 能弥补这些更新操作所带来的效率的下降时,最好不要使用覆盖查询。 例如,假定用户在authors表上创建一个索引,该索引包含如下的列:au_lname、city、state 和phone。用户要经常从查询的返回列中获得信息(以字典顺序),但是用户行踪不定,需要经常地 改变city、state和phone列,甚至与用户查找这些信息一样频繁。由于索引中四列有三列经常更 新,索引会导致这些更新操作进行得较慢。如果检索速度的提高不能弥补损失的时间,就应该放 弃索引。观察下面的几段脚本以及执行情况。这段脚本创建具有多个不同值的表: ====================================================================== DROP TABLE TestTable GO CREATE TABLE TestTable ( TableId int IDENTITY(1,1) NOT NULL, status char(20) not null ) GO DECLARE @intNum int SELECT @intNum = 0 BEGIN TRAN WHILE @intNum <= 5000 BEGIN INSERT TestTable VALUES ('test' + convert(char(6),@intNum)) SELECT @intNum = @intNum + 1 END COMMIT TRAN GO CREATE CLUSTERED INDEX icTestTableId ON TestTable (TableId) GO CREATE INDEX inTestTableId ON TestTable (TableId) GO ====================================================================== 下面的两个查询语句使用覆盖查询选择数据 作者:姜江 error 179 ====================================================================== SELECT TableId FROM TestTable WITH (index (nTestTableId)) WHERE TableId BETWEEN 1000 and 1500 SELECT TableId FROM TestTable WITH (index (cTestTableId)) WHERE TableId BETWEEN 1000 and 1500 ====================================================================== 上面两个查询语句的Stats I/O结果 ====================================================================== --Stats I/O from nonclustered indexed access (comment was added) Table 'TestTable'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0. --Stats I/O from clustered indexed access (comment was added) Table 'TestTable'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0. ====================================================================== 结果表明,由于包含绝大多数的检索数据,非聚簇索引只需要读取很少的数据页面。非 聚簇索引在这里的范围检索中也比聚簇索引要好(因为数据/叶层占用更多的空间)。如果表的数据 行很庞大,非聚簇索引会比聚簇索引更为有效。 使用索引检索和更新数据 前面提到索引在数据检索和修改之间的有冲突,下面两种情况下,索引能够同时提到检索和 更新的效率:  当索引的字段用来定位要检索和修改的数据,而自身不被修改时;  当数据的更新比数据的插入和删除更加频繁时。 例如,在pubs数据库中的authors表有一个键列au_id,它用来找到要检索和更新的作者而自 身从来不被修改。所有的索引在向表中插入数据时,都会降低工作性能。因为表中要加入新信息, 索引必须相应地重新进行动作。 如果索引的字段是用来定位要删除的行时,当从表中删除数据时索引就会提高工作性能。尽 管从表中删除一行数据时SQL Server需要作一些维护工作,但通常寻找要删除的记录所增加的速 度超过维护工作所带来的速度降低。当用户使用仅含键au_id的索引删除au_id号为“123-45-6789” 的作者时,该索引提高了搜索该作者的速度。尽管数据项必须从索引中删除(因为该行已不在表 中),此操作花费的总时间远小于使用索引查找作者所节省的总时间。如果索引中的字段用来定位 行数据并且不被任何更新操作改变,更新数据总会提高工作 性能。如果用户更新索引中的字段,就会引起SQL Server作一些维护工作,从而降低性能。 例如,当用户打算更新 au_id 为“111-22-3333”的作者并提供使用 au_id 的索引,使用 au_id 的索引将会减少查找记录和进行修改的总时间。如果没有该索引,必须搜索整个表来确定需要更 作者:姜江 error 180 新的所有记录。 B.在 PowerDesigner 中创建索引 你可以创建用户自定义的索引(和一个或者多个列相关),或者创建主键、外键、候选键。对 键创建索引的习惯命名方法如表 3-22 所示。 表 3-22 不同类型索引的命名方法 索引 习惯命名方法 主键 表的 code 后面加 PK;例如:student_PK 外键 列的 code 后面加 FK;例如:classID_FK 候选键 列的 code 后面加 AK;例如:studentNo_AK a.创建用户定义的索引的步骤 1. 双击图形模型中的表“学生”,弹出表属性窗口 2. 进入 indexes 属性页,该属性页会列出已经存在的索引 3. 点击列表中的一个空白行 或者点击窗口上方的第二个按钮 在该行中将会出现一个箭头 4. 输入 name 和 code 为 STU_NAME_IDX 5. 点击【Properties】 或者按快捷键【Alt+Enter】或者双击该行最左端的箭头,弹出索引 属性窗口 6. 在 General 属性页中写入备注 comment,选定该索引是否为 Unique 以及 Cluster 索引 进入 Columns 属性页,这里显示和该索引相关的行,点击【Add a Row】 工具,弹出一个窗口, 该窗口列出该表所包含的列,选择一个或者多个列,在该例中选择列“姓名”,确定 如果数据库是 Oracle,可以在这里的列的列表后面有一列是 Sort 可以规定索引按升序或者 是降序排列,选择升序 Ascending,点击【确定】按钮,该索引创建成功。 如果 DBMS 是 SQL Server 2000 中则没有该属性,那么如何解决这个问题呢?这需要自定义生 成数据库脚本,请参考: 第 7 章 高级应用&网友常见疑难解答(FAQ)(7.3 问题三)。 创建和键连接的索引的步骤: 如果你将一个索引和主键、外键或者候选健,当键的行被修改时,该索引也自动更新。例如: 一个表的主键有几个列组成的主键叫做复合主键。创建一个连接到该复合主键上的索引,如果你 删除该主键中的一个列,那么该索引中对应的列也会相应的被删除。如果删除主键中所有的列, 也就是表中不再有主键,则该索引会被删除。 1. 点击图形模型中的表“学生”,弹出表属性窗口 2. 进入 indexes 属性页,该属性页会列出该表已经建立的索引 3. 点击列表中的一个空白行 或者点击窗口上方的第二个按钮 在该行中将会出现一个箭头 4. 输入 name 和 code 为 studentID_PK 作者:姜江 error 181 5. 点击【Properties】 或者按快捷键【Alt+Enter】或者双击该行最左端的箭头,弹出索引 属性窗口 6. 在 General 属性页中写入备注 comment,选定该索引是否为 Unique 以及 Cluster 索引 7. 进入 Columns 属性页,这里显示和该索引相关的行。在 Columns Definitions 下拉框中选中 PK: Key_1,表示建立主键的索引,此时,该主键中包括的列都会出现在下面的 columns 列表。 如果是选择外键,则可以发现在 Columns Definitions 下拉框中的外键名称是引用 reference 的名称 8. 如果数据库是 Oracle,我们可以在这里的列的列表后面有一列是 Sort 可以规定索引按升序或 者是降序排列,选择升序 Ascending,如果 DBMS 是 SQL Server 2000 中则没有该属性。点击 【确定】按钮,该索引创建成功。 b.创建基于函数(functions)的索引的步骤: 在某些 DBMS 中(例如:Oracle 就具备该功能,而 SQL Sever 不具备),你可以创建一些基于 函数(functions)和表达式(expressions)的索引,这种索引会涉及到表中一个或者多个列。 基于函数的索引事先计算好函数和表达式的值,然后存储在索引中。在这类索引中,函数和表达 式将代替索引的列。 例如:创建基于函数的 UPPER(column_name)或者 LOWER(column_name)的索引,能够使得大小 写不敏感的查询更加容易。 假设我们定义一个索引,它将表“学生”中的“姓名”都转化为小写,可以定义一些索引: create index "fun_name_IDX" on "student" ( lower(NAME) ASC )。 执行如下查询时,DBMS 将会使用到该索引: SELECT * FROM STUDENT WHERE LOWER (NAME) ='JIANGJIANG',因为 SQL Server 2000 不支持这种索引,我们可以临时通过【Database】→【Change Database】将 DBMS 切换为“Oracle version 9i” 1. 双击图形模型中的表“学生”,弹出表属性窗口 2. 进入 indexes 属性页,该属性页会列出该表已经建立的索引 3. 点击列表中的一个空白行 或者点击窗口上方的第二个按钮 在该行中将会出现一个箭头 4. 输入 name 和 code 为 fun_name_IDX 5. 点击【Properties】 或按快捷键【Alt+Enter】或者双击该行最左端的箭头,弹出索引属 性窗口 6. 进入 Columns 属性页,点击 或者 或者点击空白行,建立一个新行 7. 点击该窗口右上方的【Customize Columns and Filter】 按钮,或则通过快捷键【Ctrl +U】,在弹出的窗口中选中 Expression 复选框 8. 点击 Expression 列中的 按钮,弹出 SQL Editor 窗口 作者:姜江 error 182 9. 在编辑器中输入表达式:lower(name),点击【确定】按钮。SQL Editor 窗口下放提供了丰富 的表达式函数以及聚和函数,如图 3-42 所示。 图 3-42 在“SQL Editor”窗口中编辑索引的函数 c. Rebuilding indexes(重新创建索引) 重新创建物理模型中的索引能够自动更新主键、外键、候选键中的任何变化。可以为模型或 者模型中的某个包单独重建索引。参考 3.12 PDM 模型的检查(Check)中将学习如何检查模型, 有些时候我们没有为每个主键和外键都建立索引,因此,检查模型的结果是往往有很多警告 (warning),提示:Existence of indexes,表明某个表没有索引。或者我们不想每次都要手动 定义每个主键和外键的索引的时候就可以使用重建索引来自动为所有的键创建索引。如图 3-43 所示。 图 3-43 “Index Rebuild”窗口 如图所示,主键的输入框中为%TABLE%_PK,“ %TABLE%”为命名变量。 主键可以使用的命名变量有:%TABLE%:表生成的 code(如果 code 不满足 DBMS 的长度要求,则 生成的 code 会自动截短表的 code); %TNAME%,表的 name;%TCODE%,表的 code;%TLABL%,表的 comment; 外键可以使用的命名变量有:%REFR%:reference(引用)生成的 code;%PARENT%,父表生 成的 code;%PNAME%,父表的 name;%PCODE%,父表的 code;%CHILD%,子表的生成的 code;%CNAME%, 子表的 name;%CCODE%,子表的 code;%PQUALIFIER%,父表的 qualifier;%CQUALIFIER%,子表 作者:姜江 error 183 的 qualifier;%REFRNAME%,Reference 的 name;%REFRCODE%,Reference 的 code; 重建索引的步骤: 1. 选择【Tools】→【Rebuild Objects】→【Rebuild Indexes】,或者按快捷键【Shift+Ctrl +I】,弹出索引重建的窗口,如图 3-43 所示。其中:  Foreign key threshold 表示生成外键之前表中至少应该有多少条记录;  Delete and Rebuild 表示在索引重建之前删除所有的现有的索引;  Preserve Indexes 表示保留物理模型中的现有的所有的索引; 2. 选择 Delete and Rebuild 单选框,表示在先删除模型中所有的主键、外键、候选键的索引, 然后重建 3. 在 Selection 属性页中选择需要更新的表,这里选择全部表 4. 点击【确定】按钮,弹出确认窗口,提问是否确认删除并重建键的索引,点击【确定】按钮 5. 点击表“学生”,进入 indexes 属性页,发现前面建立的主键索引 studentID_PK 已经不存在, 取而代之的是 student_PK。 6. 这时候,再按 F5(检查模型),发现以前的警告(warning)“ Existence of index”已经不 存在了,关于模型的检查请参考:3.12 PDM 模型的检查(Check)。 3.4.6 创建视图(View) A.创建视图 视图以另一种方式来代表一个或多个表中的数据。它由一个或者多个表的多字段的子集组成。 你可以为每个视图定义 SQL 查询语句。 可以为图形中选定的表和视图创建视图,如果选定的表和视图之间有 reference 或者视图 reference 连接,那么他们之间的连接将会在视图查询中以条件的形式出现。创建步骤如下: 1. 选择图形模型中的表“学生”、“学生组织成员”、“职务”以及“学生组织”,(PowerDesigner 中选择多个表要按住 Shift 键) 2. 选择【Tools】→【Create View】,这时在图形模型中会出现一个视图的图符。最上方为视 图的名称 View_1,中间为这几个表的所有的字段,最下方为各个表和视图的名称。如图 3-44 所示。 3. 双击该图形,弹出视图的属性窗口,在 General 属性页中可以输入视图的 name 和 code,点击 【确定】按钮。 4. 进入 Columns 属性页,可以定义那些表要出现在视图中,将不需要的列删除。或者直接进入 SQL Query 属性页中修改代码,在 select 中去掉不需要的列。 如果需要编辑该 SQL 语句,可以点击该属性页下方的【Properties of selected query】 或者【Edit】 进行编辑。其中,后者弹出 SQL Editor 窗口,该窗口中列出了数据库模型中包 批注 [e6]: 此处引用编号错误,已更 正 批注 [e7]: 此处原为“见右边图” 作者:姜江 error 184 含的数据库元素,并且还有提前定义好的一些函数和表达式可以使用,这样,即使设计者记不清 一些函数也可以直接从中选择。 图 3-44 选择表之后创建视图 创建一个空的视图,然后选择表和视图: 1. 选择【Tools】→【Create View】(前提是没有选中模型中的任何表或者视图) 2. 会弹出一个选择窗口,该窗口中列出了模型中的所有的表和视图,选择需要的表和视图 3. 点击【确定】按钮,这时图形模型中同样会出现一个视图的图符 4. 双击进入属性页,其他操作同前面定义视图相同。 为视图使用扩展依赖: 扩展以来是物理模型中对象之间的依赖。这些依赖能够使得对象之间的关系更加清晰,但它 本身并不被 PowerDesigner 解释或者检查,主要是出自文档的考虑才建立扩展依赖。 使用版型(stereotypes)可以补充说明这些连接。可以直接在对象属性窗口中输入版型。如 果在导入的或者内嵌的扩展模型定义(.XEM)中有事先定义好的版型,可以直接在下拉列表中选 择。 可以在表和视图之间使用扩展依赖。在本例中,点击 Palette 面 板 上 的【 Link/ ExtentedDependency】,在视图与几个表之间建立联系,在视图的属性窗口中的 Extended Dependencies 属性页中,在 Stereotype 列输入各个依赖的 stereotype,如图 3-45 所示。 作者:姜江 error 185 图 3-45 在视图和表之间建立扩展依赖 B.为视图(View)定义 reference(引用) 具体的操作步骤如下: 1. 在图形模型中双击视图,显示视图属性窗口 2. 进入 SQL Query 属性页 3. 点击该下方【Properties of selected query】 工具 4. 在弹出的查询属性窗口中,点击 Where 页面,如图 3-46 所示。 5. 选择适当的列可以定义视图与表之间的引用(reference) 图 3-46 视图查询属性窗口的“Where”页 C.为视图中包含的表和列指定别名(Alias) 通过为视图中的表和列指定别名,可以避免在查询脚本中打出完整的代码。操作方法如下: 1. 在图形模型中双击视图,显示视图属性窗口 2. 进入 SQL Query 属性页 3. 点击该下方【Properties of selected query】 工具 4. 在弹出的查询属性窗口中,点击 Table 或者 columns 页面 5. 选择需要赋予别名的行,在 Alias 列中输入别名,点击【确定】按钮。 可以通过 SQL Query 属性页看到相应的变化,以后在书写 SQL 查询语句的时候就可以直接用 这个别名代替要加上表名的复杂冗余的列名。 作者:姜江 error 186 定义视图的生成次序: 可以使用扩展依赖定义视图生成的先后次序。扩展属性是 PDM 中对象的自由连接。这些连接 能够使得对象之间的关系更加清楚。通常这些关系不被 PowerDesigner 解释或者检查,因为他们 住的目的是生成文档。但是,如果你规定视图之间的扩展依赖的 stereotype 为《DBCreateAfter》, 生成数据库脚本的时候会被分析。 如果你创建了一个自反的、循环的 stereotype 为《DBCreateAfter》的扩展依赖,在检查模 型的时候会提示错误。如果你选择忽略该错误,视图将会以字母顺序创建,如果不考虑生成顺序, 那么生成视图的时候往往会导致错误。 假设为一个表“STORE”创建一个视图:DEPARTMENT STORE,该表的 SQL 语句如下:select STORE.STOR_ID, STORE.CITY, SOTRE.STATE from STORE,然后又创建另外一个视图 COMPUTER COUNTER 只显示 DEPARTMENT STORE 的数据的一部分,这个视图由 DEPARTMENT STORE 创建。 默认情况下:视图是按照字母生成的,所以 COMPUTER COUNTER 会在 DEPARTMENT STORE 之前 生成,但是生成 COMPUTER COUNTER 的时候会出现错误,因为它必须依赖于 DEPARTMENT STORE 生 成后才能成功。解决这个问题的办法是在两个视图之间创建 stereotype 为《DBCreateAfter》的 扩展依赖,如图 3-47 所示。 图 3-47 视图之间建立扩展依赖设定生成次序 D.定义视图的引用 视图的引用指的是父表和视图之间或者子表和视图之间的连接。它用于定义一系列事先定义 好的父表和子表或者视图的列之间的 join(连接)。 例如:表 Order 为视图 Customer_Order 的父表,如图 3-48 所示。 点击 Palette 面板中的 Reference 工具,然后按照表之间建立引用的方法建立视图的引用。 相关的操作请参考:3.4.4 定义外键/引用(ForeignKey/Reference)。 图 3-48 定义视图之间的引用 E.PowerDesigner 10 中的视图 前面第一章提到过,在 PowerDesigner 10 中,视图中的列已经成为一个标准的对象,在相应 的属性页内,包含 name,code,comment 等属性,可以像定制表的列一样,在视图的属性窗口中 定义视图。 作者:姜江 error 187 示例:在 PowerDesigner 10 中定义一个视图,打开视图属性窗口,如图 3-49 所示。而在 PowerDesigner 9.5 中的视图属性窗口则如图 3-50 所示。 图 3-49 PowerDesigner 10 中视图的属性窗口 图 3-50 PowerDesigner 9.5 中视图的属性窗口 可以看出,PowerDesigner 10 与 PowerDesigner 9.5 在视图方面的区别除了增加了 Code 列,还 在左上方增加了一个【Properties】工具 。 在 PowerDesigner 10 刚才打开的视图属性窗口的 Columns 属性页中选择列列表中的某行(这 里选择列“学号”),双击该行行首箭头,或者点击【Properties】工具,弹出视图属性窗口,如图 3-51 所示。 视图中的列已经成为一个标准的对象,在相应的属性页内,包含 name,code,comment 等属 性,还可以在该窗口中定义数据类型的细节,以及其他相关属性。 作者:姜江 error 188 图 3-51 视图列的属性窗口 3.4.7 在 PDM 中使用抽象数据类型(AbstractDataTypes) 请参考:3.3.3 抽象数据类型(AbstractDataTypes)。 3.4.8 在 PDM 中使用业务规则(BusinessRules) 请参考:3.3.1 业务规则(Business Rules)。 3.4.9 配置表空间和存储 表空间(Tablespace)和存储(Storage)指定了表和索引在数据库或者存储设备上的物理位置。 表空间(Tablespace)和存储(Storage)是数据库相关的,不同的数据库往往使用不同的术语描述 表空间和存储。 表空间和存储这两个名词都是指代存储表和索引的命名的分区。表空间指代数据库中的分区, 而存储则指代存储设备上的一个分区。 有些 DBMS 中,表空间的定义使用已经定义过的存储,例如 Oracle。 定义表空间和存储 PowerDesigner 中的不同的 DBMS 都预定义了一些 DBMS 相关的特殊的关于表空间和存储的 参数。这个参数列表显示了参数的默认值,某些特定的参数,根据 DBMS 推荐的值,预定义了一 个推荐值的列表。 具体的创建定义步骤如下: 1. 选择【Model】→【Tabsespaces】或者选择【Model】→【Storages】,弹出表空间或者存储的 列表(有些 DBMS 没有这些选项,例如,SQL Server 2000 中没有表空间,而 Oracle 包含表空 批注 [e8]: 此处编号错误,已修改 作者:姜江 error 189 间)。如图 3-52 所示。 图 3-52 表空间列表窗口 2. 点击列表中的一个空白行,或者点击【Add a Row】工具 ,新建的行的行首出现一个箭头 3. 输入表空间或者存储的 name 和 code,点击【Apply】按钮应用 4. 选择该行点击【Properties】工具,或者双击该行行首箭头,弹出表空间或者存储属性窗口。 5. 在属性窗口中进入 Options 属性页,如图 3-53 所示。 6. 窗口左方显示 DBMS 相关的表空间和存储的 Syntax 页,选择需要定义的物理选项,点击【Add selected item】工具 ,添加到右侧的 Items 页中 7. 在 Items 属性页中选择添加的 item,定义 item 的值或者默认值,这里可以参考:3.4.2 创建表 (D.表的物理选项)。 图 3-53 为存储定义物理选项 在表空间或存储的属性窗口中,可以进入 Preview 属性页中,可以预览表空间或者存储的生 成代码,例如:create tablespace "Tablespace_1" 表空间和存储的命令的示例 表 3-23 列出了 PowerDesigner 中一些特定的 DBMS 创建表空间的命令的示例。 表 3-23 不同 DBMS 创建表空间以及存储的方式 DBMS 表空间 存储 DB2 CREATE TABLESPACE CREATE STOGROUP 批注 [e9]: 此处错误,已修改 作者:姜江 error 190 DB2 C/S CREATE TABLESPACE 没有这个概念 Oracle CREATE TABLESPACE Storage structure(不是物理存储) Sybase Adaptive SQL Enterprise 没有这个概念 SP/ADDSEGMENT SQL Server 2000 没有这个概念 SP/ADDSEGMENT Sybase Adaptive SQL Anywhere CREATE DBSPACE 没有这个概念 3.5 定义触发器和存储过程 3.5.1 创建触发器 A.触发器的概念和示例 触发器是一种特殊类型的存储过程,是一段和表相关的 SQL。当使用下面的一种或多种数据 修改操作在指定表中对数据进行修改时,触发器会生效:UPDATE、INSERT 或 DELETE。触发器可 以查询其它表,而且可以包含复杂的 SQL 语句。它们主要用于强制复杂的业务规则或要求。例如, 可以控制是否允许基于顾客的当前帐户状态插入定单。 触发器的优点如下:  触发器还有助于强制引用完整性,以便在添加、更新或删除表中的行时保留表之间已定 义的关系。然而,强制引用完整性的最好方法是在相关表中定义主键和外键约束。如果 使用数据库关系图,则可以在表之间创建关系以自动创建外键约束。  触发器是自动的:它们在对表的数据作了任何修改(比如手工输入或者应用程序采取的 操作)之后立即被激活  触发器可以通过数据库中的相关表进行层叠更改。例如,可以在 titles 表的 title_id 列上写入一个删除触发器,以使其它表中的各匹配行采取删除操作。该触发器用 title_id 列作为唯一键,在 titleauthor、sales 及 roysched 表中对各匹配行进行定 位  触发器可以强制限制,这些限制比用 CHECK 约束所定义的更复杂。与 CHECK 约束不同 的是,触发器可以引用其它表中的列。例如,触发器可以回滚试图对价格低于 10 美元 的书(存储在 titles 表中)应用折扣(存储在 discounts 表中)的更新。由于 CHECK 约束只能引用定义了列级或表级约束的列,表间的任何约束(在下例中是指业务规则) 都必须定义为触发器。 手动创建 Trigger 时可以使用 PowerDesigner 中的触发器模板(trigger template),也可以 不是用模板自己定义触发器。 触发器模板是一段可以复用的 SQL 脚本,能够实现引用完整性或者其他和数据库表相关的事 作者:姜江 error 191 情。模板项被插入到触发器模板脚本中或者触发器脚本中。模板相调用相应的 SQL 宏,这些宏能 够实现数据库中表的插入、更新、删除或者错误消息的提示。 例如:当 SQL Sever 中的 titles 表更改时,下例将电子邮件发送给指定的人员 (MaryM): USE pubs IF EXISTS (SELECT name FROM sysobjects WHERE name = 'reminder' AND type = 'TR') DROP TRIGGER reminder GO CREATE TRIGGER reminder ON titles FOR INSERT, UPDATE, DELETE AS EXEC master..xp_sendmail 'MaryM', 'Don’t forget to print a report for the distributors.' GO 下例创建一个触发器,当插入或更新雇员工作级别 (job_lvls) 时,该触发器检查指定雇员 的工作级别(由此决定薪水)是否处于为该工作定义的范围内。若要获得适当的范围,必须引用 jobs 表: =============================================================================== USE pubs IF EXISTS (SELECT name FROM sysobjects WHERE name = 'employee_insupd' AND type = 'TR') DROP TRIGGER employee_insupd GO CREATE TRIGGER employee_insupd ON employee FOR INSERT, UPDATE AS /* Get the range of level for this job type from the jobs table. */ DECLARE @min_lvl tinyint, @max_lvl tinyint, @emp_lvl tinyint, @job_id smallint 作者:姜江 error 192 SELECT @min_lvl = min_lvl, @max_lvl = max_lvl, @emp_lvl = i.job_lvl, @job_id = i.job_id FROM employee e INNER JOIN inserted i ON e.emp_id = i.emp_id JOIN jobs j ON j.job_id = i.job_id IF (@job_id = 1) and (@emp_lvl <> 10) BEGIN RAISERROR ('Job id 1 expects the default level of 10.', 16, 1) ROLLBACK TRANSACTION END ELSE IF NOT (@emp_lvl BETWEEN @min_lvl AND @max_lvl) BEGIN RAISERROR ('The level for job_id:%d should be between %d and %d.', 16, 1, @job_id, @min_lvl, @max_lvl) ROLLBACK TRANSACTION END =============================================================================== 模板项能够包存在当前模型或者当前 DBMS 中。PowerDesigner 中预为每种支持的 DBMS 都预 定义了一些特定的模板项。 B.在 PowerDesigner 9.5 中创建触发器 触发器是一种灵活的用于数据库管理和修改的工具。触发器中还可以包含变量,在触发器生 成的时候,这些变量会被特定模型或者表中的值所代替。下面讲述手动创建触发器的步骤: 1. 双击图形模型中的表,弹出表属性窗口 2. 进入 Triggers 属性页,这里会列出已经为表定义好的触发器 3. 点击空白行,或者点击添加行工具 4. 输入触发器的 name 和 code,和该表触发器的名称必须是唯一的 5. 点击【Apply】按钮应用。双击该行或者选择该行然后点击属性工具 6. 在弹出的窗口中选择 Generate 复选框,生成脚本的时候表示要生成该触发器 7. 进入 Definition 属性页,从触发器模板的下拉列表选择一个触发器模板(trigger template), 如图 3-54 所示。 作者:姜江 error 193 图 3-54 选择触发器模板 该窗口的上方最左边为触发器模板下拉列表,根据自己的需要修改触发器的代码,然后在窗 口上方最右边选择触发器触发的顺序(对该表定义了几个触发器,这里就会出现几个数字)。如果 不希望用触发器模板,则在触发器模板下拉列表中选择,然后选择触发器的类型,并且手 动输入触发器的脚本。 同时你还可以利用 PowerDesigner 提供的插入脚本工具栏中的工具,来插入已经定义好的算 子(Operator)、变量(Variable)、逻辑函数(Function)以及宏(Macros)等。点击之后相应 的脚本就会出现在光标停留的地方。具体的工具包含以下几种,如表 3-24 所示。 表 3-24 触发器编辑窗口不同工具含义 工具 插入的类型 描述 Macro 提供一些能够加快模板项创建定义的宏 Function 提供了 group,number,string,date conversion 和其他的 functions Operator 提供了逻辑算子(例如等号、大于号等) 点击 Preview 属性页,可以预览触发器的脚本,可以看到在 Definition 中的脚本在这里已经 经过了实例化了(instantiated)。例如%TABLE%已经转化为实际的表名称等。 Multiple triggers(多触发器),如果当前的 DBMS 支持的话,可以为任何表创建同一种类型 (同一时间,同一事件)的多个触发器。相同类型的触发器在同样的插入、更新和删除事件发生 的时候调用。 例如:某公司考虑在不同的岗位提供一些新的职位,有一大批候选者,为了确保所有的员工 的薪水范围都在其他在相同领域内工作的人的薪水的范围之内,同时还要确保少于他们的经理的 薪水。这样,就可以在员工表上创建两个 BeforeInsert 触发器,一个是 tibTestSalary1_EMPLOYEE 用于验证建议薪水是否在合理的范围之内,另一个是 tibTestSalary2_EMPLOYEE,用于验证建议 的薪水是否低于经理。 C.自动创建触发器(Rebuilding triggers 重建触发器) 可以为模型中的一个或者多个表自动创建触发器。自动创建索引是为那些定义了引用完整性 作者:姜江 error 194 的 reference,以及那些值依赖于一个 sequence 的列。 那些使用了触发器模板但是修改过的、以及用户定义的触发器在重建触发器(Rebuilding triggers)的时候不在重建的范围之内。所有通过 Rebuilding triggers 创建的触发器都是根据 DBMS 中以及用户定义的触发器模板创建的。被选择的需要自动创建触发器的所有的表都会被创建 一个插入(insert)触发器,而 Update 和 Delete 触发器则根据(定义在父表和子表之间的引用 的)触发器的引用完整性来创建。如果我们切换 DBMS,比如从 SQL Sever 切换到 Oracle,那么我 们定义的额触发器会自动重建。 Delete and rebuild or preserve triggers 重建触发器的时候可以选择以下两种模式: Delete and Rebuild:删除已有的触发器(不包括用户自定义的触发器),然后根据引用完整 性和列的 sequence 实现自动重建 Preserve:保留现有的用户定义好的触发器,然后根据引用完整性和列的 sequence 实现创建其他 的触发器重建(Rebuild)其他的触发器。 用户定义的触发器 如果你的触发器是通过修改触发器模板创建的,这时你想根据相同的触发 器模板创建重建触发器可以采用下面的两种方法:  点击触发器属性窗口的【User-defined】 按钮,这样会自动删除对模板所作的修改, 重新应用了触发器模板  在触发器模板下拉列表选择,此次重建触发器的时候,会自动创建一个应用该触 发器模板的新的触发器。 自动创建触发器的步骤: 1. 选择【Tools】→【Rebuild Objects】→【Rebuild Triggers】,弹出重建触发器的窗口, 如图 3-55 所示。 图 3-55 “Trigger Rebuild”窗口 2. 如果要删除所有现在的应用模板的触发器,然后重建,选择 Delete and Rebuild 单选框 注意:当且仅当和某个表相关联的一个或者多个 reference(引用)在属性窗口中的完整 性属性页中将触发器作为引用完整性的实现(implementation)的时候,才会为该表自动创 作者:姜江 error 195 建触发器。如图 3-56 所示。如果读者发现自己不能够成功的自动创建触发器,可以检查该项 是否选中。 图 3-56 查看引用的实现方式 3. 在 General 属性页中选择希望创建的触发器的复选框。 4. 展开触发器节点,显示出来的是触发器模板 5. 展开触发器模板节点,显示出来的是模板项 6. 选择你希望包含在触发器中的模板项 7. 进入 Selection 属性页,选择希望创建触发器的表,点击【确定】按钮。 创建的过程在 Output 窗口会有信息提示,创建完成之后可以进入表查看属性,也可以通 过触发器列表查看或者修改触发器的属性 3.5.2 使用和创建触发器模板 前面提到在 PowerDesigner 中可以使用触发器模板来创建触发器,这极大的方便了触发器的 创建,可以使用 PowerDesigner 自带的模板,也可以创建自己的模板。每种不同的 DBMS 根据自己 支持的触发器的类型都有各自触发器模板。 触发器模板中包含一些模板项(template item),也可以在触发器模板中使用 PowerDesigner 支持的变量,并且可以将这些变量格式化为某种固定的格式。比如说将变量的值转化为大写或者 小写等等。 触发器模板命名的规范:预定义的触发器模板中已经指明了用于生成触发器脚本的触发器习 惯命名方法。命名规范包括一个说明了触发器类型的前缀,后面追加表的 code。默认的命名规范 包含一个变量(ti_%.L:TABLE%),这将会将最终生成的触发器脚本中的表的 code 转化为小写。例 如,结果脚本可能为 ti_employee。关于脚本的格式化,请参考:3.6.2 脚本创建的选项/对脚 本进行定制(Customizing)中的格式化变量部分 作者:姜江 error 196 改变习惯命名方式的方法如下: 1. 选择【Database】→【Edit Current DBMS】,弹出 DBMS 属性窗口 2. 进入 Trigger Template 属性页 3. 双击其中的一行或者选择某行后点击属性工具 ,弹出触发器模板属性窗口 4. 在 General 属性页中的 Trigger Name 编辑框中修改,例如,修改为 mytempl_%TABLE%, 对触发器进行自动重建后,在表“学生组织”中发现生成了一个名为 mytempl_OrgStudent。 5. 点击【确定】按钮。 创建触发器模板:可以创建两种类型的触发器模板,一种是在当前 DBMS 中创建,它可以在所 有选择当前 DBMS 的模型中使用;另外一种则是在当前模型中创建,仅仅可以在当前模型中使用。 创建触发器模板的方法有两种:一种是重命名并且编辑现有触发器模板的一个拷贝;另一种 是从零开始创建。 使用现有的触发器模板创建 DBMS 触发器模板: 1. 选择【Database】→【Edit Current DBMS】,弹出 DBMS 属性窗口。如果是要创建当前模 型的触发器模板则选择【Model】→【Trigger】→【Trigger Template】,然后进入第 2 步 2. 进入 Trigger Template 属性页,这里列出了当前 DBMS 中的触发器模板的列表 3. 点击【Create From DBMS Trigger Template】工具 ,弹出了一个选择对话框,列出 了当前 DBMS 中可以选择的触发器模板。如果要从头开始创建一个新的触发器模板,则点 击一个空白行,或者点击 或者 添加新的一行,然后跳入第 5 步 4. 选择需要使用的那个模板,点击【确定】按钮 5. 这时就复制了一个触发器模板,修改它的 name 和 code,点击【Apply】按钮应用 6. 双击该行或者选中这行后点击属性工具 ,弹出触发器模板属性窗口 7. 进入 Definition 属性页,在这里修改模板 8. 点击【确定】按钮。 3.5.3 操作模板项(template item) A.模板项简介 模板项是一些定义好的经过命名的脚本块(script block),能够插入触发器脚本或者触发器 中使用。 例如:SQL Server 2000 的触发器模板中有一个模板项 DeleteParentSetNull,它的定义是: ======================================= .FOREACH_CHILD("DELETE SETNULL") 作者:姜江 error 197 /* Set parent code of "[%PQUALIFIER%]%PARENT%" to NULL in child "[%CQUALIFIER%]%CHILD%" */ update [%CQUALIFIER%]%CHILD% set .JOIN("%FK% = NULL", "", ",") from [%CQUALIFIER%]%CHILD% t2, deleted t1 where .JOIN("t2.%FK% = t1.%PK%", "and ") .ENDFOR ======================================= 可以发现,在该模板项中有类似于“.JOIN”的字符串,这些字符串被称为宏,关于宏的含义, 请参考:3.5.5 使用宏(Macros)。那么模板项是如何被插入到触发器或者触发器模板中的呢,我 们来看一个例子,SQL Server 2000 下的一个触发器模板 DeleteTrigger 的定义: ========================================== /* Delete trigger "[%QUALIFIER%]%TRIGGER%" for table "[%QUALIFIER%]%TABLE%" */ create trigger [%QUALIFIER%]%TRIGGER% on [%QUALIFIER%]%TABLE% for delete as begin declare .DeclDeleteParentRestrict .DeclDeleteParentCascade .DeclDeleteParentSetNull .DeclDeleteParentSetDefault @numrows int, @errno int, @errmsg varchar(255) select @numrows = @@rowcount if @numrows = 0 return .DeleteParentRestrict .DeleteParentCascade .DeleteParentSetNull .DeleteParentSetDefault return /* Errors handling */ error: raiserror @errno @errmsg rollback transaction 作者:姜江 error 198 end go ========================================== 可以发现,模板项在触发器模板中显示为一个点后面跟着模板项的名称,我们刚才看到的模 板项 DeleteParentSetNull,在该触发器模板中显示为:“. DeleteParentSetNull”。 PowerDesigner 为它支持的 DBMS 都自带一些使用在触发器模板中的模板项,在重建触发器的 时候可以同时使用预定义的和用户定义的模板项来为选择的表生成触发器脚本。在预定义的触发 器模板中,每个预定义的模板项都对应于一种引用完整性约束。用户可以修改 PowerDesigner 预 定义的模板项,但是不能删除它们或者重命名。 前面提到,重建触发器时,仅仅重建那些已经定义在引用完整性约束的引用相关的表中的触 发器,但是如果是用户字定义的触发器模板,使用了用户定义的模板项,则重建触发器的时候就 总会被创建。 可以为当前模型或者当前使用的 DBMS 创建模板项。 B.PowerDesigner 中预定义的模板项: PowerDesigner 预定义的模板项和具体的 DBMS 有关,下面列出这些预定义的模板项,但是不 是在所有的 DBMS 中都有。 插入约束: 表 3-25 插入约束的触发器模板 模板项 完整性约束 描述 DeclInsertChildParentExis InsertChildParentExist 父记录必须存在 当插入一个子表的记录时,必须有 相应的父表记录存在 DeclInsertTooManyChildren InsertTooManyChildren 不能超过 cardinality 的最大值的约束 不能插入某个子表记录导致达子表 到了 cardinality 的最大值 DeclInsertSequenceColumn InsertSequenceColumn 为列在 sequence 列表 中选择值 为某列从 sequence 列表中选择一 个值 更新约束: 表 3-26 更新约束的触发器模板 模板项 完整性约束 描述 DeclUpdateChildParentExist UpdateChildParentExist 父记录必须存在 当更新一个子表的记录时,必须 有相应的父表记录存在 DeclUpdateChildChangeParent UpdateChildChangeParent 不可以修改父表 在子表中不可以修改父表中列的 code DeclUpdateParentRestrict 对更新的限制 如果子表列存在,则不能修改父 作者:姜江 error 199 UpdateParentRestrict 表 DeclUpdateParentCascade UpdateParentCascade 更新时进行层叠 在所有子表的记录中修改父表的 code DeclUpdateChangeColumn UpdateChangeColumn 不可以修改的列 不能修改列 DeclUpdateParentSetNull UpdateParentSetNull 更新时设置为 null 在所有的子表记录中都将父列的 code 设为 null DeclUpdateParentSetDefault UpdateParentSetDefault 更新时设置为默认值 在所有的子表记录中都将父列的 code 设为默认值 DeclUpdateTooManyChildren UpdateTooManyChildren 不能超过 cardinality 的最大值的约束 不能更新某个子表记录导致子表 达到了 cardinality 的最大值 删除约束: 表 3-27 插入约束的触发器模板 模板项 完整性约束 描述 DeclDeleteParentRestrict DeleteParentRestrict 删除的限制 如果子记录存在,则不能删 除父记录 DeclDeleteParentCascade DeleteParentCascade 删除时进行层叠 对所有子记录删除父表的 code DeclDeleteParentSetNull DeleteParentSetNull 更新时设置为 null 删除父记录是将字记录列设 为 null DeclDeleteParentSetDefault DeleteParentSetDefault 删除时设置为默认值 删除父记录是将字记录列设 为默认值 C.创建模板项 通常情况下,当现有的模板项不适合设计人员的应用时,就有必要创建新的模板项,或者创 建反复执行的代码块用于更新数据库表中所作的工作。 使用现有的模板项创建模板项的步骤如下: 1. 选择【Database】→【Edit Current DBMS】,弹出 DBMS 属性窗口 注意:如果要为当前模型创建模板项,则选择【Model】→【 Triggers】→【 Trigger Template Items】,弹出当前模型中用户定义的触发器模板项的列表窗口。 2. 点击 Trigger Template Items 属性页,该页列出现有的模板项 3. 点击【Create from DBMS trigger item】工具 ,弹出选择对话框,列出了当前 DBMS 中现 有的模板项,如图 3-57 所示。 注:如果要直接创建新的模板项,则在该属性页下方的列表中点击一个空白行,或者点 作者:姜江 error 200 击 或者 ,添加新的一行,然后直接进入第 6 步。 图 3-57 以当前模板项为模板创建模板项 4. 选择你希望从哪个模板项为基础创建自己的模板项,点击【确定】按钮 5. 返回 Trigger Template Items 属性页,这时新创建了一个模板项 6. 输入 name 和 code,点击【Apply】按钮应用。 7. 双击该行,或者点击属性工具 ,弹出模板项属性窗口 8. 进入 Definition 属性页,根据自己的需要进行修改 9. 点击【确定】按钮,最后会弹出一个对话框询问是否保存在当前 DBMS 中,点击【是】 D.在触发器的定义中声明模板项 某些 DBMS 中需要在模板项的名称在脚本中出现之前,为模板项声明一些游标或者变量。可以 是调用相应过程的语句。可以使用这种格式声明一个模板项:Decl template item name。 例如:.DeclInsertChildParentExist 语句声明了模板项:.InsertChildParentExist: ======================================= -- Before insert trigger "[%QUALIFIER%]%TRIGGER%" for table "[%QUALIFIER%]%TABLE%" create trigger [%QUALIFIER%]%TRIGGER% before insert on [%QUALIFIER%]%TABLE% for each row declare integrity_error exception; errno integer; errmsg char(200); dummy integer; found boolean; .DeclInsertChildParentExist begin .InsertChildParentExist 作者:姜江 error 201 -- Errors handling exception when integrity_error then raise_application_error(errno, errmsg); end; / ======================================= 在生成的脚本中, .DeclInsertChildExist 对应于以下定义: ======================================= .FOREACH_PARENT() --Declaration of InsertChildParentExist constraint for the parent "[%PQUALIFIER%]%PARENT%" .DEFINE "CURSOR" "cpk%REFNO%_%.25L:TABLE%" cursor %CURSOR%(.JOIN("var_%.L26:FK% %.L:COLTYPE%", "", ",", ") is") select 1 from [%PQUALIFIER%]%PARENT% where .JOIN("%PK% = var_%.L26:FK%", "and ") and .JOIN("var_%.L26:FK% is not null", "and ", "", ";") .ENDFOR 可以在模板项的属性窗口中,为模板项在 Definition 属性页中定义一个声明语句,在触发器 生成的时候,将会在触发器脚本中自动插入这条声明语句。 3.5.4 定义存储过程和函数(Function) A.存储过程的概念和示例 存储过程是经过预编译的 SQL 与语句的集合,这些语句在一个名称下存储,并作为一个单元 进行处理。这里以 SQL Server 2000 为例,所以使用的存储过程定义语言为 Transact-SQL,而 Oracle 中则为 PL/SQL。存储过程与其它编程语言的过程类似,原因是存储过程可以:  接收输入参数并以输出参数的形式将多个值返回值调用过程或批处理  包含执行数据库操作(包括调用其它过程)的编成语句  向调用过程或批处理返回状态值,以表明成功或者失败(以及失败的原因) 函数:作为单个逻辑单元运行的代码块。函数通过名称来调用,接受可选输入参数,并返回 一个状态和可选的输出参数(许多语言都支持函数,包括 C 语言、Visual Basic 以及 SQL Server 2000 中的 Transact-SQL)。 Transact-SQL 提供内置函数(不能修改),并支持用户定义的函数 (可以由用户自己创建并修改)。 存储过程与函数不同,因为存储过程不返回取代其名称的值,也不能直接用在表达式中。 作者:姜江 error 202 使用存储过程而不适用存储在客户本地计算机的 SQL 语句(SQL Server 2000 中是 Transact -SQL)的优势在于:  允许模块化程序设计 只需创建过程一次并将其存储在数据库中,以后即可在程序中调用该过程任意次。存储 过程可由在数据库编程方面有专长的人员创建,并可独立于程序源代码而单独修改,这 样将有利于变成人员发挥自己的特长,实现良好的分工协作  允许更快执行 如果某操作需要大量 Transact-SQL 代码或需重复执行,存储过程将比 Transact-SQL 批代码的执行要快。将在创建存储过程时对其进行分析和优化,并可在首次执行该过程 后使用该过程的内存中版本。每次运行 Transact-SQL 语句时,都要从客户端重复发送, 并且在 SQL Server 2000 每次执行这些语句时,都要对其进行编译和优化。  较少网络流量 一个需要数百行 Transact-SQL 代码的操作由一条执行过程代码的单独语句就可实现, 而不需要在网络中发送数百行代码。许多任务以一系列 SQL 语句来执行。对前面 SQL 语句的结果所应用的条件逻辑决定后面执行的 SQL 语句。如果将这些 SQL 语句和条件 逻辑写入一个存储过程,它们就成为服务器上一个执行计划的一部分。不必将结果返回 给客户端以应用条件逻辑,所有工作都可以在服务器上完成  可作为安全机制使用 即使对于没有直接执行存储过程中语句的权限的用户,也可授予他们执行该存储过程的 权限 存储过程定义包含两个主要组成部分:过程名称及其参数的说明,以及过程的主体(其中包 含执行过程操作的 Transact-SQL 语句)。 存储过程帮助在不同的应用程序之间实现一致的逻辑。在一个存储过程内,可以设计、编码 和测试执行某个常用任务所需的 SQL 语句和逻辑。之后,每个需要执行该任务的应用程序只须执 行此存储过程即可。将业务逻辑编入单个存储过程还提供了单个控制点,以确保业务规则正确执 行 存储过程还可以使用户不必知道数据库内的表的详细信息。如果一组存储过程支持用户需要 执行的所有业务功能,则用户永远不必直接访问表,他们可以只执行特定的存储过程,这些过程 为他们所熟悉的业务进程建立了模型。 ====================================================================== USE Northwind GO DROP PROCEDURE OrderSummary GO CREATE PROCEDURE OrderSummary @MaxQuantity INT OUTPUT AS 作者:姜江 error 203 -- SELECT to return a result set summarizing -- employee sales. SELECT Ord.EmployeeID, SummSales = SUM(OrDet.UnitPrice * OrDet.Quantity) FROM Orders AS Ord JOIN [Order Details] AS OrDet ON (Ord.OrderID = OrDet.OrderID) GROUP BY Ord.EmployeeID ORDER BY Ord.EmployeeID SELECT @MaxQuantity = MAX(Quantity) FROM [Order Details] RETURN (SELECT SUM(Quantity) FROM [Order Details]) GO ====================================================================== 下面对这个存储过程进行测试 ====================================================================== DECLARE @OrderSum INT DECLARE @LargestOrder INT EXEC @OrderSum = OrderSummary @MaxQuantity = @LargestOrder OUTPUT PRINT 'The size of the largest single order was: ' + CONVERT(CHAR(6), @LargestOrder) PRINT 'The sum of the quantities ordered was: ' + CONVERT(CHAR(6), @OrderSum) GO ====================================================================== 下例执行后的输出结果是: ====================================================================== EmployeeID SummSales ----------- -------------------------- 1 202,143.71 2 177,749.26 3 213,051.30 4 250,187.45 5 75,567.75 6 78,198.10 7 141,295.99 8 133,301.03 9 82,964.00 The size of the largest single order was: 130 The sum of the quantities ordered was: 51317 作者:姜江 error 204 在 SQL Server 2000 中存储过程可以通过以下四种方式返回数据:  输出参数,既可以返回数据(整型值或字符值等),也可以返回游标变量(游标是可以逐 行检索的结果集)。  返回代码,始终是整型值  SELECT 语句的结果集,这些语句包含在该存储过程内或该存储过程所调用的任何其它存 储过程内  可从存储过程外引用的全局游标 可以在 PowerDesigner 中 可 以为 任何 DBMS 定义为它们支持的任何存储过程 和 函数 (function)。 B.在 PowerDesigner 9.5 中创建存储过程 使用模板操作存储过程和函数:可以通过对 DBMS 的修改来修改存储过程和函数的模板。具体 操作步骤如下: 1. 选择【Database】→【Edit Current DBMS】,弹出当前 DBMS 属性的窗口 2. 在当前 DBMS 树中扩展 Script 节点,然后再点开 Object 节点 3. 点开 Procedure 节点 4. 点击【CustomProc】节点可以在右方的 value 编辑框中编辑存储过程模板 点击【CustomFunc】节点可以在右方的 value 编辑框中函数的模板,如图 3-58 所示。 5. 点击【确定】按钮。如果定义好了存储过程,通过进入存储过程的 Preview 属性页就可以发 现生成的脚本也发生了相应的改变。 图 3-58 编辑存储过程模板 创建存储过程和函数:可以使用前面在 DBMS 中定义的存储过程和函数的模板。具体的操作步 骤如下: 1.点击 Palette 工具面板中的【Procedure】 工具,或者在【Model】→【Procedures】 弹出的存储过程窗口中创建。 作者:姜江 error 205 2.在图形模型中的空白区域点击鼠标,会在点击鼠标的位置上出现图符: , 右击鼠标,从而释放 Procedure 工具 3.双击该图符,弹出存储过程或函数的属性窗口 4.在弹出的窗口中输入存储过程或函数的 name 和 code 分别为 student_addrow 5.点击【Apply】按钮应用。 6.进入 Definition 属性页,在下拉列表中选择 Function 或者 Procedure,会在下方的编辑 框中出现定义好的脚本模板,在这里定义我们需要的存储过程或函数 这里我们可以使用 PowerDesigner 事先定义好的算子、变量、函数以及宏,需要时只需要点 击窗口中的相应的工具,然后这些脚本就会插入到光标处,各种工具的用法如表 3-28 所示。 表 3-28 “Definition”页部分工具含义 工具 插入的类型 描述 算子 提供了逻辑算子 函数 提供了 group、number、string、date、conversion 和其他的 函数 变量 提供了可以用在算子或者函数中的变量 宏 提供了能够加快模板项定义创建的宏 7.<可选>进入 Script 属性页,在这里可以为存储过程或脚本定义 begin script 和 end script,可以在脚本中使用%PROC%和%FUNC%等变量 8.点击【确定】按钮。 将存储过程和表相关联:如果当前 DBMS 支持存储过程的化,就可以将一个存储过程和表关联 起来,这个特征允许你更新表或者从该表中取出信息。 例如:一个叫做 student_addrow 的存储过程被关联在表“学生”上,它的目的是用于在该表 中插入一条新记录。 这种关联在模型之间转化的时的应用如下: 当我们将 PDM 转化为 OOM 的时候,和表关联的存储过程最终将转化为生成的类中的 stereotype 为《procedure》的方法,通过定义和表相关的存储过程,可以定义最终生成的 OOM 中的类的操作。 当我们将 OOM 转化为 PDM 的时候,stereotype 为《procedure》的方法最终将转化为和表相 关的存储过程。 具体的操作方法有两种:一种是在存储过程的属性窗口的 General 属性页中下放的 Table 下 拉框中选择相关联的表;另一种是在表的属性窗口进入 Procedures 属性页,选择添加工具,在弹 出的存储过程列表中选择需要和该表关联的存储过程。每个存储过程只能和一张表关联。因此被 选择过的存储过程在该列表中不可见。 作者:姜江 error 206 3.5.5 使用宏(Macros) PowerDesigner 中预先定义好的宏可以被使用在触发器模板、模板项、触发器和存储过程中。 宏可以完成某种特定的功能。 AKCOLN 宏的含义:为表中的每个候选键产生一条语句 语法为:.AKCOLN(“statement”,”prefix”,”suffix”,”last_suffix”,”condition”) 表 3-29 宏 AKCOLN 参数表 参数 描述 Statement 对每列生成的语句 Prefix 每一新行的前缀 Suffix 每一个新行的后缀 Last_suffix 最后一行的后缀 Conditions 候选键码(如果 condition 参数为空,则该宏为表中的每个候选键返回一个声 明) 例如:定义一个和表“学生”关联的触发器,使用了下列宏(在 Definition 属性页 中)message .AKCOLN("'%COLUMN% is an alternate key column'","", "", "", "AK1_idCard"), 其中"AK1_idCard"为我们前面为表“学生”中的字段身份证号码“idCard”定义的候选键的 code 进入 Preview 属性页,我们发现生成了脚本:message 'idCard is an alternate key column'。 将 Definition 中的宏换为:message .AKCOLN("'%COLUMN% is an alternate key column'","", "", "", "AK1_idCard"),也可以得到相同的结果,读者可以试验并体会其中的含义。这里 AKCOLN 仅 仅可以使用变量%COLUMN%。 ALLKCOL 宏的含义:为表中的每个字段产生一条语句 语法为: .ALLCOL("statement","prefix","suffix","last_suffix") 表 3-30 宏 ALLKCOL 参数表 参数 描述 Statement 对每列生成的语句 Prefix 每一新行的前缀 Suffix 每一个新行的后缀 Last_suffix 最后一行的后缀 例如:定义一个和表“学生组织”关联的触发器,使用了下列宏(在 Definition 属性页 中) .ALLCOL("%COLUMN% %COLTYPE%","",",",";")进入 Preview 属性页,我们发现生成了脚本: 作者:姜江 error 207 studentOrgID numeric(6), studentOrgCode char(10), studentOrgName varchar(20), description varchar(50); DEFINE 宏的含义:定义一个变量,并且初始化它的值 语法为: .DEFINE "variable" "value" 表 3-31 宏 DEFINE 参数表 参数 描述 Variable 变量名(不需要%) Value 变量的值(可以通过用%包含另一个变量) 例如:定义一个和表“学生组织”关联的触发器,使用了下列宏(在 Definition 属性页中是 使用) .DEFINE "TRIGGER" "T_%TABLE%" message 'Error: Trigger(%TRIGGER%) of table %TABLE%' 进入 Preview 属性页,我们发现生成了脚本: message 'Error: Trigger(T_studentOrg) of table studentOrg' DEFINEIF 宏的含义:定义一个变量,如果测试值不为空,则初始化它的值 语法为: .DEFINEIF "test_value" "variable" "value" 表 3-32 宏 DEFINEIF 参数表 参数 描述 Test value 要测试的值 Variable 变量名(不需要%) Value 变量的值(可以通过用%包含另一个变量) 例如:为默认数据类型定义一个变量: %DEFAULT% .DEFINEIF "%DEFAULT%" "_DEFLT"" "%DEFAULT%" Add %COLUMN% %DATATYPE% %_DEFLT% ERROR 宏的含义:处理错误 语法为: .ERROR (errno, "errmsg") 作者:姜江 error 208 表 3-33 宏 ERROR 参数表 参数 描述 errno 错误编号 errmsg 错误消息 例如:.ERROR(-20001, "Parent does not exist, cannot insert child") FKCOLN 宏的含义:为表中的每个外健的列产生一条语句 语法为:.FKCOLN(“statement”,”prefix”,”suffix”,”last_suffix”) 表 3-34 宏 FKCOLN 参数表 参数 描述 Statement 对每个外键生成的语句 Prefix 每一新行的前缀 Suffix 每一个新行的后缀 Last_suffix 最后一行的后缀 例如:定义一个和表“学生组织成员”关联的触发器,使用了下列宏(在 Definition 属性页 中) message .FKCOLN("'%COLUMN% is a foreign key column'","",",",";") 进入 Preview 属性页,得到生成脚本如下: message 'studentOrgID is a foreign key column', 'studentID is a foreign key column', 'positionID is a foreign key column'; FOREACH_CHILD 宏的含义:对当前表的每个满足条件的父-子引用都生成一条语句 语法为:.FOREACH_CHILD(“condition”) “statement” .ENDFOR 表 3-35 宏 FOREACH_CHILD 参数表 参数 描述 Statement 每执行一次都生成的语句 Condition 循环执行的条件 其中 condition 包括以下几种:UPDATE RESTRICT(对更新的限制)、UPDATE CASCADE(级连 更新)、 UPDATE SETNULL(更新时设置为 Null)、 UPDATE SETDEFAULT(更新时设置为默认值)、 DELETE RESTRICT(对删除的限制)、DELETE CASCADE(级连删除)、 DELETE SETNULL(删除时设置为 Null)、 DELETE SETDEFAULT(更新时设置为默认值) 批注 [e10]: 该段英文内容已翻译 作者:姜江 error 209 例如:我们定义一个和表“学生”关联的触发器,使用了下列宏(在 Definition 属性页中): .FOREACH_CHILD("DELETE RESTRICT") -- Cannot delete parent "%PARENT%" if children still exist in "%CHILD%" .ENDFOR 进入 Preview 属性页,我们发现生成了脚本(部分): -- Cannot delete parent "student" if children still exist in "OrgStudent" 如果为表“学生组织成员”的触发器中使用这段宏,则不会产生如上脚本,因为没有其他表 的外键指向表“学生组织成员”,也就不存在删除约束(DELETE RESTRICT)了。 FOREACH_COLUMN 宏的含义:对当前表的每个满足条件的列都生成一条语句 语法为:.FOREACH_COLUMN(“condition”) “statement” .ENDFOR 表 3-36 宏 FOREACH_COLUMN 参数表 参数 描述 Statement 对每执行一次都生成的语句 Condition 循环执行的条件 其中,条件包含以下几种:empty(所有的列);PKCOLN(所有的主键);FKCOLN(所有的外键); AKCOLN (所有的候选键);NMFCOL(所有的不可以修改的列,是那些选中了“Cannot Modify” 作为检查参数的列,在列的属性窗口中的 Standard Checks 属性页下面可以选择该项);INCOLN (所有的触发器的列:所有的主键、外键、候选键列)。 例如:定义一个和表“学生”关联的触发器,使用了下列宏(在 Definition 属性页中): .FOREACH_COLUMN("PKCOLN") -- "%COLUMN%" cannot be modified .ENDFOR 进入 Preview 属性页,发现生成了脚本: -- "studentOrgID" cannot be modified FOREACH_PARENT 宏的含义:对当前表的每个满足条件的父-子引用都生成一条语句 语法为:.FOREACH_PARENT(“condition”) “statement” .ENDFOR 表 3-37 宏 FOREACH_PARENT 参数表 参数 描述 Statement 对每执行一次都生成的语句 批注 [e11]: 此处内容已经补充完整 作者:姜江 error 210 Condition 循环执行的条件 其中 condition 包括以下几种:empty(所有的引用);FKNULL ( 可 为 空 的 外 键 ); FKNOTNULL(不可为空的外键);FKCANTCHG(不可以修改的外键) 例如:定义一个和表“学生组织成员”关联的触发器,使用了下列宏(在 Definition 属性页 中): .FOREACH_PARENT("") -- Cannot modify parent code of "%PARENT%" in child "%CHILD%" .ENDFOR 进入 Preview 属性页,我们发现生成了脚本(部分): -- Cannot modify parent code of "student" in child "OrgStudent" 如果是表“学生”的触发器中使用这段宏,则不会产生如上脚本,因为该表不存在外键指向 其他表,也就不存在这种约束了。 INCOLN 宏的含义:为表中的每个主键、外健、候选键和不可修改的列产生一条语句 语法为:.INCOLN(“statement”,”prefix”,”suffix”,”last_suffix”) 表 3-38 宏 INCOLN 参数表 参数 描述 Statement 对每个列生成的语句 Prefix 每一新行的前缀 Suffix 每一个新行的后缀 Last_suffix 最后一行的后缀 例如:定义一个和表“学生”关联的触发器,使用了下列宏(在 Definition 属性页 中) :.INCOLN("%COLUMN% %COLTYPE%","",",",";") 进入 Preview 属性页,我们发现生成了脚本: studentID int, idCard varchar(20), classID int; 根据我们前面对该表的定义,我们发现 studenID 为该表的主键;idCard 是候选键;classID 为外键。 JOIN 宏的含义:为引用中的“一对列”(父表与子表的两个列)产生一条语句 语法为:.JOIN(“statement”,”prefix”,”suffix”,”last_suffix”) 表 3-39 宏 JOIN 参数表 批注 [e12]: 此处内容已经补充完整 作者:姜江 error 211 参数 描述 Statement 对每个这样的列生成的语句 Prefix 每一新行的前缀 Suffix 每一个新行的后缀 Last_suffix 最后一行的后缀 例如:定义一个和表“学生”关联的触发器,使用了下列宏(在 Definition 属性页中) : .FOREACH_CHILD("") -- .JOIN("%PK%=%FK%", " and", "", ";") .ENDFOR 进入 Preview 属性页,我们发现生成了脚本: -- studentID=studentID; NMFCOL 宏的含义:为表中每一个不可以修改的列产生一条语句,这些列是那些选中了“Cannot Modify” 作为检查参数的列(列的属性窗口中的 Standard Checks 属性页下面可以选择该项) 语法为:. NMFCOL("statement","prefix","suffix","last_suffix") 表 3-40 宏 NMFCOL 参数表 参数 描述 Statement 对每个不可以修改的列生成的语句 Prefix 每一新行的前缀 Suffix 每一个新行的后缀 Last_suffix 最后一行的后缀 例如:先分别定义“学生”表中的“学号”、“身份证号”、“性别”为不可以修改的列,然后 定义一个和表“学生”关联的触发器,使用了下列宏(在 Definition 属性页中) : .NMFCOL("%COLUMN% %COLTYPE%","",",",";") 进入 Preview 属性页,我们发现生成了脚本: studentID int, idCard varchar(20), gender bit; PKCOLN 宏的含义:为表中的每个主键列产生一条语句 语法为:. PKCOLN("statement","prefix","suffix","last_suffix") 表 3-41 宏 PKCOLN 参数表 参数 描述 批注 [e13]: 此处已修改,并添加了 “„生成了脚本”至“ NMFCOL”之 间的内容 作者:姜江 error 212 Statement 对每个主键生成的语句 Prefix 每一新行的前缀 Suffix 每一个新行的后缀 Last_suffix 最后一行的后缀 例如:定义一个和表“职务”关联的触发器,使用了下列宏(在 Definition 属性页中) : message .PKCOLN("'%COLUMN% is a primary key column'","",",",";") 进入 Preview 属性页,我们发现生成了脚本: message 'positionID is a primary key column'; CLIENTEXPRESSION and SERVEREXPRESSION 宏的含义:在触发器模板、模板项、存储过程的脚本中使用业务规则服务器端或者客户端的表达 式(expression)。 语法为:.CLIENTEXPRESSION(业务规则的代码) .SERVEREXPRESSION(业务规则的代码) 例如:我们创建一个名称为 ACTIVITY_DATE_CONTROL,它的 Server 端的 Expression 为 : activity.begindate < activity.enddate 然后在创建一个和表“学生”关联的触发器,使用了下列宏(在 Definition 属性页 中) :.SERVEREXPRESSION(ACTIVITY_DATE_CONTROL) 进入 Preview 属性页,我们发现生成了脚本:activity.begindate < activity.enddate 3.5.6 生成触发器和存储过程脚本(SQL 脚本) 在 PowerDesigner 的 PDM 模型中,我们创建的触发器和存储过程都可以直接使用脚本或者通 过 ODBC 创建,或者通过脚本和 ODBC 对数据库中的触发器和存储过程进行修改。 A.定义存储过程的生成的次序 可以使用扩展依赖(ExtentedDependency)定义存储过程生成的先后次序。扩展依赖是 PDM 中对象的自由连接。这些连接能够使得对象之间的关系更加清楚。通常这些关系不被 PowerDesigner 解释或者检查,因为他们住的目的是生成文档。但是,如果你规定视图之间的扩 展依赖的 stereotype 为《DBCreateAfter》,生成数据库脚本的时候会被分析。 如果你创建了一个自反的、循环的 stereotype 为《DBCreateAfter》的扩展依赖,在检查模 型的时候会提示错误。如果你选择忽略该错误,视图将会以字母顺序创建,如果不考虑生成顺序, 那么生成视图的时候往往会导致错误。 例如:一个出版商希望如果客户的订单金额大于一万美金,那么对于某些书籍就可以给 15% 的折扣。我们创建两个存储过程:第一个存储过程为 GeneralCheck,用于检查书是否缺货、订单 金额、是否打折以及下订单;另一个存储过程为 DiscountCalc,用于计算 15%的折扣,第一个存 储过程会调用它。这样,很显然 DiscountCalc 就必须在 GeneralCheck 之前创建,但是如果按照 作者:姜江 error 213 默认的创建方式的话就会按照字母方式创建,这显然会出问题。因此我们可以在这两个存储过程 之间创建扩展依赖,使得第二个存储过程在第一个之前产生。具体操作办法如下: 1. 选择 Palette 面板,选择 Link/ExtendedDependency 工具 2. 连接两个存储过程,使得第一个存储过程指向第二个存储过程 3. 在图形模型中双击存储过程 GeneralCheck,弹出存储过程属性窗口 4. 进入 Extended Dependencies 属性页,在 stereotype 列选择 DBCreateAfter,点击【确定】 按钮即可 5. 或者点击添加工具 ,在弹出的对话框中选择适当的对象(存储过程等),然后在 stereotype 中选择 DBCreateAfter B.生成存储过程和触发器 具体的操作步骤如下: 1. 选择【Select】→【Database】→【Generate Triggers and Procedures】,或者按快捷键 【Ctrl+Shift+P】,弹出生成触发器和存储过程对话框,如图 3-59 所示。 图 3-59 生成存储过程和触发器设置窗口 2. 选择 Script generation,表示生成脚本,选择文件保存路径,输入文件名称 如上图 3-59 所示,在 Triggers & Procedures 属性页中,有相应的选框。在 Triggers 部 分,Drop trigger 表示在生成触发器之前先将同名的触发器删除,下面的 Trigger Filters 处可 以选择生成哪几种类型的触发器;在 Procedure 部分可以选择是否要 Drop procedure,以及是否 要在生成存储过程的时候生成 permission。 3. 进入 Options 属性页,对脚本生成的选项进行定制 在 Text 区域可以定制生成脚本的格式,如编码的格式,大小写等;在 Usage 区域可以定制是 否要添加用户前缀或者数据库作为前缀;同时,还可以选择是否要在生成触发器和存储过程前检 作者:姜江 error 214 查模型,生成后是否对模型自动存档。 4. 点击 Selection 属性页,选择要对哪个模型和包生成触发器和存储过程,如果要对某个用户 生成触发器或者存储过程也可以在上方选择用户。在 Trigger 子属性页中选择要对哪些表产 生触发器,在 Procedures 属性页中选择要生成的存储过程 5. 点击【确定】按钮,生成的过程信息会在 Output 窗口中显示 如果要直接在数据库中生成触发器和存储过程,可以在生成窗口中选择 ODBC Generation, 但是要先定义好 ODBC 数据源,定义的方法参考:3.8.1 定义 ODBC 数据源。 ,创建好之后通过【Database】→【Connect】连接,如果没有连接,那么在生成之前会弹出对话 框提示选择数据源,输入用户名和密码。 C.创建并生成用户定义的错误消息(error message) 用户可以自己创建错误消息,这些错误消息将存储在用户定义的一个错误消息的表中,当你 选择触发器生成参数的时候,可以选择从这个表中选择产生一个错误消息。在生成的触发器脚本 中,这种错误消息是通过 SELECT 命令选择出来的。如果脚本中的错误号(error number)和表中 的错误号的值相同,那么标准的错误消息就被表中定义的错误消息取代。 创建消息表的步骤: 1. 创建一个表结构(error number,message text)的表,如图 3-60 所示。 图 3-60 创建消息表 2. 在该表的 Preview 属性页中将脚本拷贝,在 SQL Analyzer 中执行,创建该表 3. 选择【Database】→【Execute SQL】,或者按快捷键【Ctrl+Shift+E】,弹出连接数据源对话 框,选择数据源,输入用户名和密码,点击【Connect】工具连接(若已经连接,则不会弹出 该窗口) 4. 如果连接正确,弹出 Execute SQL Query 窗口 5. 在窗口编辑框中输入插入语句在错误信息表中插入记录: insert into errorMessage values(1004,’The value that you are trying to insert does not exist in the referenced table’) 6. 点击【Run】,若执行成功,下方的消息框会提示 7. 点击【Close】关闭 生成用户定义的错误消息的步骤: 1. 选择【Tools】→【Rebuild Objects】→【Rebuild Triggers】,弹出重建触发器对话框 2. 点击 Error Messages 属性页,选择【User-defined】单选框 3. 在 Message table name 编辑框中输入包含错误消息的表名称 4. 在 Message numbecolumn 编辑框中输入包含 error number 的列的名称 作者:姜江 error 215 5. 在 Message text column 编辑框中输入和 error message 对应的列的名称,如图 3-61 所示。 图 3-61 定义错误消息 6. 点击 General 属性页,选择创建触发器的类型以及创建的模式 7. 在 Selection 属性页中选择为哪些表创建触发器 8. 点击【确定】按钮。 9. 选择【Database】→【General Triggers and Procedures】,选择表“学生”,生成触发器脚 本如下: ======================================= /*==============================================================*/ /* Database name: test1 */ /* DBMS name: Microsoft SQL Server 2000 */ /* Created on: 2003-11-20 20:05:43 */ /*==============================================================*/ if exists (select 1 from sysobjects where id = object_id('tu_student') and type = 'TR') drop trigger tu_student go if exists (select 1 from sysobjects where id = object_id('td_student') and type = 'TR') drop trigger td_student go /* Update trigger "tu_student" for table "student" */ create trigger tu_student on student for update as 作者:姜江 error 216 begin declare @numrows int, @numnull int, @errno int, @errmsg varchar(255) select @numrows = @@rowcount if @numrows = 0 return /* Non modifiable column "idCard" cannot be modified */ if update(idCard) if exists (select 1 from inserted i, deleted d where i.idCard != d.idCard) begin select @errno = 50001,@errmsg = message from errorMessage where errorNo = 50001 goto error end /* Non modifiable column "gender" cannot be modified */ if update(gender) if exists (select 1 from inserted i, deleted d where i.gender != d.gender) begin select @errno = 50001, @errmsg = message from errorMessage where errorNo = 50001 goto error end /* Cannot modify parent code in "student" if children still exist in "OrgStudent"*/ if update(studentID) begin if exists (select 1 from OrgStudent t2, inserted i1, deleted d1 where t2.studentID = d1.studentID 作者:姜江 error 217 and (i1.studentID != d1.studentID)) begin select @errno = 50005, @errmsg = message from errorMessage where errorNo = 50005 goto error end end return /* Errors handling */ error: raiserror @errno @errmsg rollback transaction end go /* Delete trigger "td_student" for table "student" */ create trigger td_student on student for delete as begin declare @numrows int, @errno int, @errmsg varchar(255) select @numrows = @@rowcount if @numrows = 0 return /* Cannot delete parent "student" if children still exist in "OrgStudent" */ if exists (select 1 from OrgStudent t2, deleted t1 138 9189 2382 where t2.studentID = t1.studentID) begin select @errno = 50006,@errmsg = message from errorMessage where errorNo = 50006 goto error end return /* Errors handling */ 作者:姜江 error 218 error: raiserror @errno @errmsg rollback transaction end go ======================================= 3.6 使用 PowerDesigner 创建数据库生成脚本(SQL 脚本) 3.6.1 生成数据库 假设我们的数据库已经建立(鉴于我们的学习目的是掌握如何生成数据库,我们这里的模型 尽可能简单,关于数据库的设计思想,可以参考相关的书籍),如图 3-62 所示。 图 3-62 生成数据库脚本模型实例 现在我们使用该模型生成数据库,以 SQL Server 2000 为例 1.选择【Database】→【Generate Database】或者按快捷键【Ctrl+G】,弹出窗口,如 图 3-63 所示。 图 3-63 “Database Generation”窗口 2. 在 Generation 出选择单选框 Script generation(生成数据库 SQL 脚本),然后在 Directory 出填写脚本存放目录,以及在 File 处规定生成脚本的名称;选中 One file only,否 则,会对每个不同的表格都单独生成一个脚本文件 作者:姜江 error 219 3.在 SQL Server 2000 中创建一个数据库命名为 TEST 4.点击该窗口的 Selection 属性页,PowerDesigner 会自动列出当前模型中包含的各种元素 (在我们当前的模型中仅仅包含 3 个 table),根据需要选择自己需要生成到数据库的表 5.点击【确定】按钮,默认情况下,PowerDesigner 9.5 会自动先对模型的正确性进行检查, 我们将在 ResultList 窗口中看到如图 3-64 所示图形: 图 3-64 生成脚本前模型检查结果 我们将在后面的章节中学习如何对模型进行验证和检查,以及如何利用 PowerDesigner 提供 的各种方便的功能进行纠错,这里就不再赘述。 紧接着 PowerDesigner 生成数据库,这时,我们将会在 OutPut 窗口中看到数据库生成的过程, 如图 3-65 所示。 图 3-65 生成数据库过程显示 随后,在生成结束后的窗口中,选择 Edit 来查看或者编辑生成的 SQL 脚本: ====================================================================== /*==============================================================*/ /* Database name: test */ /* DBMS name: Microsoft SQL Server 2000 */ /* Created on: 2003-11-7 13:26:42 */ /*==============================================================*/ alter table class drop constraint FK_Class_Teacher go alter table student drop constraint FK_Student_Class go if exists (select 1 from sysobjects where id = object_id('class') 作者:姜江 error 220 and type = 'U') drop table class go if exists (select 1 from sysobjects where id = object_id('student') and type = 'U') drop table student go if exists (select 1 from sysobjects where id = object_id('teacher') and type = 'U') drop table teacher go /*==============================================================*/ /* Table: class */ /*==============================================================*/ create table class ( classID int not null, className varchar(20) not null, teacherInCharge int null, description varchar(50) null, constraint PK_CLASS primary key (classID) ) go /*==============================================================*/ /* Table: student */ /*==============================================================*/ create table student ( studentID int not null, 班级编号 int null, name varchar(20) not null, gender bit not null, email varchar(50) null, 作者:姜江 error 221 mobile char(11) null, phone varchar(15) null, address varchar(50) null, description varchar(50) null, constraint PK_STUDENT primary key (studentID) ) go /*==============================================================*/ /* Table: teacher */ /*==============================================================*/ create table teacher ( teacherID int not null, name varchar(20) not null, gender bit not null, email varchar(50) null, mobile char(11) null, phone varchar(15) null, address varchar(50) null, description varchar(50) null, constraint PK_TEACHER primary key (teacherID) ) go alter table class add constraint FK_Class_Teacher foreign key (teacherInCharge) references teacher (teacherID) go alter table student add constraint FK_Student_Class foreign key (班级编号) references class (classID) go ====================================================================== 接下来,分析这一段 SQL 脚本,总的来说,这段脚本分为以下几个部分: 1.先 drop 外键,这样式为了保证后面 drop table 的成功(如果存在表之间的外键约束关系, 那么删除表的时候 DBMS 会报错) 2.检查数据库中是否已经存在同名的表,如果有则自动删除 作者:姜江 error 222 3.根据模型创建表 4.建立各个表之间按的外键约束关系 然后,使用 Sql Analyzer(SQL 查询分析器)登陆到刚才建立的数据库 TEST 下,把这段脚 本拷贝到查询分析器的脚本窗口中,点击执行查询 或者按快捷键【F5】,执行该脚本,会发现 在下面的消息窗口有以下错误信息出现: ------------------------------------------------------------------------------------ 服务器: 消息 4902,级别 16,状态 1,行 6 无法更改表 'class',因为数据库 'TEST' 中不存在此表。 服务器: 消息 4902,级别 16,状态 1,行 1 无法更改表 'student' ,因为数据库 'TEST' 中不存在此表。 ------------------------------------------------------------------------------------ 这是因为前面提到,在数据库表还没有建立的时候,PowerDesigner 生成的脚本为了解决重新 建表的问题而先试图将表之间的外键关系删除,所以 SQL Server 2000 自然会报错,提示表这个 时候不存在。 第一次执行这个脚本的时候,数据库会报错,细心的读着会发现,每一段代码的后面都跟着 一个“go”,这表示即使前面的代码没有执行成功,后面的代码还会继续往下执行,他们是分段的, 彼此无关的代码。因此,后边的创建表以及建立外键关系的脚本仍然可以正确执行。 所以,当再次执行这个脚本一次或者 n 次的时候,就会发现 SQL Server 2000 不会再报错, 那是因为当我们再次执行脚本的时候,前面出错的条件已经不复存在,数据库中的相关的表和外 键已经在第一次建立,所以对他们的相关操作就不会再次出错了。 生成窗口参数的含义 关于 Database Generation 窗口中个选项的含义,下面将着重介绍(本小节剩余部分几张图 形均为 PowerDesigner 10 中的截图,可能会与 PowerDesigner 9.5 中的不尽相同,读者可自行比 较,这里不再赘述)。 如图 3-66 所示,为表和视图的相关参数的定义页面,关于表、视图以及列生成脚本的相关参 数,如表 3-42 所示。 表 3-42 生成窗口“Tables & Views”页部分选项含义 参数 含义 Create Table 生成表 Check 表的检查参数以及约束性规则(inside 和 outside 分别表示该 语句是包括在建表语句内部还是外部)(Table 和 Column 都包 含该参数) Physical options 是否生成和物理选项相关的脚本(View 和 Table 都包含该参 数) 作者:姜江 error 223 Begin script/End script 语句前面或者后面插入预先定制好的脚本(View 和 Table 都有) Drop table 建表前检查库中是否有同名的表,如果有删除该表 Comment 生成表的注释(View 和 Table 以及 Column 都包含该参数) Permission 生成 Permission 相关的脚本(View 和 Table 都包含该参数) Create default/Drop default 指明列的默认值/创建前删除存在的默认值 User-defined type 生成创建用户自定义类型的脚本 Create View 生成视图 Drop View 建视图前检查库中是否有同名的视图,如果有删除该视图 图 3-66 生成数据库窗口的“Table & View”页 Key&Indexes 页用于定义键以索引生成脚本的相关参数,如图 3-67 所示,个参数的含义如表 表 3-43 所示。 表 3-43 生成窗口“Key & Indexes”页部分选项含义 参数 含义 Create primary key 生成主键(inside 和 outside 分别表示在建表语句表内或者外建) Physical options 生成物理选项(主键、后选键和索引都包含该选项) Comment 生成注释(主键、索引以及外键、后选键都包含该选项) Drop primary key 生成主键之前删除原来的相同的主键 Create alternate key 生成后选键(inside 和 outside 分别表示在建表语句表内或者外 建) Drop alternate key 生成侯选键之前删除原来的相同的侯选键 作者:姜江 error 224 Create index/Drop index 创建索引/创建之前删除相同索引 Index filter 要创建的索引类型(Primary key、Foreign key、Alternate key、Cluster 以及其他) Create foreign key 生成外键(inside 和 outside 分别表示在建表语句表内或者外建) Drop foreign key 生成外之前删除原来的相同的外键 Declarative integrity 生成参照完整性约束(可进一步设置 Create join index / drop join index 创建连接索引/创建之前删除相同的连接索引 图 3-67 生成数据库窗口的“Key & Indexes”页 在 Database 页设置生成数据库的参数,如图 3-68 所示,各参数的含义如表 3-44 所示。 表 3-44 生成窗口“Database”页部分选项含义 参数 含义 Create database/Drop database 创建数据库/创建数据库前先删除数据库 Begin script/End script 创建数据库语句的前面或者后面插入预先定制好的脚本 (Tablespace 表空间也包含该参数) Physical options 生成数据库的物理选项 Open database/Close database 打开数据库/关闭数据库 Create storage/drop storage 生成存储/生成存储前删除原存储 Comments 生成注释(Sequence、Rules、User-defined data types、 Table space、Storage、Abstract data types 包含该项) 作者:姜江 error 225 Create tablespace/drop tablespace 生成表空间/生成表空间前删除原表空间 Create rule/drop rule 生成规则/生成规则前删除原规则 Create data type/Drop data type 生成数据类型/生成之前先删除原数据类型(用户自定 义数据类型 User-defined data type 和抽象数据类型 Abstract data type 都包含该参数) User-defined data type (Default value、Check) 是否为用户自定义数据类型生成默认值、生成检查以及 有效性参数 Install java class / remove java class 安装 Java 类/安装 Java 类之前先删除原 Java 类 Permission 生成和抽象数据类型的许可脚本 图 3-68 生成数据库窗口的“Database”页 Options 页中可以设置脚本的参数,如图 3-69 所示,主要参数含义如表 3-45 所示。 表 3-45 生成窗口“Options”页部分选项含义 参数 含义 Check model(Before generation) 生成数据库之前,先检查模型,如果模型有错误,则停 止生成数据库 Script preview(Before generation) 生成数据库之前,先预览生成数据库的脚本 Automatic archive 生成数据库自动存档(apm 文件) Generate name in empty comment 如果注释为空,则用 name 替换为注释(关于注释,请参 考 7.11 问题十一) 作者:姜江 error 226 图 3-69 生成数据库窗口的“Options”页 3.6.2 脚本创建的选项/对脚本进行定制(Customizing) 在这一节中,将学习如何通过创建数据库的选项对数据库生成脚本进行定制,以及根据不同 情况选择不同的生成组合,尽可能的使得生成的脚本能够一次性执行成功。 前面提到,PowerDesigner 默认生成的脚本在 SQL Server 2000 中第一次执行的时候会出现 错误,下面将通过脚本定制解决这一问题: 图 3-70 生成脚本的不同选项 如图 3-70 所示。这几张图分别从 Table & Views/Keys & Indexes/Database 几个属性页 中截取出来的,我们先看 Foreign key 这张图,发现 PowerDesigner 默认是选中 Drop foreign key 的,这也就是我们生成的脚本第一段总是 drop 外键关系的原因,也是在 SQL Server 2000 中第 一次执行的时候宗会报错的原因。此外,还可以在这里选择是否要创建外键,以及是在表内创建 还是表的外部创建(默认是 Outside) 我们再来看一下 Tables 这张图,同样可以看到 Drop table 默认是选中的,这也就是为什么 作者:姜江 error 227 在 SQL Server 2000 中第一次以后的执行都没有问题的原因,在建表之前检查是否有同名的表, 有则自动删除。 下面我们再来看几个例子,进一步学习定制脚本。 A. 数据库的 Begin Scripts/End Scripts 在数据库生成之前和数据库生成之后加入相应的 脚本(Begin Scripts/End Scripts)。可以在这些脚本中使用如表 3-46 所示系统变量。 表 3-46 数据库的 Begin Scripts 和 End Scripts 中可以使用的系统变量 变量 含义 %DATABASE% 当前物理数据模型的名称 %DATE% 脚本生成的日期 %DBMSNAME% 目标数据库的 DBMS 的名称 %NAMESCRIPT% 脚本文件的文件名 %PATHSCRIPT% 脚本文件名以及文件的路径 %STARTCMD% 执行脚本的命令 %AUTHOR% 当前模型的作者 1. 选择【Model】→【Model Properties】或者右键图形模型中的空白部分,在弹出的菜单 中选择属性(Properties),如图 3-71 所示。 图 3-71 模型属性窗口 2. 输入作者和版本名称,然后点击 Database 的新建 按钮,会弹出一个确认窗口,询问 你是否确认要新建数据库脚本对象。点击【确定】按钮。 3. 在接下来的窗口的 General 属性页中输入该脚本的 name 和 code 4. 在 Script 属性页中可以分别输入 Begin Script 和 End Script,然后可以通过 Preview 进行预览脚本 作者:姜江 error 228 B. 表的 Begin Scripts/End Scripts 在表生成之前和数据库生成之后加入相应的脚本 (Begin Scripts/End Scripts)。可以在这些脚本中使用如表 3-47 所示系统变量。 表 3-47 表的 Begin Scripts 和 End Scripts 中可以使用的系统变量 变量 含义 %COLNLIST% 列的列表 %DATABASE% 当前物理数据模型的名称 %DATE% 脚本生成的日期 %DBMSNAME% 目标数据库的 DBMS 的名称 %NAMESCRIPT% 脚本文件的文件名 %OWNER% 表的所有者 %OWNERPREFIX% 表的所有者的称谓(如 Mr. Sir. Dr.等) %PATHSCRIPT% 脚本文件名以及文件的路径 %STARTCMD% 执行脚本的命令 %TABLE% 表的 name 或者 code(根据显示 name 还是 code 而定) %TCODE% 当前表的 code %TLABL% 当前表的 label %TNAME% 当前表的 name %AUTHOR% 当前模型的作者 C. 定制脚本是对系统变量进行格式化(formatting) 表 3-48 格式化变量的代码 格式化代码 作用 .L 将所有字符小写化 .T 删除空格 .U 所有字符大写化 .n 字符串的最大长度 .J 字符串的固定长度 我们对变量进行格式化的格式:%.format:variable%,例如:%.L:TABLE% 相信读者通过前面几个的学习应该能够掌握如何对其他的相关内容进行详细的定制,这里就 不再一一赘述。 3.6.3 产生数据库创建脚本(针对不同数据库) 前面的建模都是以 MS SQL Server 2000 为例,假如后来发现 MS SQL Server 2000 不适合我 作者:姜江 error 229 们的应用,而需要切换数据库成 MySQL 怎么办呢?传统落后的方法往往在建库的时候直接在各种 工具提供的相关的 GUI 中直接完成建库工作,当需要改变数据库时,往往不得不在新的 DBMS 中重 新输入相关的表和列的定义。 此外,由于各种 DBMS 之间的数据类型有时候有很大的不同,而数据库设计人员也不可能对所 有数据库的特点都十分精通。 有时候,建库人员利用第三方工具(有些 freeware 可以做到这一点)从数据库中直接生成建 库脚本,但是这些不同的 DBMS 的脚本之间也不尽相同,比如说 Oracle 使用 PL/SQL,而 MS SQL Server 2000 中则是 Transact-SQL 因此,在数据库的迁移工程中往往会遇到前所未有的困难。为了保证数据能够在不同库之间 顺利迁移,不得不很大的牺牲做很多细致繁琐的调整工作,这些困难都使得同构数据库的重建任 务非常繁重,更不用说另大多数数据库人员头痛的异构数据库迁移了。 而在 PowerDesigner 中可以非常方便的实现同构数据库在不同的 DBMS 之间切换。 选择 Database-Change Current DBMS,将 Microsoft SQL Server 2000 改变为我们需要的 DBMS,假设是 Oracel9i,如图 3-72 所示。 图 3-72 选择要切换的 DBMS 类型 在 DBMS Preserver Options 属性页中,你可以规定当不同的 DBMS 之间切换时,哪数据库对 象(Table,index,stored procedure 等等)需要保留下来,哪些数据库对象忽略。 切换为 Oracle9i 后点击【确定】按钮,可以立即发现图形模型发生了相应的改变,例如:性 别的字段类型在 SQL Server 2000 中为 bit 型,而在 Oracle9i 中则为 Boolean 型,如图 3-73 所 示。 图 3-73 切换 DBMS 后的模型 作者:姜江 error 230 同样,在此基础上对数据库进行修改或者定义就会发现,相关的很多东西都发生了变化,比 如说 SQL Server 2000 中的 Identity 在 Oracle9i 中就变成了 Sequence。改变数据库以后,我们 再次生成数据库,可以观察到在 Database Generation 的窗口的各个属性页中的选项也发生了相 应的变化,我们在 Tables & Views 属性页中选中 Comment(在 SQL Server 2000 的情况下为灰 化不可以选择),然后确定,读者可以对比生成的数据库脚本的不同之处: ====================================================================== /*==============================================================*/ /* Database name: test1 */ /* DBMS name: ORACLE Version 9i */ /* Created on: 2003-11-7 15:56:44 */ /*==============================================================*/ alter table "class" drop constraint "FK_Class_Teacher" / alter table "student" drop constraint "FK_Student_Class" / drop table "class" cascade constraints / drop table "student" cascade constraints / drop table "teacher" cascade constraints / /*==============================================================*/ /* Database: "test1" */ /*==============================================================*/ create database "test1" / /*==============================================================*/ /* Table: "class" */ /*==============================================================*/ create table "class" ( "classID" INTEGER not null, "className" VARCHAR2(20) not null, "teacherInCharge" INTEGER, 作者:姜江 error 231 "description" VARCHAR2(50), constraint PK_CLASS primary key ("classID") ) / comment on table "class" is '班级的编号例子:管理信息系统 9812 班' / /*==============================================================*/ /* Table: "student" */ /*==============================================================*/ create table "student" ( "studentID" INTEGER not null, "classID" INTEGER, "name" VARCHAR2(20) not null, "gender" BOOLEAN not null, "email" VARCHAR2(50), "mobile" CHAR(11), "phone" VARCHAR2(15), "address" VARCHAR2(50), "description" VARCHAR2(50), constraint PK_STUDENT primary key ("studentID") ) / comment on table "student" is '这里是一些关于学生的备注 / /*==============================================================*/ /* Table: "teacher" */ /*==============================================================*/ create table "teacher" ( "teacherID" INTEGER not null, "name" VARCHAR2(20) not null, "gender" BOOLEAN not null, "email" VARCHAR2(50), "mobile" CHAR(11), 作者:姜江 error 232 "phone" VARCHAR2(15), "address" VARCHAR2(50), "description" VARCHAR2(50), constraint PK_TEACHER primary key ("teacherID") ) / comment on table "teacher" is '他们是人民的好教师' / alter table "class" add constraint "FK_Class_Teacher" foreign key ("teacherInCharge") references "teacher" ("teacherID") / alter table "student" add constraint "FK_Student_Class" foreign key ("classID") references "class" ("classID") / ====================================================================== 3.6.4 使用 ODBC 创建 使用 ODBC 创建数据库的步骤如下: 1. 选择【Database】→【Configure Connections】 或者【控制面板】→【管理工具】→【数 据源(ODBC)】或者在【开始】→【运行】→【odbcad32】,打开配置 ODBC 的窗口 2. 定义一个 ODBC 数据源,选择我们刚刚创建好的 SQL Server 2000 的数据库 test,数据源名称 也为 test,填写正确的用户名和密码。如图 3-74 所示。 3. 选择【Database】→【Connect】,选择前面定义好的数据源,输入用户名和密码。 图 3-74 选择连接的数据源 作者:姜江 error 233 4. 选择 Database-Generate Database 选择 ODBC Generation,弹出窗口,如图 3-75 所示。 图 3-75 “Execute SQL Query”窗口 5. 点击右上角【Run】 或者直接按快捷键【F5】,这时同样会弹出来一个错误提示窗口,如图 3-76 所示。 图 3-76 脚本执行错误提示对话框 6. 实际上这个错误就是前面在 SQL Server 2000 查询分析器中遇到的那个问题,但是,这里的 错误信息只提示有错误,不够明确,所以笔者建议数据库的脚本最好在 DBMS 自带的具有调试 功能的 GUI 工具中执行,便于调试和调整。 7. 去掉前面的两个 drop 外键关系的语句,再次执行,则数据库生成脚本执行顺利。 注:关于 ODBC 的其他操作,请参考:3.8 反向工程/对数据库进行修改及其应用。 3.7 生成数据库测试数据 很久以前,在笔者还在读本科的时候,和几个朋友当时参加学校和省上的软件比赛,作品是 一个"零售业销售部决策支持系统",很显然,决策支持系统需要一般都适用于一些数据仓库的东 东,当然也就需要海量数据的支持才能够更好的”show”给那些评委们花里胡哨的各种图形决策 建议,没有哪家超市愿意给我们实际的数据(可能性为零),于是,情急之下连蒙带骗拽了班上十 几个”铁哥们”(有些是说了半天好话才在那几天临时成为铁哥们的),在机房加班奋战输入了两 天测试数据。最后笔者获的了一等奖之后,为了筹劳这帮手力劳动者,忍痛将奖金的一部分“割 舍”出去让大家下酒,等各种请客活动结束以后,发现还倒贴了 5 块钱。当时我就想,要是有个 作者:姜江 error 234 软件可以自动生成测试数据,不就可以省出来这笔“成本”了吗?不过想归想,又觉得可能性不 大,知道遇见了 PowerDesigner 之后,才感觉前途一片光明。 下面我们将学习如何使用 PowerDesigner 生成测试数据 现在,进一步扩展模型,加入课本等几张表,如图 3-77 所示。并未模型生成测试数据: 图 3-77 生成测试数据模型实例 测试数据 测试数据是能够为模型中的一个或者多个表生成的样本数据。PowerDesigner 可以为表生成 测试数据。 一般而言,可以通过测试数据验证数据库的性能,包括以下几个方面:  当数据库中包含大量数据的时候,检查数据库的性能  当不同用户和不同应用程序访问数据库的时候, 检查数据库的性能  当不同用户和不同应用程序访问数据库的时候, 检查数据库的操作性能  估计数据库需要占用的内存空间  评估数据库的数据格式化 测试数据摘要文件 测试数据摘要文件在 PowerDesigner 用来生成测试数据。测试数据摘要文件是一种经过命名 的数据类型,包含经过定义的数据产生源。测试数据摘要文件能够指定给一列或者多列。 测试数据摘要文件不仅能够指定给某列,还可以指定给 domain(域),这样就可以使得使用 该 domain 的所有列都可以自动分配到该测试数据摘要文件。 测试数据摘要文件包括三种类型:  Number  Character  Date/Time 假设创建一个叫做 Address 的测试数据摘要文件,那么我可以在 Teacher.address 中使 用,可以在 Student.address 中使用。以下几种类型的数据库元素在生成的测试数据中不被 考虑:  作者:姜江 error 235    , sequential, OLE, text or image data types  3.7.1 创建测试数据摘要文件 创建测试数据摘要文件的步骤: 1. 选择【Model】→【Test Data Profiles】,弹出测试数据摘要文件列表窗口 2. 双击空白行新建测试数据摘要文件,输入 name 和 code 3. 从 Profile Class 下拉列表中选择一种数据类型,点击【应用】按钮 4. 双击该行,进行详细定义 5. 在 General 属性页中的 Generation Source 单选框中选择 Automatic 自动化产生 Number 类型数据 Class 选择 Number 然后选择 Detail 属性页,如图 3-78 所示。 图 3-78 定义数字类型测试摘要文件的详细信息 如果在 Generation Source 中选择 List,那么在 Detail 属性页中则可以输入列表,同理, 可以选择 ODBC 方式,和从文件中取值,如果是 file 那么,可以默认可以选择*.csv(excel)类 型的文件作为测试数据源。LIST/ODBC/FILE 这三种方式都是读者利用外部数据的方式产生测试 数据,而 Automatic 则是 PowerDesigner 自动产生,使用者之需要做一些定制即可,这里主要介 绍自动化产生测试数据。 自动化产生 Characters 类型数据 Class 选择 Characters 然后选择 Detail 属性页,各选项参考表 3-49。 表 3-49 测试数据摘要文件属性窗口“Detail”页各参数含义 作者:姜江 error 236 选项 参数 描述 Verify Valid characters 可以使用的合法字符 All 所有字符都为合法字符 Invalid characters 不合法的字符列表 No accents 不是用重音符号 Mask 字符串的掩码字符 Case Upper First uppercase Lower Mixed 说明大小写的合法性 Length Exact 指定精确的字符长度 From/To 指定字符长度的范围 其中,字符串掩码字符为提前定义的能够向用户指明他们需要输入特定类型的信息。 PowerDesigner 可以根据如表 3-50 所示掩码字符生成相应的测试数据。 表 3-50 不同类型的掩码 掩码字符 类型 A 字母 9 数字 ? 任何字符 自动化产生 Data & Time 类型数据 Class 选择 Date & Time 然后选择 Detail 属性页: 图 3-79 定义时间日期类型测试摘要文件的详细信息 如图 3-79 所示,输入日期的起始范围,以及时间的范围,并且可以选择是随机产生还是顺序 产生,如果选择了顺序产生,则可以进一步规定顺序增长的值。点击【确定】按钮。 如果在 Generation Source 中选择 List,那么在 Detail 属性页中则可以输入列表,同理, 可以选择 ODBC 方式,和从文件中取值,如果是 file 那么,可以默认可以选择*.csv(excel)类 型的文件作为测试数据源。LIST/ODBC/FILE 这三种方式都是读者利用外部数据的方式产生测试 数据,而 Automatic 则是 PowerDesigner 自动产生,使用者之需要做一些定制即可,这里主要介 作者:姜江 error 237 绍自动化产生测试数据。 定义列填充参数 打开表编辑窗口中的 Columns 属性页,双击需要规定平均长度的列,进入列的 Detail 属性页 中,在 Average Length 中输入特定的值,以及 null 值占的百分比,和不重复值的百分比,这里 主要规定测试数据生成时,以何种方式填充列。 如图 3-80 所示。 图 3-80 定义列生成测试数据的填充参数 下面就根据自己的模型创建几个测试数据摘要文件: 1. 创建一个 code 为 country 的测试数据摘要文件,Generation Source 选择为 File,Class 选 择为 Character,然后在 Detail 属性页中选择文件 D:\Program Files\Sybase\PowerDesigner 9\testdata\country.csv(这个目录为笔者电脑中安装目录,读者可根据自己的安装目录选 择 PowerDesigner 自带的测试数据文件) 2. 创建一个 code 为 ISBN 的测试数据摘要文件,Generation Source 为 Automatic,Class 选择 为 Number,进入 Detail 属性页,在 Valid Characters 输入框中输入:'0'-'9',Mask 中输 入 9999999999(表示 ISBN 包含十位数数字) 3. 创建一个 code 为 subject 的测试数据摘要文件,Generation Source 为 List,Class 选择为 Character,选取 Detail 属性页中,输入 10 个不同的 value:English/Math/Software/ Database/UML/OS/Java/Delphi/Vc/PowerDesigner 4. 创建一个 code 为 publishDate 的测试数据摘要文件,为 Generation Source 为 Automatic, Class 选择为 Date & Time,进入 Detail 属性页,输入 Date Range 为:1980/1/1-2003 /12/31 5. 创建一个 code 为 description 的测试数据摘要文件,为 Generation Source 为 List,Class 选择为 Character,进入 Detail 属性页,输入几个不同的 value:“这是一本好书”/“这本 书还可以”/“这本书很差劲”„ 作者:姜江 error 238 3.7.2 给列指定测试摘要文件 为某个列指定测试摘要文件相当于为指定了该列产生哪种类型的测试数据,除了外键值外, 你可以为表中的每个列指定测试摘要文件,因为外键的测试摘要文件会被默认分配,如果你给某 个包含约束的列指定测试摘要文件,那么生成的测试数据也会符合约束的规定。 为列指定测试摘要文件可以通过以下三种途径:  通过表列表指定或者双击图形模型中的表,进入 Columns 属性页的 Detail  通过列列表指定 在 Detail 中的 Profile 下拉框中选择我们定义好的测试摘要文件,确定即可。  为 domain(域)指定测试摘要文件,这样,所有和该域相关的列都自动被指定为该测试 摘要文件 前面两种方法虽然可以实现,但是由于必须打开每个表,每个列的属性窗口,因此效率 比较低,也不方便。选择【Model】→【Columns】,打开所有列的列表的窗口【Customize Columns and Filter】,使得列“Test data profile”显示出来,通过下拉框为各列选择定义好 的测试摘要文件,如图 3-81 所示。 图 3-81 在列的列表窗口中为列选择测试摘要文件 为表“课本”表中的:“课本名称”选择 subject,ISBN 选择 ISBN,“出版日期”选择 publishDate, 为备注选择 description,为表“国家”中的列“国家名称”选择 country,点击【确定】按钮。 3.7.3 生成数据库测试数据脚本(SQL 脚本) 下面,为“课本”和“国家”两张表生成测试数据,在生成测试数据之前,必须用模型更新 数据库,读者可以使用生成脚本的方法,也可以直接用 ODBC 更改,这部分内容已经在前面的章节 中学习过。 1.选择【Database】→【Generate Test Data】,弹出测试数据生成窗口 作者:姜江 error 239 2.在 Selection 属性页选择表“课本”和“国家”,进入 Number of rows 属性页,为两张表 格生成 5 条测试数据。 3.在 Test Data Generation 属性页中可以规定默认的生成测试数据的数据,以及是否删除 表中的旧数据,此外,还可以选择数字型,字符型,以及日期时间三种类型的数据的默认测试数 据文件,读者可以根据自己的需要选择 4.最后选择 Script Generation,选择脚本文件存放的路径,输入脚本文件保存的名称,点 击【确定】按钮。生成的脚本如下 ====================================================================== set identity_insert country on go insert into country (countryID, countryName) values (0, 'AFGHANISTAN') go insert into country (countryID, countryName) values (4, 'ALBANIA') go insert into country (countryID, countryName) values (3, 'ALGERIA') go insert into country (countryID, countryName) values (2, 'AMERICAN SAMOA') go insert into country (countryID, countryName) values (1, 'ANDORRA') go set identity_insert country off go insert into book (bookID, bookName, ISBN, description, price, publishDate, country) values (0, 'OS', '6144016648', '这是一本好书', 2, '1998-4-22 0:4:27', 3) go insert into book (bookID, bookName, ISBN, description, price, publishDate, country) values (2, 'Java', '3523482367', '这本书还可以', 0, '1992-12-22 1:27:37', 3) go insert into book (bookID, bookName, ISBN, description, price, publishDate, country) values (3, 'Delphi', '1832331476', '这本书很差劲', 1, '1986-3-13 20:52:48', 2) go insert into book (bookID, bookName, ISBN, description, price, publishDate, country) values (4, 'Vc', '6420757530', '这是一本好书', 4, '2003-4-5 23:42:45', 2) go insert into book (bookID, bookName, ISBN, description, price, publishDate, country) 作者:姜江 error 240 values (1, 'PowerDesigner', '6436135060', '这本书还可以', 3, '1980-1-1 0:0:0', 3) go ====================================================================== 这样,就可以直接将该脚本在 SQL Server 2000 的 SQL Analyzer 中执行了,如果需要大量数 据,可以在 Number of rows 属性页中修改测试数据生成的行数。如果为数据库中所有表生成测试 数据,那么为每一张表的每一行都分配测试数据摘要文件无疑比较浪费时间,这时候,读者可以 根据不同类型数据的特点,定义一些测试数据摘要文件,作为默认的测试数据摘要文件,可以节 省大量的时间和精力。 笔者在前面的章节中也提到过,生成的测试脚本也不一定完全能够正确执行,PowerDesigner 生成的测试 Date & Time 这种类型数据脚本有时候会出错,出错时读者可以自行调节。 3.7.4 测试数据摘要文件的 Import 和 Export 一般而言,定义好的测试摘要文件都只在特定的模型中使用,不过我们也可以通过导入导出 测试摘要文件来在 PDM 中使用其他模型中定义的测试数据,因为这些摘要文件在很多情况下复用 性是很高的。 测试数据摘要文件可以导出格式为 XPF 的文件。 A.导出测试数据摘要文件 1.选择【Tools】→【Test Data Profile】→【Export】,弹出选择窗口 2.选择一个或者多个你需要导出的测试摘要文件,点击【确定】按钮, 如图 3-82 所示。 3.弹出一个保存文件的窗口,选择好存放路径,输入带有 XPF 为后缀名的文件名 图 3-82 选择要导出的测试摘要文件 4.点击【保存】按钮。 B.导入测试数据摘要文件 1.选择【Tools】→【Test Data Profile】→【Import】,弹出打开文件窗口 2.在弹出的窗口中选择需要导入的测试数据摘要文件 3.点击【确定】按钮。查看【Model】→【Test Data Profiles】确定测试数据摘要文件已 成功导入 作者:姜江 error 241 3.7.5 定义 ODBC 为测试数据源 PowerDesigner 提供的另外一个强大的功能就在于可以定义 ODBC 数据源为测试数据源。下面 为具体的操作方法: 1. 选择【Model】→【Test Data Profiles】,弹出测试数据摘要文件列表 2. 新建一个测试数据摘要文件,在 Generation Source 中选择 ODBC 3. 进入 Detail 属性页中 4. 在 Datasource 处选择 ODBC 数据源,并在下方输入用户名和密码 5. 输入表名和列名,同时定制最下方的 Query 查询语句,用于选择出希望得到的测试数据 源的“列”。如图 3-83 所示。 图 3-83 定义 ODBC 的数据为测试数据源 3.8 反向工程/对数据库进行修改及其应用 前面提到,很多数据库设计人员往往直接在 DBMS 自带的 GUI 中输入表的相关定义,但是,如 果要对整个模型有一个总体的把握就比较困难,一般 DBMS 不提供丰富的图形模型表示功能。MS SQL Server 2000 中有一个叫“关系图”的工具,从一定程度上能够帮助设计人员进一步方便的操作 数据库,但是无论从其图形布局能力还是从数据库相关设计功能方面都不能令人满意。 前面我们已经利用在 PowerDesigner 中建立的模型在 MS SQL Server 2000 中生成了一个叫 TEST 的数据库,现在假设我们需要对这个数据库有一个整体的直观的了解,很显然,看着一堆表 的列表会让人头痛,如果要看表之间的关系,要么就是利用“关系图”不够强大的功能(布局出 来的图形也很不易理解),要么就只能通过不断的点击鼠标进入表查看相关的外键约束等关系,数 据库中的表越多这种感觉就会越明显,也就越难以对数据库有一个宏观的把握。此外,对于数据 库设计人员和程序员而言,如果能够有一张关系清晰的图形能够表明数据库的结构以及表之间的 关系那么对数据库设计和修改以及程序员的变成而言都会有极大的方便。 作者:姜江 error 242 下面,我们将学习如何利用 PowerDesigner 的反向工程的功能,对现有数据库模型化,并且 直接通过对模型的操作进一步改进数据库设计,同时与现有数据库进行比较保持同步。 3.8.1 定义 ODBC 数据源 定义 ODBC 的步骤如下: 1. 选择【Database】→【Configure Connections】 或者【控制面板】→【管理工具】→【数 据源(ODBC)】或者在【开始】→【运行】→【odbcad32】,打开配置 ODBC 的窗口 2. 定义一个 ODBC 数据源,选择我们刚刚创建好的 SQL Server 2000 的数据库 test,数据源名称 也为 test,填写正确的用户名和密码。 3.8.2 反向工程产生模型 A.将数据库反向工程产生模型的方法 1. 选择【Database】→【Connect】,选择我们定义的数据源,输入用户名和密码,点击【确定】 按钮。 2. 新建一个 PDM,选择 DBMS 为 MS SQL Server 2000,默认模型名称为 PhysicalDataModel_1 3. 选择【Database】→【Reverse Engineer Database】,或者按快捷键【Ctrl+R】,在弹出窗 口 Database Reverse Engineering 中选择单选框 Using an ODBC data source,选择刚才建 立并连接的 ODBC 数据源,可以点击【Connect to and ODBC Data Source】工具 ,在弹出 的窗口中选择数据源,并且输入登录的用户名和密码。 4. 如果要选择从脚本反向工程生成模型,则在 Database Reverse Engineering 窗口中选择单选 框 Using Script files,点击【Add files】工具 ,在弹出的窗口中选择需要反向工程的 脚本文件,点击【确定】按钮,如图 3-84 所示。 图 3-84 反向工程数据库 作者:姜江 error 243 5. 在 Database Reverse Engineer 窗口中的 Options 属性页中是反向工程的一些选项,请参考 表 3-51。 表 3-51 数据库反向工程窗口“Options”页部分选项含义 选项 含义 Automatically rebuild references when no reference is reversed 如果反向工程未产生引用,那么创建引用。 如果某个表主键和另外一个表的某列具有 相同名称和数据类型,并且这个非主键的 列也不是另一个表的外键,那么在这两列 之间创建外键引用 Automatically rebuild primary keys from unique indexes when tables have no key and only one unique index 如果某表没有主键,并且只有一个唯一性 索引的,则将这个唯一性索引定义为该表 主键,该选项为默认选项 Automatically reverse parent tables for references of selected tables 对选定的子表(ChildTable)的父表也反 向工程,这样做的目的是为了完整这些 ChildTable 的定义 Create symbols 为每个反向工程的对象在图形中都创建图 符,否则只能在左侧的 browser(浏览器) 中看到对象,该选项为默认选项 6. 点击【确定】按钮,PowerDesigner 会弹出一个窗口,将 ODBC 数据源中包含的元素列出,共 用户选择哪些数据库元素需要被反向工程在我们刚才建立的模型中,如图 3-85 所示。 图 3-85 选择要反向工程的对象 7. 选择完毕后点击【确定】按钮。 这时,PowerDesigner 会将相关的元素反向工程到模型中,并且建立相应的图形模型,如图 3-86 所示,该图为经过布局调整的图形模型: 作者:姜江 error 244 图 3-86 反向工程生成的模型 在基础上,我们就可以进一步操作模型,同时,也可以利用前一节的知识在不同的 DBMS 之间 轻松的建立同构的数据库。 B.反向工程到新的模型中的方法 选择:【File】→【Reverse Engineer】→【Database】,会弹出新建模型的 PDM 模型的窗口, 选择 DBMS 之后确定,会弹出反向工程的窗口,其他步骤均相同。 3.8.3 比较、同步模型和数据库、通过模型修改数据库 这一节中,我们将进一步学会如何利用 PowerDesigner 提供的强大功能进行模型和实际数据 库之间的同步以及比较。具体的操作方法如下: 1. 将“teacher”中的列“name”改为“teacherName”,列“gender”的数据类型改为 char (1),添加一个 isMarried 的字段,数据类型为 bit,删除“teacher”与“class”之间 的外健关系(这里仅仅是举例)。 2. 选择 Modify Database,弹出的窗口非常类似 Generate Database 的窗口,我们可以选择 通过 SQL 脚本修改,或者 ODBC 方式修改,该窗口包括三个属性页:Synchronization, Options,Selection 3. 在 Synchronization 属性页中选择我们 ODBC 数据源 test,在 Selection 属性页中选择需 要同步的元素。而 Options 属性页中的内容一般情况下不用修改,使用默认即可,用户 也可以自己定制。点击【确定】按钮 除了同步 ODBC 数据库之外,还可以通过选择 Using a script file 或者 Using an archive model 分别同步、修改数据库的脚本,以及存档模型(Archived Model),关于 如何将 PDM 模型存档,请参考 :3.4 创建和操作 PDM(B.PDM 和 Workspace)。如图 3-87 所示。 作者:姜江 error 245 图 3-87 “Database Modification”窗口 选择 Using an archive model,然后点击右边的工具 ,在弹出的窗口中选择需要修 改或者同步的存档模型,点击打开,其他步骤都和使用 ODBC 相同。 4. 这时, 一个和前面那个反向工程的对话框 一模一样的窗口会弹出来,这表明 PowerDesigner 实际是通过反向工程在内存中建立一个模型,然后与 workspace 中存在的 模型进行比较来实现数据库与模型之间的比较与同步的。进行适当的选择后点击【确定】 按钮。 5. 如图 3-88 所示。该图为模型和数据库比较窗口: 作者:姜江 error 246 图 3-88 模型域数据库同步窗口 在模型和数据库之间会比较出四种类型的不同:  创建/增加:一个模型中新建了一个对象,这时候会以蓝色显示  删除:一个对象从某个模型中被删除,则对象被删除的模型中,该对象看起来则像一个 幽灵(颜色非常暗淡,有点虚幻的感觉,类似灰化)  修改:如果连个模型中的同一个对象被修改,那么在这个对象的右下方会有一个红色的 感叹号的标志。  移动:如果是两个模型之间比较,那么某个模型中的对象的位置发生了移动。例如,某 列在表中的前后顺序发生了改变,那么一个绿色的三角会出现在该对象的右下方。如果 绿色的三角形状同时以“幽灵”的形式出现,则表明该对象只是被移动 读者可以参考表 3-52 对前面窗口中的内容进行分析。 表 3-52 模型比较窗口图标示例及其含义 符号 含义 “幽灵”对象在某个模型中不存在 子对象不同 两个模型中都存在的对象,但是具有不同的属性 对象被移动并且修改,往往指在模型中的初始位置 作者:姜江 error 247 对象被移动并且修改,往往指在模型中的新位置 对象被移动 如果修改数据库,则这个字段要增加(注意加号) 如果修改数据库,则这个字段要增加(注意加号) 在模型中该字段为新建的字段 如果修改数据库,则这个字段要删除(注意减号) 如果修改数据库,则这个字段要修改(注意等) 各个对象在右下角的小图标的颜色表示的含义,可以参考表 3-53。 表 3-53 对象右下角图标颜色含义 符号 含义 红色(Red) Modification(修改) 黄色(Yellow) Indication(指示) 绿色(Green) Move(移动) 紫色(Purple) Deletion and shortcut replacement(删除或者快捷方式替换) 蓝色(Blue) Addition(增加) 而小图标中的“加号”、“减号”、“等于号”等符号的含义,请参考表 3-54。 表 3-54 对象右下角图标符号含义 符号 含义 [=] 相同 [+-] 增加的 [-+] 修改的 [#] 删除的 [!] 修改过的 <- 从„移动 -> 移动至„ ['?] 有冲突(不一致的地方) [#<-] 从„移动过来,经过修改 [->#] 经过修改,移动至„ 为了让读者进一步熟悉模型比较窗口的含义,这里引用了 PowerDesigner 10 自带的帮助文件 中的一些例子公大家学习。如表 3-55 所示。 表 3-55 模型比较窗口图形含义实例 符号 区别 合并行为 作者:姜江 error 248 对象创建 在需要合并的模型中增加这个对象 对象删除 从需要合并的模型中删除该对象 对象修改 用左侧的对象定义更新模表模型中对象的 定义 对象移动 移动对象使之与左侧模型中的该对象的位 置相同,或者用快捷方式替换 快捷方式合并 用目标对象替换快捷方式 快捷方式删除 从目标模型中删除快捷方式 快捷方式创建 在目标模型中创建快捷方式 s 在 Merge Models 窗口中可以看到很多对象前面都包含一个复选框,这个复选框如果被选中, 则表示执行该合并行为,否则忽略不执行。 下面的例子中,Entt_2 被从主 Diagram(Diagram1)移动至 Package_2 中,如图 3-89 所示。 图 3-89 实体移动先后的模型比较 下面的例子中,Package_2 中的 Entt_5 被修改,并且移动到 Package_1 中,模型合并窗口如 图 3-90 所示。 作者:姜江 error 249 图 3-90 实体修改先后的模型比较 不同的情况可能导致模型比较/合并窗口的结果有很大的不同,读者可以多试验,逐步掌握 各种不同图标的含义,从而更佳清晰的了解模型之间的不同,确保模型合并可以正确进行。 下面,我们在来看看如图 3-91 所示同步窗口中的其他快捷工具的作用: 图 3-91 同步窗口的快捷工具 上图的八个工具的含义分别是: 1. 对象属性,弹出对象属性的窗口,但是不可以在此处修改对象属性 2. 模型比较的选项,可以选择模型比较的数据库元素 3. 手动同步两个模型 4. 第一个不同的地方 5. 前一个不同的地方 6. 下一个不同的地方 7. 最后一个不同的地方 8. 合并(Merge)预览,会有相应的窗口弹出,显示修改数据库所要进行的操作 除此之外,还可以通过如图 3-92 所示的三个菜单,对模型中不同类型的“不一致”进行分类 的选择,相信读者通过字面意思就能够理解每个菜单项的功能含义。 图 3-92 同步窗口的工具菜单 作者:姜江 error 250 选择好之后,点击【确定】按钮。如果我们前面选择了 Script Generation,那么 PowerDesigner 会为我们生成一个 SQL 脚本,如果选择了 ODBC Generation,则会弹出一个脚本执行窗口,这和 我们前面生成数据库建库脚本是相同的。 下面我们研究一下 PowerDesigner 为我们生成的代码: ====================================================================== /*==============================================================*/ /* Database name: Database */ /* DBMS name: Microsoft SQL Server 2000 */ /* Created on: 2003-11-9 21:06:43 */ /*==============================================================*/ alter table dbo.class drop constraint FK_Class_Teacher go alter table dbo.class drop column teacherInCharge go if exists (select 1 from sysobjects where id = object_id('dbo.tmp_teacher') and type = 'U') drop table dbo.tmp_teacher go /*==============================================================*/ /* Table: tmp_teacher */ /*==============================================================*/ create table dbo.tmp_teacher ( teacherID int not null, name varchar(20) not null, gender bit not null, email varchar(50) null, mobile char(11) null, phone varchar(15) null, address varchar(50) null, description varchar(50) null ) 作者:姜江 error 251 go insert into dbo.tmp_teacher (teacherID, name, gender, email, mobile, phone, address, description) select teacherID, name, gender, email, mobile, phone, address, description from dbo.teacher go if exists (select 1 from sysobjects where id = object_id('dbo.teacher') and type = 'U') drop table dbo.teacher go /*==============================================================*/ /* Table: teacher */ /*==============================================================*/ create table dbo.teacher ( teacherID int not null, teacherName varchar(20) not null, gender char(1) not null, email varchar(50) null, mobile char(11) null, phone varchar(15) null, address varchar(50) null, description varchar(50) null, isMarried bit null, constraint PK_TEACHER primary key clustered (teacherID) ) go insert into dbo.teacher (teacherID, teacherName, gender, email, mobile, phone, address, description) select teacherID, ?, ?, email, mobile, phone, address, description from dbo.tmp_teacher go ====================================================================== 我们发现,这段脚本的结构式这样的: 作者:姜江 error 252 1. 删除表之间的外键关系,这同数据库较本省城市一致的 2. 会有一段 drop table dbo.tmp_teacher 的脚本,我们稍后再作解释 3. 建立一个表 dbo.tmp_teacher 注意:SQL Server 2000 中 dbo 是一个用户,tmp_teacher 的 db_owner(数据库所 有者)是 dbo,可以用面向对象的方式来操作表,由此可以看出 PowerDesigner 能够根据 不同类型的数据库生成个性化的脚本,基本实现数据库无关的建模方式 4. 将 dbo.teacher 中的数据保存在 dbo.tmp_teacher 中 5. 删除表 dbo.teacher,在重新创建一个经过我们在模型中修改的 dbo.teacher 6. 再将 dbo.tmp_teacher 中的数据插入到 dbo.teacher 中 由此我们可以发现第二步中删除表 dbo.tmp_teacher 目的也在于删除数据库中同名的表,便 于后面重新建立,这个临时表 dbo.tmp_teacher 所起的作用就是临时存放数据库数据,待新表建 立之后将数据转移至新表。 我们会发现,如果我们把这段代码 Copy 到 SQL Server 2000 的 SQL Analyzer 中执行,发现 也会出错,因为我们会发现最后一段代码是:select teacherID, ?, ?, email, mobile, phone, address, description,因为 PowerDesigner 无法像人一样推断哪些字段在经过修改之后可以对 应,只能机械的生成代码,如果我们的数据库中还没有数据的,那么在执行的时候读者完全可以 先将于这系临时表有关的语句删除,那么也就可以避免这种类型错误的出现。 所以,在执行之前,最好能先执行语法检查(SQL Analyzer 中为 Ctrl+F5)分析一下脚本的 构成。在这里我们主要是为了通过这个例子告诉读者如何利用工具生成脚本,同时,生成的脚本 在某些情况下是需要读者进行调整的,不是永远都可以在 DBMS 中正确执行的。和 Rational Rose 等建模工具一样,工具仅仅是工具,并不能代表有了强大的建模工具就不再需要精通编程语言的 程序员,它只能尽最大可能的帮助设计人员和开发人员自动化一些功能。 备份选项对生成脚本的影响: 下面,进一步学习在 Database Modification 窗口中下方的关于数据备份的选项,也可以选 择是否要备份表(旧的版本不一定有这个选项,笔者使用的版本是 PowerDesigner 的版本是 9.5.2.908 EBF4),对于生成脚本的影响。如图 3-93 所示。 图 3-93 修改数据库时的选项 各个选项的含义如下:  Use alter statements when possible:尽可能使用 alter 语句,而不删除对象后重新 创建  Always use create statements:总是使用创建语句,先删除数据库中同名对象,然后 作者:姜江 error 253 重新创建  Drop temporary:处理完毕后删除临时表 假设数据库中的表“student”表包含一个字段 name,而模型中的表“student”包含两个字段, 和数据库相比多了一个字段“testColumn”,我们可以通过三个选项的四种组合生成的代码做一个 比较,就不难理解各个选项的作用: ==============脚本一:选择 Use alter statements when possible===== alter table dbo.student add testColumn int null go ==============脚本二:选择 Always use create statements======== if exists (select 1 from sysobjects where id = object_id('dbo.tmp_student') and type = 'U') drop table dbo.tmp_student go /*==============================================================*/ /* Table: tmp_student */ /*==============================================================*/ create table dbo.tmp_student ( studentID int not null, name varchar(20) not null ) go insert into dbo.tmp_student (studentID, name) select studentID, name from dbo.student go if exists (select 1 from sysobjects where id = object_id('dbo.student') and type = 'U') drop table dbo.student go /*==============================================================*/ 作者:姜江 error 254 /* Table: student */ /*==============================================================*/ create table dbo.student ( studentID int not null, name varchar(20) not null, testColumn int null, constraint PK_STUDENT primary key clustered (studentID) ) go insert into dbo.student (studentID, name) select studentID, name from dbo.tmp_student go =======脚本三:选择 Use alter statements when possible 和 Drop temporary=== alter table dbo.student add testColumn int null go =======脚本四:选择 Always use create statements 和 Drop temporary====== if exists (select 1 from sysobjects where id = object_id('dbo.tmp_student') and type = 'U') drop table dbo.tmp_student go /*==============================================================*/ /* Table: tmp_student */ /*==============================================================*/ create table dbo.tmp_student ( studentID int not null, name varchar(20) not null ) go insert into dbo.tmp_student (studentID, name) select studentID, name from dbo.student 作者:姜江 error 255 go if exists (select 1 from sysobjects where id = object_id('dbo.student') and type = 'U') drop table dbo.student go /*==============================================================*/ /* Table: student */ /*==============================================================*/ create table dbo.student ( studentID int not null, name varchar(20) not null, testColumn int null, constraint PK_STUDENT primary key clustered (studentID) ) go insert into dbo.student (studentID, name) select studentID, name from dbo.tmp_student go if exists (select 1 from sysobjects where id = object_id('dbo.tmp_student') and type = 'U') drop table dbo.tmp_student go ========================================== 通过比较可以发现:第一段代码选择的是 Use alter statements when possible,因此添加 一个字段并不需要重新创建表,而只需要执行 alter table 脚本即可;第二段代码选择的是 Always use create statements,因此无论是否需要创建表,都会创建一个临时表保留数据,然后删除表, 最后重新创建表,再将临时表中的数据插入新创建的表;第三段代码选择的是 Use alter statements when possible 和 Drop temporary,因为本例中不需要创建临时表,所以也就没有删 除临时表的脚本,和第一段脚本一样(注意第三种方式不一定和第一种脚本一样,有时模型和数 据库之间的不一致不能通过 alter 语句来实现就必须使用到临时表保存数据,这时候就会在处理 作者:姜江 error 256 其它信息完毕后删除临时表;第四段代码和第二段代码的区别就在于在脚本的最后删除该脚本执 行期间创建的临时表。 读者可以用心的体会,多实验一些复杂的情况对脚本的影响,一方面要判断自己数据库中的 数据是否要保留,另一方面在模型和数据库的比较窗口中也可以选择一些不希望产生修改的地方 (在数据库对应的右侧,例如: ,去掉选钩,表示不对数据库应用该修改),避 免一些不希望产生的对数据库的修改。这样才能用好 PowerDesigner,较好的实现模型和数据库 的同步控制。 3.8.4 通过反向工程实现异种数据库转化 如果我们希望在异构数据库之间进行转化,而且又没有现成的数据库的模型,那么完全可以 利用 ODBC 反向工程生成模型,然后参考 3.6.4 使用 ODBC 创建,生成其他类型 DBMS 的数据库 3.8.5 在 PowerDesigner 中操作数据库 前面我们提到定义好 ODBC 数据源,并且连接到该数据库。现在,我们可以直接通过在 PowerDesigner 中执行 SQL 语句,对数据库进行操作。 1.选择【Database】→【Execute SQL】或者按快捷键【Ctrl+Shift+E】,或者在图形模型 中右键点击某表,在弹出的菜单中选择 View Data 2.弹出窗口 Execute SQL Query,输入需要执行的 SQL 语句,例如: ==================================================================================== delete from student insert into student (studentID, name, gender, email) values (2, '姜江', 1, 'jiangj@modesoft.cn'); go insert into student (studentID, name, gender, email) values (3, '艾顺刚', 1, 'jiangj@modesoft.cn'); go select * from student ==================================================================================== 点击右上角的快捷键【Run】 或者按快捷键【F5】,执行该脚本,在弹出的对话框中显示 该段 SQL 脚本执行的结果集。如果 SQL 脚本执行有错误则 PowerDesigner 在 Execute SQL Query 窗口的下方显示或者弹出窗口提示错误信息,与以下信息类似: ====================================================================== 批注 [e14]: 此处编号错误,已修改 作者:姜江 error 257 *** Execution of statement failed: [Microsoft][ODBC SQL Server Driver][SQL Server]语句已终止。 SQLSTATE = 01000 ====================================================================== 3.9 数据库优化及非范式化(Denormalizing) 关系数据库设计是要遵守一定的规则的,规范化目的是使结构更合理,消除存储异常,使数 据冗余尽量小,便于插入、删除和更新,这就是大家常说的范式设计。但是有一点需要引起大家 的注意,并不是满足的范式越高越好。你所设计的数据表满足的范式越高,只能说明数据冗余越 小而已。不能说满足第三范式的关系一定比满足第一范式的好。你设计的关系到底应该满足第几 范式,应该视实际情况而定,可能我们减少了数据冗余,节省了空间,但却减慢了运行速度。所 以,数据库的设计应该满足第几范式,应根据实际应用的需要,采用灵活的策略 这部分主要讲述 Denormalization(非范式化)。Denormalization 是把某个 fact(可理解 为数据)存放在不同的地方以加快数据查询速度的过程。我们将会发现,Denormalization 似乎 是 一 个 与 范 式 化 ( normalization)恰恰相反的过程,但我们必须清楚,除非为了通过 Denormalization 来提高数据库的性能,否则请不要轻易使用 Denormalization。以下几种情况都 有可能需要做 Denormalization:  关键性的查询依赖于几个表中的数据  需要一个或者多个字段进行计算才能得到查询的结果  在某个时间帧上,某个表可能被不同的用户以不同的方式存取  对某个特定的列占用了查询的大部分时间 我们主要通过以下几种方法来实现 Denormalization:  水平分割(Horizontal partitioning) 将一个表分割为几个表,每个表包含相同的列,但是行数减少  垂直分割(Vertical partitioning) 将一个表分割为几个表,每个表包含相同的行数,但是列数减少  “打碎”表(Table collapsing) 将几个不同的表合并,以便减少之间的关联  对列进行非范式化(Column Denormalization) 在表中重复某列的值,以避免在表之间创建关联 3.9.1 范式与非范式化 关系数据库设计是对数据进行组织化和结构化的过程,核心问题是关系模型的设计。关系模 型是数学化的、用二维表格数据描述各实体之间的联系的模型;它是所有的关系模式、属性名和 作者:姜江 error 258 关键字的汇集,是关系模式描述的对象。关系模式是指一个关系的属性名表,即二维表的表框架。 关系模式的设计是关系模型设计的灵魂。所以,关系模式的设计是关系数据库设计核心的核心。 关系模式的设计直接决定着关系数据库的性能。目前,在指导关系模式的设计中规范化 (normalization)设计占有主导地位,它是在数据库几十年的长期发展中产生并成熟的。但近年来 这一领域出现了一种新的趋势,一种称为非规范化(denormalization)或者非范式化的关系模式设 计引起业界的关注并已在一定的范围内得到应用。对这一新的设计思想,各方反应迥异褒贬不一, 从而在相关的理论界掀起了一场不大不小的规范化与非规范化之争。 一、规范化设计 关系模式规范化设计的基本思想是通过对关系模式进行分解,用一组等价的关系子模式来代 替原有的关系模式,消除数据依赖(包括函数依赖和多值依赖)中不合理的部分,使得一个关系仅 描述一个实体或者实体间的一种联系。这一过程必须在保证无损连接性、保持函数依赖性的前提 下进行,即确保不破坏原有数据,并可将分解后的关系通过自然联接恢复至原有关系。 具体地说,规范化设计的过程就是按不同的范式,将一个二维表不断地分解成多个二维表并 建立表之间的关联,最终达到一个表只描述一个实体或者实体间的一种联系的目标。目前遵循的 主要范式包括 1 NF、2 NF、3 NF、BCNF、4NF 和 5NF 等几种;在工程中 3NF、BCNF 应用得最广泛, 推荐采用 3 NF 作为标准。 规范化设计的优点包括可有效地消除数据冗余,理顺数据的从属关系,保持数据库的完整性, 增强数据库的稳定性、伸缩性、适应性。通常认为规范化设计存在的主要问题是增加了查询时的 连接库表运算,导致计算机时间、空间、系统及运行效率的损失。在大多数情况下,这一问题可 通过良好的索引设计等方法得到解决。 二、非规范化设计 非规范化设计的基本思想是,现实世界并不总是依从于某一完美的数学化的关系模式。强制 性地对事物进行规范化设计,形式上显得简单化,内容上趋于复杂化,更重要的是导致数据库运 行效率的减低。非规范化要求适当地降低甚至抛弃关系模式的范式,不再要求一个表只描述一个 实体或者实体间的一种联系。其主要目的在于提高数据库的运行效率。 非规范化处理的主要技术包括增加冗余或派生列,对表进行合并、分割或增加重复表。一般 认为,在下列情况下可以考虑进行非规范化处理:(1)大量频繁的查询过程所涉及的表都需要进行 连接;(2) 主要的应用程序在执行时要将表连接起来进行查询;(3)对数据的计算需要临时表或进 行复杂的查询。 非规范化设计的主要优点是减少了查询操作所需的连接;减少了外部键和索引的数量;可以 预先进行统计计算,提高了查询时的响应速度。非规范化存在的主要问题是增加了数据冗余;影 响数据库的完整性;降低了数据更新的速度;增加了存储表所占用的物理空间。其中最重要的是 数据库的完整性问题。这一问题一般可通过建立触发器、应用事务逻辑、在适当的时间间隔运行 批命令或存储过程等方法得到解决。 三、规范化与非规范化争论的要点 作者:姜江 error 259 支持非规范化设计的一方认为,数据库规范化的程度越高,其中表的数量越多,规范化程度 与表的数量直接相关;表的数量越多,表的连接运算也越多;连接运算增多,必然降低数据库执 行的速度,影响数据库的性能。只有通过非规范化设计,显著减少表的数量,从而减少对连接运 算的依赖,加速数据库执行的速度,才能保证数据库性能的正常发挥。例如目前流行于数据仓库、 决策支持系统的非规范化星型模式就远胜于应用规范化设计,是非规范化设计的最好范例。非规 范化设计并不意味着混乱和无视规则,它也遵循保护信息完整性等软件工程的基本原则。 支持规范化设计的一方认为,规范化与非规范化只是一个逻辑概念,强调非规范化设计者混 淆了逻辑与物理的关系。数据库的性能是由物理水平决定的,即硬件、数据库的大小和物理设计、 数据存储和访问的方法、数据库管理系统的优化程度、并发访问的数量等;非规范化设计并未改 变数据库的物理水平,因此不可能提高数据库的性能。规范化并不只是为了避免数据冗余,更重 要的是为了确保数据库的完整性。非规范化设计的最大问题是难以保证数据库中数据的一致性, 存在着破坏数据的危险。此外,非规范化使一个表中存在多个实体,不同实体混合在一起强化了 数据库的复杂性,提高了用户理解的难度,并导致描述问题上的困难,增加了正确响应的风险。 只有规范化设计才是解决这些问题的根本途径。如果不摒弃非规范化设计理念,为了获得所谓的 性能的提高而漠视数据库完整性被破坏的风险,就无法激励开发商去研究真正的完全规范化而高 性能的关系数据库管理系统,其后果必然影响数据库的健康发展。 从某种意义上说,数据库的规范化与非规范化设计并不是对立的、非此即彼的关系。也许其 中一方会逐渐消亡,也许二者存在一条中间道路可走。认识事物原本存在一个螺旋式上升的过程。 这场争论尚未结束,也无法对最终的结果进行预测。但可以肯定的是,无论结果如何,都将对未 来数据库的发展方向产生深远的影响。 后面的章节中,将依次介绍范式的概念,以及 PowerDesigner 对非范式化的支持与应用。 3.9.2 范式的基本概念 数据库设计范式包括 1NF(第一范式),2NF(第二范式),3NF(第三范式)和 BCNF,4NF (第四范式),5NF(第五范式)。下面我们简单介绍各种范式的基本含义: 第一范式(1NF):在关系模式 R 中的每一个具体关系 r 中,如果每个属性值都是不可再分原 子数据项,则称 R 是第一范式的关系。 你用一张表来保存你朋友的通讯地址和邮政编码,你可能会这样设计:friends(name, address_and_zip),即把地址和邮政编码放在一块,我们在现实生活中很多时候也是这样做的, 比如(姜江,上海市杨浦区郭定路 700 弄 34 号楼 403 室(200433))。如果是这样,你就不可能根据 某个邮政编码来查询它到底是你哪个朋友的。这种设计是不符合第一范式的,所以 address_and_zip 不是原子数据项,它可以分为两个字段:address 和 zip 。合理的设计应该是 这样的:friends(name,address,zip),这样,数据表中的记录就变了:(姜江,上海市杨浦区郭 定路 700 弄 34 号楼 403 室,200433),这才是符合关系数据库最低要求的设计,也就是第一范式。 第二范式(2NF):如果关系模式 R 是第一范式的,而且关系中每一个非主属性都完全依赖于 作者:姜江 error 260 主键(候选关键字),称 R 是第二范式的 例:有一张员工表格 Employee(employeeID,employeeName,projectID,projectName,startDate, startDate),如表 3-56 所示。 表 3-56 表格“Employee” employeeID employeeName projectID projectName startDate startDate 123 Harry XYZ Space Shuttle Jul 7, 1991 Aug 8, 1991 123 Harry ZYX Place Scuttle Aug 9, 1991 Dec 24, 1991 231 Mary XYZ Space Shuttle Jul 12, 1991 Dec 24, 1991 231 Mary XYX Face Shuttle Dec 26, 1991 Mar 18, 1992 312 Larry ZYX Place Scuttle July 27, 1991 Mar 3, 1992 在应用中使用以上关系模式有以下问题:  数据冗余,假设同一员工由参与 40 个项目,员工姓名就重复 40 次。  更新异常,若调整了某项目“Space Shuttle”为“Space Shuttle No.1”,就必须保证 所有的“Space Shuttle”都要更新,否则,就会出现同一项目不同名称。  插入异常,如要新建一个项目,由于没人负责这个项目,没有和员工关联起来,此时, 要么分配一个员工负责此项目,要么就置为空。  删除异常,如果某员工离开公司,从当前数据库删除该员工记录,会相应的删除项目的 信息,例如如果删除 Mary 这个员工,那么编号为 XYX 的这个项目的信息就会被删除。 我们分析这张表就会发现,这张表中没有任何一个字段为主键,如果我们定义 employeeID+ projectID,就会发现这样使得每个员工只能负责一个项目,这显然是不能满足需求的,如果要解 决这个问题,就不得不再加上 startDate 作为主键的一部分。 为了解决这个问题,我们使用第二范式,设计如下表格: employee(employeeID,employeeName) project(projectID,projectName,startDate,completionDate) works_on(employeeID,projectID) 查询时可以通过连接实现。 第三范式(3NF):如果关系模式 R 是 2NF 的,且每一个非主属性都不传递依赖于主键,称 R 是第三范式的 例:如学生(学号,姓名,所在系,系名称,系地址) 关键字“学号”决定各个属性。由于是单个关键字,没有部分依赖的问题,肯定是 2NF。但 这关系肯定有大量的冗余,有关学生所在的几个属性所在系,系名称,系地址将重复存储,插入, 删除和修改时也将产生类似以上例的情况。 原因:关系中存在传递依赖造成的。即“学号”决定“所在系”,“所在系”->“系地址”, 因此关键辽“学号”对“系地址”函数决定是通过传递依赖实现的。也就是说,“学号”不直接 作者:姜江 error 261 决定非主属性“系地址。” 解决办法: 学生(学号,姓名,所在系) 系(所在系,系名称,系地址) BCNF:Boyce/Codd Normal Form,如果关系 R 的所有属性(包括主属性和非主属性)都不传 递依赖于 R 的任何候选关键字,那么称关系 R 是属于 BCNF 的。或是关系模式 R,如果每个决定因 素都包含关键字(而不是被关键字所包含),则 RCNF 的关系模式。 例:有表:配件管理(仓库号,配件号,职工号,数量),其中:  一个仓库有多个职工。  一个职工仅在一个仓库工作。  每个仓库里一种型号的配件由专人负责,但一个人可以管理几种配件。  同一种型号的配件可以分放在几个仓库中。 分析:由以上得“配件号”不能确定“数量”,由组合属性(仓库号,配件号)来决定,由 于每个仓库里的一种配件由专人负责,而一个人可以管理几种配件,所以有组合属性(仓库号, 配件号)才能确定负责人,有(仓库号,配件号)->职工号。因为一个职工仅在一个仓库工作, 有“职工号”->“仓库号” 找一下候选关键字,因为(仓库号,配件号)->“数量”,( 仓库号,配件号)->“职工号”, 因此(仓库号,配件号)可以决定整个元组,是一个候选关键字。根据“职工号”->“仓库号”, (职工号,配件号)->“数量”,故(职工号,配件号)也能决定整个元组,为另一个候选关键 字。属性“配件号”,“仓库号”,“职工号”均为主属性,只有一个非主属性“数量”。它对 任何一个候选关键字都是完全函数依赖的,并且是直接依赖,所以该关系模式是 3NF。 分析一下主属性。因为“职工号”->“仓库号”,主属性“职工号”是“仓库号”的决定因 素,但是它本身不是关键字,只是组合关键字的一部分。这就造成主属性“仓库号”对另外一个 候选关键字(职工号,配件号)的部分依赖,因为(职工号,配件号)->职工号,而“职工号” ->“仓库号”,故(职工号,配件号)->“仓库号”也是传递依赖。 虽然没有非主属性对候选关键的传递依赖,但存在主属性对候选关键字的传递依赖,同样也 会带来麻烦。如一个新职工分配到仓库工作,但暂时处于实习阶段,没有独立负责对某些配件的 管理任务。由于缺少关键字的一部分“配件号”而无法插入到该关系中去。又如某个人改成不管 配件了去负责安全,则在删除配件的同时该职工也会被删除。 解决办法:分成管理(职工号,配件号,数量号),关键字是(职工号,配件号),工作(职 工号,仓库号)其关键字是“职工号”。 缺点:分解后函数依赖的保持性较差。如此例中,由于分解,函数依赖(仓库号,配件号) ->“员工号”丢失了,因而对原来的语义有所破坏。没有体现出每个仓库里一种部件由专人负责。 有可能出现一部件由两个人或两个以上的人来同时管理。因此,分解之后的关系模式降低了部分 完整性约束。 作者:姜江 error 262 一个关系分解成多个关系,要使得分解有意义,起码的要求是分解后不丢失原来的信息。这 些信息不仅包括数据本身,而且包括由函数依赖所表示的数据之间的相互制约。进行分解的目标 是达到更高一级的规范化程度,但是分解的同时必须考虑两个问题:无损联接性和保持函数依赖。 有时往往不可能做到既有无损联接性,又完全保持函数依赖。需要根据需要进行权衡。BCNF 的范 式出现机会较少,而且会破坏完整性,你可以在做设计之时不考虑它。 注意:一个关系模式结这分解可以得到不同关系模式集合,也就是说分解方法不是唯一的。 最小冗余的要求必须以分解后的数据库能够表达原来数据库所有信息为前提来实现。其根本目标 是节省存储空间,避免数据不一致性,提高对关系的操作效率,同时满足应用需求。实际上,并 不一定要求全部模式都达到 BCNF 不可。有时故意保留部分冗余可能更方便数据查询。尤其对于那 些更新频度不高,查询频度极高的数据库系统更是如此。 在关系数据库中,除了函数依赖之外还有多值依赖,联接依赖的问题,从而提出了第四范式, 第五范式等更高一级的规范化要求。 第四范式(4NF):第四范式是 BC 范式的推广,是针对有多值依赖的关系模式所定义的规范 化形式。 反例 1:下表表示关系 R4(设备名,厂站代码,生产厂家),如表 3-57 所示。 表 3-57 表示关系 R4 设备名 设备代码 生产厂家 引风机 101 匈牙利 引风机 101 沈阳风机厂 引风机 101 成都电力机械厂 引风机 102 沈阳风机厂 分析上表,对“设备名”的一个值,不论“生产厂家”取什么值,总有一组确定的“厂站代 码”与之对应,所以有:“设备名”→“设备代码”,同样分析有“设备名”→“设备代码”。 这说明 R4 不满足 4NF,此种关系模式有数据冗余和修改量大等弊端。可用分解法消除不满足 4NF 的非平凡多值依赖。解决办法:把 R4 分解为 R41(设备名, 设备代码),R42(设备名,生产厂家)。 反例 2: employee(employeeID,employeeName) skill(skillID,skillName) language(languageID,languageName) employee_skill_language(employeeID,skillID,languageID) 如表 3-58 所示。 表 3-58 数据冗余的实例 EMPLOYEE_ID SKILL_CODE LANG_CODE 作者:姜江 error 263 1 A - 1 - X5 1 - X1 1 B - 2 H - 2 - X2 2 A - 2 - X6 3 A - 3 - X7 我们发现,这样对空间是十分浪费的,此外,表中没有某列可以唯一确定该行作为主健,列 的组合也无法作为主键 假设我们设计表为: employee_language( employeeID,languageID) employee_skill( employeeID,skillID) 假定随着时间的消逝,员工的技巧和语言水平进一步提高,那么我们的表格可能就是: employee_language( employeeID,languageID,prof,date ) employee_skill( employeeID,skillID prof,date) 这样,既解决了空间浪费的问题,又解决了函数依赖的问题,读者可以仔细体会。 第五范式(5NF):如果关系模式 R 中的每一个连接依赖, 都是由 R 的候选键所蕴含,不会 产生有损连接,称 R 是第五范式。 前面我们提高范式等级的办法是分解,把一个关系用投影来代替,这些投影一般都能通过连 接得到原来的关系。但有一种关系不能无损分解成两个投影,而能分解成三个以上的投影。如图 1 中,关系 ABC 可分解成两个投影 AB 和 BC(或 AC 和 BC)。AB 与 BC 在上连接得 ABC2;ABC2 与 AC 再连接得 ABC3。显然关系 ABC2 中比关系 ABC 多出一元组(a2,b1,c2),称之为寄生元组。ABC2 与 AC 连接,得关系 ABC3,和原关系相同。所以关系 ABC 具有连接依赖 Join Dependency*(A,B,C)。 如图 3-94 所示。 作者:姜江 error 264 图 3-94 表之间的连接依赖 3.9.3 水平分割 水平分割主要是将一个表分成几个表,每个表都属于原始表的行的一个子集,他们都与原始 表一样包含相同的列。 水平分割通过将表中的行数减少来优化数据查询。 例如:表 Annual_Sales 包含以下几个列,如图 3-95 所示。 图 3-95 水平分割的模型实例 那么很有可能这个表中有大量的数据,于是我们可以使用 Horizontal Partitioning Wizard 通过将一个表分割来优化数据查询,我们可以以其中的任何一个列作为分割的标准。例如,在该 例中,我们按照年度来分割表,分别建立三张 2000/2001/2002 年的表,如图 3-96 所示。 图 3-96 水平分割形成的新模型 该方法的优点和缺陷: 水平分割能够允许你将一张大表分割为较小的表,以便:  改进查询响应时间  加速递增数据的备份和恢复  减少载入到索引表中的时间 然而,水平分割也同样意味着以下缺点:  为了从多个表中查询相关数据,必须创建连接(joins)和并集(unions) 作者:姜江 error 265  为了确定哪个表中包含所需数据,必须编写智能式的查询语句  使用额外的元数据(metadata)来描述经过分割的表格 使用 Horizontal Partitioning Wizard 对表进行水平分割,你可以选择分割后保留或者删除 原始表。你可以在工具或者表的右键菜单中找到水平分隔向导。 表 3-59 为向导中各页的含义。 表 3-59 水平分隔各向导页含义 向导页 描述 Partitioned Table Selection 选择当前模型中需要分割的表,如果表被选择,那么会出 现在 Partitioned Table 对话框中。如果在 Partitioning check 对话框后选择 Keep the Partitioned Table,则保 留原始表 Partition Definition 定义对表的分割,可以使用 Insert 或者 Add 工具添加,每 个分割出来的表的名字在模型中都是唯一的 Discriminant Column Selection 定义每个分割的表中不需要被复制的列,这些列就是分割 的标准,可以选择 Add Columns 选择不要复制的列 Partitioning Information 输入这次分割的相关对象的 name 和 code,我们把这个创建 的对象称为水平分隔对象 操作步骤如下: 1. 选择【Tools】→【Denormalization】→【Horizontal Partitioning】.或者右键表从 菜单中选择Horizontal Partitioning 2. 在Partitioned Table Selection窗口中选择表“国家” 3. 选中Keep the Partitioned Table After Partitioning check box 4. 在Partition Definition中输入以下几个名称,如图 3-97所示。 5. 点击【下一步】,在Discriminant Column Selection中选择我们新建的列“所属洲” (continent) 图 3-97 “Partition Definition”窗口 批注 [e15]: 该行是新添加的 作者:姜江 error 266 6. 输入name和code为continent_horizontal_partition,创建transformation 7. 点击【确定】按钮,我们发现原表所有的引用外键关系,在分割出来的表中都存在,如 图 3-98所示。 图 3-98 水平分割后的模型 注:我们可以通过选择【Model】→【Transformations】,即可查看到Transformation的列 表,可以双击查看其属性,也可以在List of Transformation窗口中,点击右上角的【Cancel a transformation】工具来取消转化。如果选择的表不是一个产生的对象,那么这里的取消工具是 灰化的,不可以操作。 点击【确定】按钮,PowerDesigner会删除该Transformation对象,同时创建原始表。 3.9.4 垂直分割 垂直分割主要是将一个表分成几个表,每个表都包含原始表的列的一个子集,他们都与原始 表一样包含相同的主键和相同的行数。 例如:表 Customer 包含以下几个列,如图 3-99 所示。 图 3-99 垂直分割的模型实例 可以根据表的不同的方面将表分为两张表,例如,可以使用 Horizontal Partitioning Wizard 将客户表分为客户信用等级表和客户地址表: 作者:姜江 error 267 图 3-100 垂直分割结果实例 垂直分割使得查询可以扫描较少的数据,从而改进响应时间。还可以通过垂直分割实现不同 级别的数据保护,比如说把某些重要信息存放在特殊的分割表中。但是我们不可否认,垂直分割 也会带来以下问题:  为了从多个表中查询相关数据,必须创建连接(joins)和并集(unions)  为了确定哪个表中包含所需数据,必须编写智能式的查询语句  使用额外的元数据(metadata)来描述经过分割的表格 使用 Vertical Partitioning Wizard 对表进行垂直分割,你可以选择分割后保留或者删除原 始表。你可以在工具或者表的右键菜单中找到水平分隔向导。 表 3-60 为向导中各页的含义。 表 3-60 垂直分割各向导页含义 向导页 描述 Partitioned Table Selection 选择当前模型中需要分割的表,如果表被选择,那么会出 现在 Partitioned Table 对话框中。如果在 Partitioning check 对话框后选择 Keep the Partitioned Table,则保 留原始表 Partition Definition 定义对表的分割,可以使用 Insert 或者 Add 工具添加,每 个分割出来的表的名字在模型中都是唯一的 Discriminant Column Selection 定义包含在每个表中的不同的列。可是使用 Add 按钮从原 始表中添加列。主键列在这里不出现,因为在每个分割出 来的表中都会包含该列。选择好所有的列之后点击【下一 步】按钮。 Partitioning Information 输入这次分割的相关对象的 name 和 code,我们把这个创建 的对象称为水平分隔对象 1. 为“学生”表添加两个字段“年龄”(age/smallint)“已婚”(isMarried/bit) 2. 选择【Tools】→【Denormalization】→【Vertical Partitioning】。或者右键表从菜 单中选择Vertical Partitioning 3. 在Partitioned Table Selection窗口中选择表“学生” 4. 选中Keep the Partitioned Table After Partitioning check box 5. 在Partition Definition中输入以下几个名称,如图 3-101所示。 作者:姜江 error 268 图 3-101 定义垂直分割分区 6. 点击【下一步】按钮,在 Partition Column Selection给分割表分配相应的列,如图 3-102 所示。 图 3-102 为分割表分配列 7. 输入name和code为student_vertical_partition,创建transformation 8. 点击【确定】按钮,我们同样发现原表所有的引用外键关系,在分割出来的表中都存在 同样,我们也可以通过选择【Model】→【Transformations】,即可查看到 Transformation 的列表,查看属性,在必要的时候 Revert 垂直分割。 3.9.5 “打碎”表的关系 Table collapsing 通过将几个表合并为一个表,从而减少表之间的连接提高查询效率。 使用该方法生成的表将几个合并表中的列汇集在了同一张表中。所有的原始表的相关的外键 引用在生成的表中也依然保留。那些被“Collapsed”的表之间如果有引用关系,那么:  连接的 parent 列(外键)不再需要,自动删除  附表中的列被复制  子表中的外键被删除,但是他们的列在最后生成的表中被保留 例如下面的客户表和订单表之间存在关联,如图 3-103 所示。 图 3-103 模型实例 作者:姜江 error 269 我们可以通过将两个表 Collapse 两个单独的表,从而减少表之间的 join,进一步优化数据 查询的效率。对上面客户订单两张表的优化结果是产生两张同名的表,使用 child table(子表) 的主键,如图 3-104 所示。 图 3-104 打碎生成的表 使用 Table Collapsing Wizard 对表进行“打散”,你可以对几个存在外键关联的表或者是具 有相同主健的表进行 collapsing,同时还可以选择分割后是否保留原始表。在工具或者表的右键 菜单中都可以找到水平分隔向导。 各向导页的含义参考表 3-61。 表 3-61 Table Collapsing 各向导页含义 向导页 描述 Table Collapsing Target 根据选择的需要 Collapse的表,定义结果表的name 和code Input Table Selection 选择要 Collapse 的表,如果表被选择那么会出现在列表中, 可以使用 Insert 或者 Add 工具添加,每个分割出来的表的 名字在模型中都是唯一的,如果选择了 Keep the Input Tables After the Table Collapsing ,则这次 transformation 后原始表仍然保留 Table Collapsing Information 输入这次分割的相关对象的 name 和 code,我们把这个创建 的对象称为 table collapsing 对象 1. 选择【Tools】→【Denormalization】→【Table Collapsing】。或者右键表之间的引 用从菜单中选择Vertical Partitioning 2. 在Table Collapsing Target窗口中输入name和code为student_class 3. 在Input Table Selection 窗口选择需要collapse的表“学生”和“班级”,同时选中 Keep the Partitioned Table After Partitioning check box 4. 在Table Collapsing Definition中输入name和code为:stu_class_table_collapse 5. 点击【确定】按钮。同样,原表所有的引用外键关系,在分割出来的表中都存在 通过选择【Model】→【Transformations】,可查看 Transformation 的列表中包含我们刚才 创建的 transformation 对象 stu_class_table_collaps,通过双击可查看属性,在必要的时候 Revert 垂直分割。 作者:姜江 error 270 3.9.6 对列进行非范式化 Column denormalization 使用对象复制技术,可以通过对列进行非范式化,减少表之间的频 繁的关联。 例如图 3-105 所示。 图 3-105 对列非范式化模型实例 我们希望能够为每个 employee 打印出包括部门名称的工资单,但是,有与表之间的关联过于 复杂,也比较繁琐,会造成速度的显著下降,因此我们可以对列进行非范式化,直接在 PaySlip 中加入列:Div_Name,如图 3-106 所示。 图 3-106 列非范式化产生的表 对列进行非范式化可以减少很多查选涉及到的表之间的关联,但是,也造成了磁盘空间的浪 费,并且需要经常的维护才能保证数据的一致性。 使用 Column Denormalization Wizard 对列进行非范式化,能够从某个特定的表中复制列。 在工具或者表的右键菜单中都可以找到水平分隔向导。 各向导页的含义参考表 3-62。 表 3-62 列非范式化各向导页含义 向导页 描述 Target Table Selection 选择要往哪些表中复制列,即目标表。如果我们在图形模 型中选定了某个表,那么默认在 Target Table Selection 对话框中就会出现 Selection 选择需要复制给目标表的一个或者多个列 作者:姜江 error 271 1. 选择【Tools】→【Denormalization】→【Column Denormalization】。或者右键表之 间的引用从菜单中选择Column Denormalization 2. 在Target Table Selection 窗口选择目标表“学生” 3. 在Selection选中需要复制的列 4. 点击【确定】按钮。同样,原表所有的引用外键关系,在分割出来的表中都存在,只是 在目标表中增加了我们需要复制的列。 3.10 设计数据库的访问控制(Access) 在这一节中我们将学习如何使用 privileges、permissions,以及定义用户、组、角色、object synonyms 等对象管理对数据库的存取。 3.10.1 访问控制的基本概念 数据库访问管理的目的,是为了保证用户在使用数据库执行他们的任务的同时,确保数据库 中数据的保密性以及信息的完整性。数据库必须具有坚固的安全系统,才能控制可以执行的活动 以及可以查看和修改的信息。无论用户如何获得对数据库的访问权限,坚固的安全系统都可确保 对数据进行保护。不同的 DBMS 对数据库访问权限的设计也是不尽相同的,但是大致都通过以下几 种手段来进行访问管理:  创建 users(用户)、groups(组)以及 roles(角色)  对 users、groups 和 roles 定义不同的访问权限(privileges)  对数据库对象定义 permission(访问权限) PowerDesigner 的物理数据模型支持这些概念,并且允许:在反向工程的时候获得数据库中 访问控制的元素,同时允许我们在 PDM 中设计并且可以将我们的安全设计生成到数据库中。 注意:如果是从脚本反向工程,必须确保 permission 和 privilege 的脚本和定义 users、 groups、roles 的脚本在同一个脚本文件中。 3.10.2 定义用户/角色/组(user/role/group) 管理数据库的用户 允许连接数据库的人被称为用户,用户可以被分配角色,而角色中规定了它们作为数据库用 户的职责,也可以把用户分配在组中。 在这节中我们将学习如何定义数据库的用户、角色和组。 值得注意的是,不是所有的 DBMS 都支持 user、role 和 group。例如:Sybase Adaptive Server Anywhere 就不支持 role。 在数据库中,user 可以拥有对象,创建 user 之后可以将对象和它们之间建立联系。在数据 作者:姜江 error 272 库中,user 创建对象(表、视图、存储过程等),拥有这些对象,同时,自动获得了该对象的所 有操作。 在 PDM 中,可以在 object 和 user 之间建立连接,使得 user 成为对象的 owner,每个对象在 同一个时间内只能有一个所有者。例如,你创建了一个表,默认情况下没有所有者,可以从 user 列表中选择一个 user 作为该表的 owner。 所有者的一个作用就是用来管理 PDM 中对象的修改,在某个模型中,如果有很多人都可以访 问一个对象,就可以将该对象的修改权限限制在 owner 上,同时为其他用户定义适当的权限。在 生成数据库的时候,也可以按所有者来生成数据库。 创建用户(user)的步骤如下: 1. 选择【Model】→【Users and Roles】→【Users】,弹出窗口,显示 user 的列表 2. 点击一个空白行或者点击【Add a Row】工具 3. 输入 user 的 name 和 code 为“jiangj”, 点击【Apply】按钮应用 4. 双击该行,或者点击属性工具 ,弹出 user 属性窗口 5. 可以在 Password 输入框中输入密码,点击【确定】按钮 至此,一个用户就创建成功。注意:我们在这里没有规定该用户的权限以及它所属的角色和 组,我们将在后面陆续介绍这些知识。 要将对象和用户关联起来,只需要在图形模型中双击对象(举例为表“学生”),弹出属性窗 口中在 Owner 下拉列表中选择该 user。 创建角色(role)的步骤如下: 1. 选择【Model】→【Users and Roles】→【Roles】,弹出窗口,显示 roles 的列表 2. 点击一个空白行或者点击【Add a Row】工具 3. 输入 role 的 name 和 code 为“Designer”, 点击【Apply】按钮应用 4. 双击该行,或者点击属性工具 ,弹出角色属性窗口 至此,一个角色就创建成功。注意:我们在这里没有规定该角色的权限,我们将在 3.10.3 数 据库权限(privilege)和 3.10.4 对象的访问许可(permission)中陆续介绍这些知识。 要将角色分配给用户的操作步骤如下:在具体的角色的属性窗口中,进入 Users 属性页,点 击添加对象工具 ,在弹出的选择对话框中选择我们刚才创建的用户“jiangj”,然后在所有的 窗口中点击【确定】按钮即可。 创建组(group)的步骤如下: 组是为了方便分配权限而设计的,这样可以避免对每个个别用户分配权限时既费时又容易出 错的情况出现。 1. 选择【Model】→【Users and Roles】→【Groups】,弹出窗口,显示组的列表 批注 [e16]: 此处原先编号有错误,已 更正 作者:姜江 error 273 2. 点击一个空白行或者点击【Add a Row】工具 3. 输入 Group 的 name 和 code 为“admin”, 点击【Apply】按钮应用 4. 双击该行,或者点击属性工具 ,弹出组属性窗口 至此,一个组就创建成功。注意:我们在这里没有规定该 Group 的权限,我们将在 3.10.3 数 据库权限(privilege)和 3.10.4 对象的访问许可(permission)中陆续介绍这些知识。 要将用户分配给组的操作步骤如下:在组的属性窗口中,进入 Users 属性页,点击添加对象 工具 ,在弹出的选择对话框中选择我们刚才创建的用户“jiangj”,然后在所有的窗口中点击 【确定】按钮即可。 3.10.3 数据库权限(privilege) 系统 privilege 是一系列分配给数据库用户、组和角色的权力。定义这些 privilege 可以的 目的是为了对不同数据库用户定义的补充。系统 privileges 将不同用户的特征抽取出来,这些用 户对数据库的内容有或多或少的影响。 系统 privilege 必须和对象 permission 关联起来才能够评价用户、组和角色的权力。例如: 如果一个用户有修改权限,但是他却不能修改一个他不具有 update 许可的对象。 在有些 DBMS 中,系统 privilege 被称为 permission。我们这里将 privilege 定义为针对不 同的用户、组和角色分派权力,而将 permission 则用于对象的权限管理。 系统 privilege 随着 DBMS 的不同而不同,系统 privilege 如果被分配给一个用户则表示该用 户具有了这种特定的权限。用户如果具有管理权限,也可以将权限撤回(revoke),这将阻止某些 用户在数据库上特定的操作权限。 定义系统 privileges : 可以对用户、组、角色定义 privilege,只需要在这些对象的属性也中定义即可,它们的定 义步骤都是完全相同的,因此,这里我们以为用户定义 privilege 为例。 默认情况下,如果用户属于某个组或者具有一种角色,那么它将继承组合角色的权限。继承 的权限在用户权限属性页中出现。如果为用户选择了特定的权限,则这些权限在组权限的上方显 示。表 3-63 列出了各种权限的组合。 表 3-63 不同权限的含义 权限组合 描述 (蓝色) 分配给用户的权限 (红色) 从组中继承的权限 批注 [e17]: 此处已修改 作者:姜江 error 274 (上蓝下红) 从组中继承权限,但是将该用户的权限收回 (上蓝下红) 该 privilege 从组或者角色中继承,并且用“with admin option” 重载,表示获得该权限的用户可以将权限分派给其他用户 为用户定义系统 privilege 的方法如下: 1. 选择【Model】→【Users and Roles】→【Users】,弹出窗口,显示 user 的列表 2. 打开我们刚才创建的用户“jiangj”的属性窗口,进入 Privileges 属性页 3. 点击【Add Privileges】工具 ,弹出一个选择窗口,这里列出了当前 DBMS 中经授权 的 privileges 4. 选择一个或者多个需要的权限,如图 3-107 所示。 5. 点击【确定】按钮。 图 3-107 为角色选择权限 6. 为 Role“designer”定义适当的 privilege(BACKUP DATABASE 和 BACKUP LOG),因为用 “jiangj”属于该角色,所以会发现在下面窗口中能够有红色打钩的图标,表示从角色或 者组中继承的权限。 7. 可以选择继承的权限,然后点击下方的【revoke】工具,收回该用户的 BACKUP DATABASE 权限,或者进行其他的修改。或者直接选中某行,然后用鼠标点击 State 单元格,图中会 显示相应的状态的变化,一支调整到自己需要的权限组和为止。如图 3-108 所示。 8. 点击【确定】按钮。 作者:姜江 error 275 图 3-108 为 User 定义权限 3.10.4 对象的访问许可(permission) 对象的 permission 表示对象的访问许可,它用于在一些特定的数据库对象上限制特定的用 户、组和角色的访问。 在 PowerDesigner 中,可以为表、视图、列、存储过程、包以及其他和 DBMS 相关的对象的 permission(访问许可)。 对象的 permission 在不同的 DBMS 中也是不同的,一些常见的 permission 如表 3-64 所示。 表 3-64 常见 Permission 类型 Permission 描述 Select 查看某对象中的信息 Insert 在对象中插入行 Alter 使用 ALTER TABLE 命令修改表 Delete 从对象中删除行 References 在表和外键参考表之间创建索引 Update 更新对象中的行 Index 使用 CREATE INDEX 命令创建索引 Execute 执行存储过程或者函数 对象的所有者(owner)自动拥有该对象的所有 permission。这些 permission 不在 Permission 的属性页中显示,但是在生成的时候或者反向工程的时候都会自动产生。 为用户创建 permission 的步骤如下: 1. 选择【Model】→【Users and Roles】→【Roles】,弹出窗口,显示 user 的列表 2. 打开我们前面创建的角色“Designer”的属性窗口,进入 Permission 属性页 作者:姜江 error 276 3. 点击【Add Objects】工具 ,弹出一个选择窗口,选择需要定义 permission 的对象(选择 “教师”、“课本”、“课程”三个表),选择 permission,如图 3-109 所示。 图 3-109 为 Role 定义 Permission 4. 选择【Model】→【Users and Roles】→【Users】,弹出窗口,显示 user 的列表 5. 打开我们刚才创建的用户“jiangj”的属性窗口,进入 Privileges 属性页 6. 点击【Add Objects】工具 ,弹出一个选择窗口,选择需要定义 permission 的对象(选择 “教师”、“课本”、“课程”三个表) 此时,因为用户“jiangj”继承了角色“Designer”的 permission,继承的 permission 显示为红色选项,如图 3-110 所示。 图 3-110 为用户定义 Permission 如果用户不希望看到从角色或者组中继承过来的 permission,在该属性页的上方有两个 工具可以在是否显示这些继承的 permission 之间切换,点击【Hide Inherited permissions】 作者:姜江 error 277 工具 隐藏所有的继承的 permission,或者通过点击【Show all Inherited permission】 工具 来显示继承的 permission。 7. 可以选择继承的权限,然后点击下方的【revoke】、【Grant with grant option】、【revoke with】 等工具,,或者直接选中某行,然后用鼠标点击个 permission 对应的单元格,图中会显示相 应的状态的变化,一支调整到自己需要的权限组和为止,如图 3-111 所示。 图 3-111 选择继承的权限 关于 permission 组和的图形显示的含义如表 3-65 所示。 表 3-65 Permission 组合图形及其含义 Permission 组和 描述 (蓝色) 分配给用户的 permission (红色) 从组或者角色中继承的 permission (上蓝下红) 该 permission 从组或者角色中继承,但被收回 (上蓝下红) 该 permission 从组或者角色中继承,并且用“with admin option” 重载,表示获得该权限的用户可以将权限分派给其他用户 (上蓝下红) 该 permission 从组或者角色中继承,但是使用 cascade 方式从 该用户处收回 其中 cascade 方式表示该用户不再享有这种 permission,同样,所有接受该用户授权的用户 今后都不具有这项 permission,我们可以理解为“株连九族”。 在对象属性窗口中定义 Permission 除了直接对 user、group 和 role 定义 permission 之外,我们还可以在对象属性窗口中定义 permission,操作办法如下: 作者:姜江 error 278 1. 在图形模型中双击某对象的图符(这里双击表“学生”),弹出对象的属性窗口 2. 进入 Permission 属性页,点击【Add Objects】工具 ,弹出一个选择窗口,选择用户,注 意 1:有些读者可能会发现有的 user 明明定义了,在这个窗口确定看不到,一般而言,这种 情况往往都是因为已经将该对象的 owner 定义为该用户,这样该用户就自动获得了这个对象 的所有权限,也不需要在这个选择窗口中再次出现。如果改变 owner,即可在选择窗口中看到 该 user 注意 2:在弹出的选择框中可能没有用户定义的 role 或者 group,这是因为读者在 Permission 属性页中针对的是 user 进行的选择,如图 3-112 所示。可以在手指向的地方选择 role 或者 group: 图 3-112 为表定义 Permission 对列进行 permission 定义 除了对表进行定义 permission 以外,还可以通过对列的 permission 进行定义,这样就可以 实现对 permission 的进一步调整与细化。各种 DBMS 支持的列的 permission 都包含在 DBMS 的原 文件中,生成 privilege 的时候,可能不支持新创建的或者经过修改的 permission。 具体的操作步骤如下: 在上图的右下方点击 Columns 后边的省略号 工具,在弹出的窗口中为每个列定义 permission,如图 3-113 所示。 作者:姜江 error 279 图 3-113 为列定义 Permission 定义好之后点击【确定】按钮,在表的 permission 属性页中可以看到 Select 和 Update 中的 图符都变成了省略号的标记 ,这表明有列对该 permission 进行了定义,如图 3-114 所示。 图 3-114 列定义 Permission 后在表中的反映 3.10.5 生成权限控制(privilege)脚本 我们在 PowerDesigner 中设计的关于权限控制的模型也可以通过 PowerDesigner 以两种方式 生成,一种是 ODBC 的方式,另一种是直接生成可以执行的脚本的方法。 具体的操作步骤如下: 1. 选择【Database】→【Generate Privileges】,弹出生成 privilege 窗口,如图 3-115 所示。 图 3-115 “Previleges Generation”窗口 作者:姜江 error 280 2. 如图 3-115 所示,可以在 Privileges 属性页中选择是否要在生成 users 和 roles 之前先删除 同名的对象,是否要生成 users 和 roles,以及它们相对应的 privileges 3. 在 Options 属性页中选择生成的一些选项 4. 在 Selection 属性页中选择需要 users、roles 和 groups 5. 点击【确定】按钮。 关于一些选项的具体含义,以及如何操作该生成过程,可以参考:3.6 使用 PowerDesigner 创 建数据库生成脚本(SQL 脚本)_在 PowerDesigner9.5 中创建和操作 PDM。 ====================================================================== /*==============================================================*/ /* Database name: test1 */ /* DBMS name: Microsoft SQL Server 2000 */ /* Created on: 2003-11-21 23:57:32 */ /*==============================================================*/ sp_revokedbaccess jiangj go sp_droprole Designer go /*==============================================================*/ /* User: jiangj */ /*==============================================================*/ sp_grantdbaccess jiangj go /*==============================================================*/ /* Role: Designer */ /*==============================================================*/ sp_addrole Designer go sp_addrolemember Designer, jiangj go ========================================================================== 这段脚本在 SQL Server 2000 的 Query Analyzer 中往往不能正确执行,要解决该问题,请参 考第 7 章 高级应用&网友常见疑难解答(FAQ)7.8 问题八。 3.10.6 定义同义词 A.同义词的概念 作者:姜江 error 281 同义词是各种对象(表、视图、sequence、存储过程、函数、同义词或者数据库包)的别名。 通常,别名都是由数据库管理员创建,主要用于:  隐藏对象的名称和所有者  在分布式数据库中使得远程对象位置透明  为数据库用户简化 SQL 语句 例如:表“学生”的所有者是用户“jiangj”,那么一个标准的查询语句可能是:Select * from jiangj.student, 数据库管理员可以创建该表和所有者一个同义词,叫作 student,这样,语句 就可以被简化为:select * from student 在 PowerDesigner 中,用于创建同义词的对象被称为 base object(基础对象)。每个 base object 可以有多个同义词,而一个同义词则至少要有一个 base object。可以在 base object 的 Dependencies 属性页中查看同义词对 base object 的依赖,如果删除了 base object,则同义词 也会被删除。 不是所有的 DBMS 都支持同义词,例如:SQL Server 2000 就不支持,为了便于操作,我们可 将 DBMS 暂时切换为 Oracle version 9i。 B.创建同义词 同义词没有图形符号,可以在 Browser 中或者同义词的列表中创建。创建的步骤如下: 1. 选择【Model】→【Synonyms】,弹出同义词列表窗口 2. 点击【Create synonyms from a selection of objects】 3. 弹出选择窗口,不同的属性页中列出了当前模型中的各种对象 4. 选择需要定义同义词的对象,点击【确定】按钮 5. 双击该行,或者点击属性工具 ,弹出同义词属性窗口 6. 可以点击 Base object 后面的省略号按钮 ,可以更换基础对象 7. 选择 visibility 为 public,输入 name 和 code 8. 点击【确定】按钮。 表可以创建视图,同样,我们也可以为同义词创建视图,创建的方法是:选择 Tools->Create view,在弹出的窗口中进入 Synonyms 属性页,选择需要定义为视图的同义词,确定,其它操作和 为表创建视图相同,可以参考:3.4.6 创建视图(View)。 C.生成同义词 和我们前面定义的各种数据库元素一样,同义词也可以生成脚本或者直接通过 ODBC 生成,具 体的操作步骤如下: 1. 选择【Database】→【Generate Synonyms】,弹出生成同义词窗口 2. 选择生成脚本或者通过 ODBC 生成,选择脚本存放路径,输入文件名称 3. 在 Synonyms 属性页中选择为那些基础对象生成同义词,以及是否要创建同义词,是否在创建 之前删除同名的同义词。如图 3-116 所示。 作者:姜江 error 282 图 3-116 选择要为哪些对象创建同义词 4. 在 Selection 属性页中选则需要创建的同义词,在 Options 属性页中规定其他的选项 5. 点击【确定】按钮。生成代码示例如下: =============================================================================== /*==============================================================*/ /* Database name: test1 */ /* DBMS name: ORACLE Version 9i */ /* Created on: 2003-11-22 21:14:00 */ /*==============================================================*/ drop public synonym "jiangj"."stud" / /*==============================================================*/ /* Synonym: "stud" */ /*==============================================================*/ create or replace public synonym "jiangj"."stud" for "jiangj"."student" / =============================================================================== 3.11 将其他软件模型转化为 CDM 3.11.1 将 Erwin 的模型导入 CDM Erwin 的模型可以很容易就导入到 PDM 中,而且不会丢失任何元数据(metadata)。 PowerDesigner 通在 CDM、PDM 以及 OOM 之间提供过可靠的转化提供了完整的灵活性,保证了模型 的高度透明性和灵活性。将 Erwin 的模型迁移到 PDM 中有以下好处:  以往分散的逻辑和物理数据库设计将能通过这种迁移使用同一个逻辑模型来实现不同 的物理实现  PDM 提供了 ER-win 中不具备的强大的面向对象模型的技术 作者:姜江 error 283 Erwin 和 PowerDesigner 的 PDM 之间的对象转化对应关系如表 3-66 所示。 表 3-66 Erwin 和 PDM 对象转化对应关系 Erwin 模型中的对象 PDM 中导入的对象 Model Model Stored display and subject area Diagram Business rule Business rule Domain Domain Key Key Table Table Relationship Relationship Index Index View Table View Fact,dimension,outrigger Table Target database Current DBMS Tablespace Tablespace Segment Storage Symbols(including size and positions) Symbols(including size and positions) Description Description Notes Annotation Text block Text symbol 不足之处(局限性): 不能将 Erwin 中的 Trigger(触发器)和 Stored Procedures(存储过程),ERwin 中用户定 义的属性,Erwin Report 或者 ER1 文件导入到 PDM 中,同样 Erwin 中的数据源和目标客户端 (clients)也能不能导入 PDM。 从 Erwin 模型迁移到 PDM 模型的步骤如下: 1. 选择【File】→【Import】→【Erwin File(Physical Data Model) 】,弹出标准的打开 2. 在打开窗口中文件类型选择 Erwin files:3.5.1 or higher (*.erx),选择需要导入的 Erwin 文件 3. 点击【打开】按钮,会弹出一个进度条的窗口显示模型转化的进度,完成时导入的 PDM 会在 PowerDesigner 中自动处于打开状态,并且在 Diagram 中显示导入的模型对象的图形。 3.11.2 将 PD6 的模型迁移到 PDM 从 PowerDesigner 6 中迁移 CDM 以及 CDM 生成的对应的 PDM 到 PowerDesigner 9.5 中, 作者:姜江 error 284 PowerDesigner 9.5 在导入的过程中会自动将保留 CDM 和 PDM 之间的生成连接。所以,如果有已 经修改过的已经迁移到 PD9.5 中的 CDM 和 PDM,希望从当前 CDM 重新生成 PDM,可以选择 Preserve Modifications 选项,这样就会保留 PDM 中的修改。 如果选择同时导入 PD6 中的 CDM 和它相应 PD6 中的 PDM,则可以保证在迁移的过程中模 型可以同步。迁移的过程是先导入概念模型,然后导入对应的物理模型。 一个 CDM 有时候可能生成过几个 PDM,如果你在导入 CDM 后没有导入其中的某个 PDM, 现在又希望在 PD9.5 中导入这些 PDM,就必须重新导入 CDM,同时选择需要导入的由该 CDM 生成的 PD6 中的 PDM。否则,以前导入的 CDM 就不能和后面导入的 PDM 保持同步。 从 PD6 中的 PDM 迁移时,可以选择打开:  Archived models(*.apm):可以避免丢失 PD6 中约束的 name,因为存档模型会保留所有 的约束的名称而不会区分用户定义的和计算约束(calculated constraint)的区别。  Standard models(*.pdm):有可能丢失约束名称,因为标准模型不会保存计算约束 (calculated constraint)的名称(name)。 具体的操作步骤如下: 1. 选择【File】→【Import】→【V6 Synchronized Models】,弹出 Import V6 Synchronized Models 窗口,如图 3-117 所示。 图 3-117 选择要导入的 PD6 的模型 2. 在 Conceptual Data Model to import 中点击【Open CDM source file】工具 ,在弹出的窗口中 选择要迁移的 CDM 文件 3. 在 Physical Data Model to import 中点击【Add PDM files】工具 ,选择要导入的 PDM 模型 4. 点击【OK】。导入成功后 CDM 的名称先出现在 Workspace 的目录树中,然后出现 PDM,这 样恰好说明了它们的依赖顺序,导入完毕后,在 Diagram 工作区仍然显示 CDM 的图形模型 5. 保存 CDM 和 PDM 以及当前的 Workspace。 3.12 PDM 模型的检查(Check) 正确的 PDM 必须符合以下规则: 作者:姜江 error 285  每个对象的名称必须是唯一的  模型的约束必须和数据库的约束兼容  每张表至少包含一个列  每个索引至少包含一列  每个引用至少包含一对列 我们前面提到,在我们生成数据库脚本之前,PowerDesigner 自动会先对模型进行检查,笔 者也推荐这样做,如果模型中有错误(不包括警告),那么数据库脚本或者 ODBC 数据库就不能生 成。但是,如果读者不希望每次生成数据库之前都对模型 Check,可以在生成数据库的窗口 Options 属性页中将复选框“Check Model”去掉即可。 3.12.1 模型检查的选项(Options) 检查 PDM 时,可以针对不同的对象的不同参数定义的不同级别的严重性,而这种严重性级别 的规定则依赖于你的模型希望达到的规范化程度。 检查模型的时候,不合法的参数往往以两种形式的消息显示出来,这也依赖于你对该参数定 义的问题严重性级别。一种是:Error,表示生成数据库有较大的破坏作用;另一种是 Warning, 表示问题不是很严重,或者仅仅是一种建议。 此外,还可以对某些特定的问题自动纠正。但是在使用自动更新功能以前,希望读者能够确 切的理解使用它对模型会产生哪些影响作用。例如某列的 code 的长度超过了特定 DBMS 的 MaxColumnLen(最大列长度),PowerDesigner 会自动将该列截短。但是也必须注意,截短这种列 的长度有可能导致产生一个和其他的列同名的列。如果列名唯一性(column code uniqueness) 处于激活状态,那么 PowerDesigner 就会重命名这个同名的列的 code,这也许是你不希望看到的, 因为 PowerDesigner 的重命名方式可能不符合你的定义需求,这种情况下,你就必须使 PowerDesigner 不对列名唯一性(column code uniqueness)的进行自动化纠正(automatic correction)。当然,也不是所有的问题都可以自动纠正。例如:PowerDesigner 不会为某个 index 创建列,你必须在 index 的属性页中手动添加。 1.选择【Tools】→【Check Model】或者按快捷键【F4】,弹出 Check Model Parameters 窗口,如图 3-118 所示。 作者:姜江 error 286 图 3-118 “Check Model Parameters”窗口 可以在窗口上方选择三种不同的工具,为不同对象的不同参数的严重级别进行定义,也可以 规定是否对某对象某参数进行检查,如表 3-67 所示。 表 3-67 模型检查窗口错误级别 工具 表示 含义 (red) Error 表示是阻碍生成数据库的主要问题 (yellow) Warning 表示问题不大,或者仅仅是一种建议 (red) Automatic correction 允许对错误的自动纠正 2.在 Selection 属性页中选择我们需要检查的模型 test,点击【确定】按钮,Result List 中显示,如图 3-119 所示。 图 3-119 检查结果列表窗口 在后面部分我们将陆续向大家介绍个对象的参数,以及如何利用 PowerDesigner 提供的工具 对模型的出现的问题纠正。 3.12.2 模型所检查的涉及的内容 下面是 Check Model Parameters 窗口中 Options 属性页中的各对象及其检查参数: 对象:Table ,下表为表的检查参数 表 3-68 表的检查参数 参数 含义 手动纠正 自动纠正 作者:姜江 error 287 Table name and code uniqueness 一个模型中不能包含两 个具有相同 name 和 code 的表 修改表名称 对某个表名称 进行修改,在 后面加上一个 数字 Table name and code length 表的 name 或者 code 长 度超过 DBMS 规定的最 大长度 修改长度使得在规 定范围内 截取名称一部 分,使长度在 规定范围内 Constraint name conflict with index name 表约束的名称不能和索 引名称一样 修改表约束的名称 - Existence of column , reference,index,key 一张表至少包含一个 列,一个索引,一个主 键以及一个引用 在表中添加缺少的 元素 - Number of auto-incremented columns 自动增加的列包含了自 动计算的值,一个表中 不能包含超过一个的自 动增加的列 只留下一个自动增 加的列 - Table index definition uniqueness 对同一个列索引的索引 被称为 identical index,表中不能包含 identical index 删除索引或者修改 属性 — Table mapping not defined 如果模型中的一个表包 括一个或者多个数据 源,,那么必须在数据源 中建立表视图的映射, 从而建立关系和关系之 间的映射 对模型中的表或者 视图进行映射 破坏列的映 射。这个操作 删除了那些没 有被映射的列 Existence of permission Permission 表 示 针 对 用户或者组或者角色对 表使用权限的额控制 为表对 users , roles,groups 定义 权限 — 对象:Column,下表为列的检查参数 表 3-69 列的检查参数 参数 含义 手动纠正 自动纠正 Column name and code uniqueness 一个模型中不能包含两 个具有相同 name 和 修改列名称 对某个表名称进 行修改,在后面 作者:姜江 error 288 code 的表 加数字 Column code length 列 code 长度超过 DBMS 规定的最大长度 修改长度使得在规 定范围内 截 取 名 称 一 部 分,使长度在规 定范围内 Domain divergence domain 的数据类型和 列的数据类型不一致 在 Model Options 窗口中选择强制一 致性复选框 使用 domain 的数 据类型覆盖列的 数据类型 Column mandatory 某些 DBMS 中,包含在主 键或者唯一索引中的列 不可为空 在列的属性窗口中 选中 Mandatory 复 选框 将列定义为 Mandatory Inconsistency in check parameters 在 check 属性页中输入 的参数(minimum , maximumdefault,或者 值的列表)存在矛盾 修改各值使得各参 数不矛盾 - Data type precision and length 数据的小数点后位数不 能超过总长度,有些 DBMS 却可以 使数据长度大于小 数点后位数长度 — Undefined data type 所有的列应该都有数据 类型 在列属性的窗口为 列选择数据类型 — Foreign key column datatype and constraint parameters divergence 主键或后选键以及外键 列之间的数据类型和约 束参数要保持一致 修改外键的数据类 型以及约束参数使 之一致 父列的数据类型 和约束参数覆盖 外键列 Column with sequence not in key Sequence 用于初始化 主键,应该包含在主键 中 将 sequence 列作为 主键的一部分 — Auto-incremented column with data type not numeric 自动增加的列的数据类 型应该是数字型的 更改列的数据类型 将数据类型修改 为 numeric Missing computed column expression 计算列应该有定义好的 表达式 在列的 detail 属性 页增加计算表达式 — Existence of permission Permission 表 示 针 对 用户或者组或者角色对 列使用权限的控制 为列对 users , roles,groups 定义 权限 — 对象:Table Key ,下表为 key 的检查参数 作者:姜江 error 289 表 3-70 Key 的检查参数 参数 含义 手动纠正 自动纠正 Key name and code uniqueness 一个模型中不能包含两 个具有相同 name 和 code 的 key 修改 key 的 name 和 code 对某个表名称 进行修改,在 后面加上一个 数字 Key code length Key 的 code 长度超过 DBMS 规定的最大长度 修改长度使得在规 定范围内 截取名称一部 分,使长度在 规定范围内 Key column exists 每个键至少包含一列 在 key 属性页中为 key 增加列 删除没有列的 key Key inclusion Key 不 能 包 含 其 他 的 key 删除包含在 key 中 的 key - Multi-column key has sequence column 因为是 sequence 的列 本 身 已 经 是 一 个 key 了,所以就不能包含在 多列组成的 key 中 将是 sequence 的列 从多行组成的列中 分离出来 - 对象:Reference ,下表为引用的检查参数 表 3-71 引用的检查参数 参数 含义 手动纠正 自动纠正 Reference name and code uniqueness 一个模型中不能包含两 个具有相同 name 和 code 的 Reference 修改 Reference 的 name 和 code 对某个表名称 进行修改,在 后面加上一个 数字 Reference code length Reference 的 code 长度 超过 DBMS 规定的最大 长度 修改长度使得在规 定范围内 截取名称一部 分,使长度在 规定范围内 Reflexive mandatory reference 自反引用不应该存在可 能会导致不一致 join 的不可为空的父列 不选取 Mandatory 选框 — Existence of reference join 一个引用至少包含一个 引用联接 为引用创建引用联 接或者删除引用 删除没有联接 的引用 Incomplete joins 联接必须是完整的 选择一个外键列或 者激活主键列的 - 作者:姜江 error 290 migration Join order 在某些 DBMS 中,联接的 顺序必须和键的顺序一 致 如果需要,改变联 接的顺序以反映键 中列的顺序 联接的顺序改 变为键中列的 顺序 除了 Check Model Parameters 窗口中 Options 属性页中的各对象及其检查参数以外,还有: Horizontal partitioning check/Table collapsing check/Vertical partitioning check/ Business Rule check/User check/Group check/Role check/Domain check/Index check /Trigger check/View reference check/View check/Synonym check/Database package check / Database package procedure check / Database package cursor check / Database package variable check/Database package type check/Database package exception check /Procedure check/Data source check/File object check/Cube check/Fact check/Fact measure check / Dimension check / Attribute check / Dimension hierarchy check / Association check/Join index check/Replication check,关于这些检查的对象及其参数, 读者可以自己学习。 3.12.3 根据检查结果纠正模型 现在我们使用 PowerDesigner 检查模型,并且进行更正,假设我们的模型现在如图 3-120 所 示。 图 3-120 检查模型实例 我们有意创建了几个错误:  表“TestTable”中不存在列,并且与其它任何表都没有关系  表“学生”没有主键  表“班级”中的字段“班级名称”没有定义数据类型  表“课本”外键引用“国家”,但表中没有列定义为外键与该引用对应 对模型进行检查,Result List 的结果如图 3-121 所示。 批注 [e18]: 原为“请参考附录”,因 附录取消,所以`修改。 作者:姜江 error 291 图 3-121 检查结果列表 下面我们开始对该模型的错误和警告进行分析: 错误 1:提示“Existence of column”对象是表“TestTable”,双击该行(或者在右键菜单 中选择 Correct,如果该错误可以自动纠正,则也可以选择 Automatic Correction),弹出表 “TestTable”的属性窗口,我们在这里可以添加一个名为 testTableID 的列,并定义为主键,字 段类型为 int。 错误 2:同样提示“Existence of column”,但对象是表“key‘key_1’”, Model 为模型中的 表“学生”,双击该行,弹出表“学生”的属性窗口,将列“学号”定义为主键,字段类型为 int。 错误 3:提示“Incomplete join”,对象为“课本”与“国家”之间的引用,双击该行,弹 出引用的属性窗口,进入 Joins 属性页中,选择子表发现列“出版国家”已经不存在,点击上方 工具栏【Migrate Columns】父表的主键。 ====================================================================== 警告 1:提示“Undefined data type”,对象为班级表中的“班级名称”,双击改行,进入表 “班级”的属性窗口,为“班级名称”定义数据类型为“varchar(20)” 警告 2:提示“Existence of reference”,对象为表“TestTable”,表明该表与其他表之间 没有引用关系,我们可以不修改。 警告 3:提示“Existence of key”,对象为表“TestTable”,之所以是警告是因为,刚才时 候表中还没有列,我们刚刚已经正确定义了该表,所以,也可以忽略该警告。 警告 4:提示“Existence of index”,对象为所有的表,这表明每个表中都没有定义索引, 单这不是必须的,仅仅是警告而已,我们这里也可以忽略。或者按照以下方法解决: 1.选择【Tools】→【Rebuild Objects】→【Rebuild Indexes】,或者按快捷键【Shift+ Ctrl+I】,弹出索引重建的窗口。 2.选择 Delete and Rebuild 单选框 3.在 Selection 属性页中选择需要更新的表,这里选择全部表 4.点击【确定】按钮。 这里请参考:3.12 PDM 模型的检查(Check)部分的“Rebuilding Indexes” 修改之后,我们再次按 F4 对模型进行检查,将会发现除了警告 2 和 4 之外,其他的错误都已 作者:姜江 error 292 经排除。这里有必要向读者提醒,如果发现了不明白含义的错误,那么可以通过在该错误或者警 告上点击右键,在弹出的菜单中选择 Help,PowerDesigner 自带的帮助的可以告诉你该错误或警 告的含义,以及如何更正。 下面我们继续介绍如何利用工具栏中的工具对检查出的警告和错误进行操作。在工具栏上右 键鼠标,在弹出的菜单中选中“Check”,各工具的含义如错误!未找到引用源。所示。 表 3-72 “Check”工具栏各工具含义 工具 功能 含义描述 Manual correction 同双击错误行一样,弹出有问题对象的属性窗口 Display help 显示关于该错误或者建议的帮助信息 Check again 对指定问题重新检查,一般在更正之后执行该操作 Automatic 自动纠正特定的错误 First Error 第一个错误 Previous Error 前一个错误 Next Error 下一个错误 Last Error 最后一个错误 例如,在更正了错误 2 之后, Check again,该错误显示为如图 3-122 所示图形,表示 已经经过更正,现在是正确的: 图 3-122 错误更正后经过再次检查在结果列表中的显示 3.13 PDM 模型的转化/比较/合并 物理数据模型(PDM)可以转化为 PDM(物理数据模型)/CDM(概念数据模型)/OOM(面向对象模 型)。还可以将一个 PDM 中的包转化为其他的模型。当不同的设计人员分别负责同一个模型中的不 同包的时候,这种方法是非常有效的,它能够生成独立的模型。 通过物理数据模型生成新的模型,可以是生成到一个新建的模型中,也可以用于更新另一个 模型(默认模型),在模型对比窗口中左边为默认模型,右侧为要被转化出去的模型。 作者:姜江 error 293 3.13.1 从一个 PDM 转化为另一个 PDM A.为什么需要从一个 PDM 转化为另一个 PDM? 如果你需要创建一个模型的新的版本的时候可以从一个 PDM 生成另外一个 PDM,这种转化允 许你创建一个特定模型的拷贝,并且定义元模型和生成的模型之间对象的连接,如果原模型中的 对象发生改变,可以使用“Update Existing Model”的生成模式,直接在生成的模型中反映出来。 如果你的工作必须在多 DBMS 中开展,你可以使用 PDM 转化,从而避免从一个 CDM(概念数据 模型)生成不同的 PDM 的时候还要根据不同 DBMS 的特征定制。你可以从 CDM 生成一个 PDM,然后 根据某个 DBMS 的特征来定义该 PDM,然后就可以直接利用该 PDM 模型为不同的 DBMS 生成相应的 物理数据模型。如图 3-123 所示。 图 3-123 PDM 模型为不同 DBMS 生成 PDM 生成一个 PDM 时,可以选择生成新的 PDM 或者更新已有的 PDM。同时,还要规定一些参数 DBMS: 结果 PDM 的数据库管理系统定义;Share:结果 PDM 使用存储在 DBMS 库中的共享 DBMS 定义;Copy: 结果 PDM 使用模型中的 DBMS 定义的一个拷贝;Name:结果 PDM 的名称;Code:结果 PDM 的名称代 码;Configure Model Options:定义新 PDM 的模型选项参数。 如果选择 Update existing Physical Data Model,就要求选择目标模型,如果该模型以前 从未被用于转化其他模型,那么默认情况下选择模型的下拉框是空的。可以通过点击 ,在弹 出的窗口中选择当前 Workspace 中的模型。Preserve Modifications 表示允许在新生成的 PDM 和 当前选择的模型进行比较和合并。如果没有选中 Preserve Modifications,PowerDesigner 会自 动用新生成的模型覆盖已有的模型。如果你想选择从现有的 PDM 中添加或者删除哪些对象,就必 须选中 Preserve Modifications 对两个模型进行比较和合并。 转化为一个新模型的步骤: 1.打开我们前面创建的模型 test,选择【Tools】→【Generate Physical Data Model】, 或者按快捷键【Ctrl+Shift+C】,显示生成物理数据模型的对话框 2.选择 Generate New Physical Data Model 选框 3.在 DBMS 下拉框中选择目标 DBMS 为 Oracle 9i,输入 name 和 code 分别为 test2 作者:姜江 error 294 4.<可选>点击【Configure Model Options】按钮,对生成的 PDM 进行定义。 5.点击 DBMS Preserve Options 属性页,为目标 DBMS 定义 Preserve Options 不同 DBMS 之间支持的对象使不同的,因此,从一个 PDM 生成另一个不同 DBMS 的模型时, 可以选择某些对象继续保留或者不保留。这些对象包括:  触发器和存储过程  关于数据库/表/索引/主键和侯选键/默认选项/表空间以及存储的一些物理选 项  数据库对象:数据存储/表空间/抽象数据类型/sequence  扩展属性 如果目标 DBMS 不支持某种数据库对象,那么该对象的 preserve options 就是灰化 的,并且不能被选择,同时,和该对象相关的值也会在你改变 DBMS 的时候丢失。如果切 换 DBMS,触发器会自动重建。如图 3-124 所示。 图 3-124 定义生成 PDM 的选项 6.在 Selection 属性页中选择需要的对象(这里选取所有的表),点击【确定】按钮 更新已有模型的步骤: 1. 选择【Tools】→【Generate Physical Data Model】,或者按快捷键【Ctrl+Shift+C】,显 示生成物理数据模型的对话框 2. 选择 Update Existing Physical Data Model 选框 3. 选择我们刚刚生成的模型 test2,如果下拉框为空,点击 选择需要更新的 PDM 4. 在其他各个属性页中设定更新时的选项,点击【确定】按钮,弹出模型合并窗口,该窗口和 模型的比较窗口的含义是一样的,根据自己的需要在该窗口中选择需要做哪些更新,不需要 更新的,在两个模型不同的地方将右侧的目标模型处变为不选中。这部分请参考:3.13.4 PDM 模型的比较。 5. 点击【确定】按钮完成对目标模型的更新。 作者:姜江 error 295 3.13.2 将 PDM 转化为面向对象模型(OOM) 在这节中我们将学习如何将物理数据模型转化为面向对象的模型 OOM。 A.生成的 CDM 对象 当我们从一个物理数据模型生成面向对象模型时, PowerDesigner 能够自动将物理对象转化 为规定的对象语言中的对象,具体的转化对象之间的对应如表 3-73 所示。 表 3-73 PDM 到 OOM 各对象转化对应关系 PDM 中的对象 在面向对象模型中生成的对象 Domain Domain Table Class。类的 cardinality 是根据表的估计的记录数产 生的 Table with migrated keys from only two other tables 由两个父表生成的在两个类之间的关联类 Column Attribute Key Identifier Primary key Primary identifier 存储过程及和表相关的存储函数 如果表生成了类,那么和该表相关联的存储过程和存储 函数就被生成为该类的一个方法 Reference Association C. PDM 和 OOM 之间数据类型的转化,如表 3-74 所示。 表 3-74 PDM 到 OOM 转化数据类型对应关系 物理数据类型 PDM 中的 code 存储的数据 在 Java 中生成的类型 Char A 字符串 Char Numeric(1) BL 16 位整数 Boolean Smallint BT 256 个值 Byte Integer SI 16 位整数 Short Integer LI 32 位整数 Integer Integer I 32 位整数 Long Float F 32 位浮点型数字 Float Numeric N 特定小数位的数字 Double Long Varchar TXT 字符串 String C.从 PDM 生成面向对象模型(OOM) 可以选择对 PDM 或者 PDM 中的一个包来生成 CDM,操作步骤如下: 作者:姜江 error 296 1. 打开我们建立好的模型 test(经过和模型 student_org 合并后的模型) 2. 选择【Tools】→【Generate Object-Oriented Model】,或者按快捷键【Ctrl+Shift+O】, 显示生成 OOM 的对话窗口 3. 选择“Generate New Object-Oriented Model”单选按钮,输入 name 和 code 分别为 studentOOM 4. 在 Object Language 下拉列表中选择 Java 作为面向对象语言 5. <可选>点击“Configure Model Options”按钮,定制生成的 OOM 的属性 6. 进入 Selection 属性页选择需要生成在目标 OOM 中的对象(这里选取所有的表),点击【确定】 按钮。 执行完毕后,可以发现在 workspace 的下级目录中,增加了一个叫做 studentOOM 的面向对象 模型,这个 OOM 中同样也包含两个模型图形,如图 3-125 所示。 可见,该模型基本上采用了原 PDM 的组织形式。生成的模型如图 3-126 所示。 图 3-125 生成的 OOM 在浏览树中的结构 图 3-126 PDM 生成的 OOM 更新已有的面向对象模型操作步骤如下: 1. 选择【Tools】→【Generate Object-Oriented Model】,或者按快捷键【Ctrl+Shift+O】, 显示生成面向对象模型的对话框 2. 选择 Update Existing Physical Data Model 选框 3. 选择我们刚刚生成的模型 studentOOM,如果我们已经生成过一次 OOM,那么默认情况自动列 出生成过的那个 OOM,如果下拉框为空,点击 选择需要更新的 OOM 4. 在其他各个属性页中设定更新时的选项,点击【确定】按钮,弹出模型合并窗口,该窗口和 模型的比较窗口的含义是一样的,根据自己的需要在该窗口中选择需要做哪些更新,不需要 批注 [e19]: 此处图已修改 作者:姜江 error 297 更新的,在两个模型不同的地方将右侧的目标模型处变为不选中。这部分请参考:3.13.4 PDM 模型的比较。 5. 点击【确定】按钮完成对目标模型的更新。 3.13.3 将 PDM 转化为概念数据模型(CDM) 在这节中我们将学习如何将物理数据模型转化为概念数据模型,同样,CDM 也可以转化为 PDM, 在将 CDM 转化为 PDM 时可能会存在问题,请参考:第 7 章 高级应用&网友常见疑难解答(FAQ) 7.10 问题十_问题十。 A.生成的 CDM 对象 当我们从一个物理数据模型生成概念数据模型时, PowerDesigner 能够自动将物理对象转化 为概念对象,具体的转化对象之间的对应请参考下表: 表 3-75 PDM 到 CDM 各对象转化对应关系 PDM 中的对象 在 CDM 中生成的对象 Table(表) Entity(实体) Table column Entity attribute Primary key Primary identifier Alternate key Identifier Reference Relationship B.PDM 和 CDM 之间数据类型的转化 PowerDesigner 同时支持物理和概念数据类型。表 3-76 列出了数字数据类型之间的转化: 表 3-76 PDM 到 CDM 转化数字类型对应关系 SQL Anywhere 示例 DBMS 中 code 存储的数据 概念数据类型 integer I 32 位整数 Integer smallint SI 16 位整数 Short Integer Integer LI 32 位整数 Long Integer Smallint BT 256 个值 Byte float F 32 位浮点型数字 Float real SF 少于 32 位浮点型数字 Short Float double LF 64 位浮点型数字 Long Float numeric MN 特定小数位的数字 Money numeric NO 自动增加的数字 Serial numeric(1) BL 两个相反的值(true/false; Boolean 作者:姜江 error 298 yes/no;1/0) 下表列出了字符型数据类型之间的转化。 表 3-77 PDM 到 CDM 转化字符型数据类型转化 SQL Anywhere 示例 DBMS 中 code 存储的数据 概念数据类型 Char A 字符串 Characters Varchar VA 字符串 Variable Characters Varchar LA 字符串 Long Characters Long varchar LVA 字符串 Long Var Characters Long varchar TXT 字符串 Float Char MB 多字节字符的字符串 Short Float Varchar VMB 多字节字符的字符串 Long Float 下表列出了时间型数据类型之间的转化。 表 3-78 PDM 到 CDM 转化时间型数据类型转化 SQL Anywhere 示例 DBMS 中 code 存储的数据 概念数据类型 Date D 日,月,年 date Time T 小时,分钟,秒 time Date & Time DT 日期和时间 timestamp Timestamp TS 系统日期和时间 Timestamp 其他数据类型。 表 3-79 PDM 到 CDM 转化其他数据类型转化 SQL Anywhere 示例 DBMS 中 code 存储的数据 概念数据类型 Binary BIN 二进制字符串 Binary Long binary LBIN 二进制字符串 Long Binary Long binary PIC 图片 Image Long binary BMP BMP 格式的图片 Bitmap Long binary OLE OLE 连接 OLE Char(10) * 用户定义的数据类型 Other 数据类型没有定义 Undefined C.从物理数据模型生成概念数据模型 可以选择对 PDM 或者 PDM 中的一个包来生成 CDM,操作步骤如下: 1. 打开我们建立好的模型 test(经过和模型 student_org 合并后的模型) 作者:姜江 error 299 2. 选择【Tools】→【Generate Conceptual Data Model】,或者按快捷键【Ctrl+Shift+C】, 显示生成 CDM 的对话窗口 3. 选择“Generate New Conceptual Data Model”单选按钮,输入 name 和 code 分别为 studentCDM 4. <可选>点击【Configure Model Options】按钮,定制生成的 CDM 的属性 5. 进入 Selection 属性页选择需要生成在目标概念数据模型中的对象(这里选取所有的表),点 击【确定】按钮。 执行完毕后,可以发现在 workspace 的下级目录中,增加了一个叫做 studentCDM 的概念数据 模型,这个 CDM 中同样也包含两个模型图形,该模型基本上采用了原 PDM 的组织形式,如图 3-127 所示。 图 3-127 生成 CDM 后在浏览树中的显示 更新已有的概念数据模型操作步骤如下: 1. 选择【Tools】→【Generate Physical Data Model】,或者按快捷键【Ctrl+Shift+C】,显 示生成物理数据模型的对话框 2. 选择 Update Existing Physical Data Model 选框 3. 选择我们刚刚生成的模型 studentCDM,如果我们已经生成过一次 CDM,那么默认情况自动列 出,如果下拉框为空,点击 选择需要更新的 CDM 4. 在其他各个属性页中设定更新时的选项,点击【确定】按钮,弹出模型合并窗口,该窗口和 模型的比较窗口的含义是一样的,根据自己的需要在该窗口中选择需要做哪些更新,不需要 更新的,在两个模型不同的地方将右侧的目标模型处变为不选中。这部分请参考:3.13.4 PDM 模型的比较。 5. 点击【确定】按钮完成对目标模型的更新。如图 3-128 所示。 图 3-128 PDM 转化生成的 CDM 作者:姜江 error 300 关于 CDM 的含义以及用法,请参考:第 2 章 概念模型(CDM)。 3.13.4 PDM 模型的比较 模型之间的比较与模型和数据库之间的比较基本雷同,因此,这部分内容可参考:3.8.3 比 较、同步模型和数据库、通过模型修改数据库。 3.13.5 PDM 模型的合并 假设我们的这个系统是由几个不同的设计人员负责,另一个设计人员负责学生组织成员管理 的子系统的设计任务,模型名称为 student_org,如图 3-129 所示。 图 3-129 PDM 合并模型实例 由于我们最终要实现的系统是要将两个子系统整合起来应用的,采用一个中央数据库,因此, 就需要合并这两个模型,形成一个完整的数据库定义。 1. 打开模型 student_org 和模型 test 2. 在模型 test 中选择【Tools】→【Merge Model】或者按快捷键【Shift+F6】 3. 在弹出的窗口中选择另外一个模型 student_org 4. 可以点击该窗口中的 Options 按钮定义两个模型之间比较的数据库元素 5. 点击【确定】按钮,弹出模型比较结果窗口,如图 3-130 所示。 作者:姜江 error 301 图 3-130 合并模型窗口“Merge Models” 图中符号的含义请参考:3.8.3 比较、同步模型和数据库、通过模型修改数据库,从图形中 我们可以看出以下几点: 1. 因为 student_org 模型中的“学生表”漏掉了“已婚”这个字段,所以图形表示“学生” 表的子元素有不同之处 2. 目标模型 test 中需要增加在 student_org 中创建的三张表:“学生组织”,“学生组织成 员”,“职务” 3. 灰化表示该元素在该模型中不存在,读者如果点击某个元素,会在下半部分的属性窗口 总看到同一个元素在两个不同模型中的性质的对比 4. 如 ,该图形本身还以为要在模型中删除该元素,但是没有选定表明这个操作不 执行 读者可以对比 3.8.3 节中的表格中图形的含义来理解该图形,最后点击【确定】按钮。 如图 3-131 所示。 图 3-131 模型合并结果 作者:姜江 error 302 在 workspace 的 browser 中可以看出,test 模型中多了另外一张图 student_org,由于 两张图中包含同一个表:“学生”,我们修改任何一张图形中的“学生”的属性,在另一张图 中都会发生相应的改变。 一般的小型系统可能不需要几个设计人员分开设计,但是一旦系统变得很复杂的时候, 一个设计人员往往无法承担成百上千张表的设计和维护工作。因此,通过按照系统涉及到不 同的部门,按照不同功能模块等方式来将问题“分而治之”就成为一种有效的防范,不同设 计人员有针对性地了解需求的一部分或者一个方面,然后根据需求设计自己负责的数据模型 部分。 这种“模块分解法”一旦开始实施,如何将不同设计人员的工作成果正确的集成就变得 至关重要。同时,由于集成后的模型将成为团队人员交流的主要工具之一,因此,模型之间 的比较和分析也就同样非常重要。就好比不同程序模块之间需要定义良好的接口一样,各个 不同的模型最后要能够较好的集成也就需要设计人员有着“定义良好的设计思路”,相似的设 计风格。这样才能保证团队尽量少走弯路,当然这可能要求项目经理能够建立有效的沟通环 境和特定的设计标准,从而确保模型的创建工作能够顺利进行。 笔者曾经管理过的一个项目涉及到的数据表大概有 300 张左右,由于各个部门之间的数 据表的关系不是很复杂,就采用了不同人员负责不同部门数据表的设计的方法,这样既使得 数据库设计工作进度的加快,又确保每个人有针对性的了解特定的需求。在分工之前,将可 能涉及到的共同的表建立,也就是尽可能保证系统概念一致性,建立相关的 Glossary 等。在 各自负责模型的建立过程中保持及时有效地的沟通,及时更新 system Glossary,避免在后 期出现较大分歧,再加上 PowerDesigner 提供的强大的工具支持,因此,最后的数据库模型 集成工作进展的非常顺利。 目标模型参数: 我们前面从 PDM 生成各种模型的时候,在生成模型的对话框中有一个属性页为 Target Models,我们一直没有使用过,这一部分主要讲述该属性页的含义和应用。 外部的快捷方式(External shortcut)依赖另外一个模型中的目标对象。外部快捷方式允许 你在不同模型之间共享对象。你可以 Target Models 属性页中选择生成的模型,并且取出外部快 捷方式像对应的目标对象。这样外部快捷方式才能够被正确的连接到正确的目标模型中。 在 Target Models 属性页中,Target Models 指的是原始的快捷方式的模型(不可编辑); Generated Models 允许你选择生成的快捷方式的目标模型。这个模型生成过程允许你在生成的模 型中定义快捷方式的目标对象。如图 3-132 所示。 正确的快捷方式生成的顺序为:  模型 1 是模型 2 快捷方式的目标模型  模型 1 生成了模型 1.1  模型 2 准备通过在 Target Model 属性页中关联恰当的参数,生成模型 2.2, 作者:姜江 error 303 图 3-132 快捷方式的生成方式 如果模型 1 在 workspace 中仍然处于打开状态 目标模型显示原始模型 Model1 以及它的路径。在你第一次用 Model1 生成模型时,Generated Models 列显示最后生成的模型,下此用 Model1 生成模型时,Generated Models 列显示最后选择 的那个模型。你可以修改 Generated Models,从而确保快捷方式的正确连接。 如果模型 1 在 workspace 中处于关闭状态 目标模型显示原始模型 Model1 以及它的路径。而 Generated Models 处显示为。当你 点击 Generated Models 列时,原始的目标模型 Model1 自动在 workspace 中打开,以确保能够查 找到从 Model1 生成的模型,可以使用下拉箭头选择模型 Model1.1,新的目标允许在 Model2.2 中 正确的创建快捷方式的连接。 最后,模型 2.2 中的外部快捷方式就通过连接到模型 1.1 而正确的生成。 3.13.6 将 PDM 模型转化为 XML 模型(XSM) 在这节中我们将学习如何将物理数据模型转化为 XML 模型 XSM。之所以将这部分内容放在本 节的最后面,是因为本书最初是按照 PowerDesigner 9.5 写的,但是 PowerDesigner 10 推出之后, 又增加了对 XML 模型的支持,所以就在本节末尾讲解如何将 PDM 转化为 XSM。 由物理数据模型 PDM 转化为 XML 模型的时候,PowerDesigner 会自动将物理模型中的对象转 化为 XML 模型中的对象,具体的对象之间的转化对应关系如表 3-80 所示。 表 3-80 PDM 到 XML 各对象转化对应关系 PDM 中的对象 在 XML 模型中生成的对象 Domain 简单类型(Simple Type) Table 元素(Element ) Column 属性(Attribute)或者元素(Element),根据转化时的选项而定 View 元素(Element) View 的列 属性(Attribute) Key Key Index Unique 作者:姜江 error 304 Abstract Data Type 复杂类型(Complex) XML 模型的命名规范:如果生成的 XML 模型对象的 code 和目标语言的命名规范不符合,可以 通过命名转化脚本将对象的 Name 转化为 Code。 从 PDM 生成 XML 模型 从 PDM 可以生成 XML 模型,如果已经用 PDM 生成过 XML 模型,还可以更新 XML 模型,操作步 骤如下: 1. 打开我们建立好的模型,如图 3-133 所示。 图 3-133 转化模型实例 2. 选择【Tools】→【Generate XML Model】,或者按快捷键【Ctrl+Shift+M】,显示生成 XML 的对话窗口,如图 3-134 所示。 图 3-134 PDM 转化为 XML 模型窗口 3. 选择“Generate New XML Model”单选框,输入 name 和 code 分别为 ExampleXML 批注 [e20]: 此图已修改 作者:姜江 error 305 4. <可选>点击【Configure Model Options】按钮,定制生成的 XSM 的属性 5. 在 XML language 下拉列表中选择生成 XML 的语言类型,可以是 DTD(Document Type Definition 1.0)或者是 XSD(XML Schema Definition 1.0) 6. 在 Detail 属性页中详细定义模型转化的其他选项,如图 3-135 所示。 图 3-135 定义生成 XML 模型的详细选项 各选项的含义如下:  Check model:生成 XML 模型之前检查 PDM 模型,发现错误时停止生成 XML  Save generation dependencies:PowerDesigner 记录每个生成对象的唯一标识,如果从同 一个 PDM 生成 XML 这个选项就非常有用,它有利于识别对象并且进行比较,即使生成 的 XML 被修改也不受影响  Covert names into codes:如果选中则表示使用响应的转化脚本将 name 转化为 code。如 果要使用不同的命名规范生成模型,这个功能就十分有用,如果不选则该选项,则 code 直接从原始对象中拷贝过来  Generate mapping:生成映射,如果选中该选项,则允许在生成的 XML 模型中定义当 前 PDM 为数据源(Data Source),并且可以在 PDM 和 XML 之间创建对象的对应关系  Generate columns as elements:选中后,PDM 中表的列将在 XML 生成为子元素,而不 是属性  Enable transformations:按下该按钮用于在生成模型过程中激活 Transformation。如果当 前模型中包含 Transformation,则该窗口会增加一个 Pre-generation 属性页,可以选择 Transformation。选择该按钮后该窗口会自动增加一个 Extended Model Definitions 属性页, 如果扩展模型定义中包含 Post-generation Transformations,则出现 Post-generation 页面允 许用户进行选择。 7. 进入 Selection 属性页选择需要生成在目标 XML 模型中的对象(这里选取所有的表),点击【确 作者:姜江 error 306 定】按钮。 执行完毕后,可以发现在 workspace 的下级目录中,增加了一个叫做 ExampleXML 的 XML 模型, 如图 3-136 所示。 图 3-136 生成 XML 模型在浏览树中的显示 可以发现,该模型中包含两张图形,一张是 ExamplePDM(PDM 转化过来的图形),还有一 张 Global Diagram。注意在 XML Model Generation Options 窗口中,选择 DTD 或者 XSD 将直接影 响到生成 XML 模型的类型和结果。图 3-137 为选择 XSD 转化后的模型(图 Example PDM), 图 3-138 为选择 DTD 之后转化出的模型(图 Example PDM),熟悉 XML 的读者可以很容易看出二者 之间的区别。 图 3-137 生成的 XML 模型(XSD) 作者:姜江 error 307 图 3-138 生成的 XML 模型(DTD) 选择 DTD 或者 XSD(XML 类型本身也是用 XML 语言定义)自然会直接影响到 XML 对象 的生成代码,我们可以通过“课程”这个对象进行观察,分别在选择 DTD 和 XSD 转化生成的两 个模型中,打开“课程”的属性窗口,进入 Preview 属性页。如图 3-139 所示,为 DTD 的生成代 码,如图 3-140 所示,为 XSD 的生成代码,读者可以清楚的看到,XSD 的定义也符合 XML 的规 范。 图 3-139 生成 XML 模型的 DTD 代码预览 作者:姜江 error 308 图 3-140 生成 XML 模型的 XSD 代码预览 图 3-141 为选择 XSD 时候 Global Diagram 显示的图形,关于 XML 的具体含义不是本书的重 点,读者可以根据需要自己进一步学习。 更新已有的 XML 模型 前面提到过,PowerDesigner 中的 PDM 模型如果已经转化过 XML 模型,那么再次生成 XML 模 型时,可以选择更新已有的 XML 模型,当然也可以选择再次生成新的 XML 模型。 操作方法如下: 作者:姜江 error 309 图 3-141 生成 XML 模型的 Global Diagram 图形 1. 打开我们建立好的 PDM 模型,选择【Tools】→【Generate XML Model】,或者按快捷键【Ctrl +Shift+M】,显示生成 XML 的对话窗口 2. 选择 Update existing XML Model 单选框。 3. 在 Select Model 下拉列表中选择通过此 PDM 模型生成的 XML 模型(需要更新的模型) 4. 根据需要选择是否选中 Preserve modification 选框。如果选中,则表示允许生成的模型和 以前的 XML 进行比较,并且弹出模型合并窗口。未选中则表示直接根据当前 PDM 生成的 XML 模型覆盖以前的 XML 模型,而不出现任何提示,一般情况建议选择该选项。如图 3-142 所示。 5. 弹出模型合并窗口,左边为根据 PDM 生成的 XML 模型,右侧为已有的 XML 模型。如图 3-143 所示。 由于我们前面生成的 XML 经过了简单的位置移动,PowerDesigner 已经判断出了两个模型之间 的不同,关于 Merge Models 窗口(模型合并窗口)的中模型比较表示方法的具体含义,请参考:: 3.8.3 比较、同步模型和数据库、通过模型修改数据库,点击某个具体的对象,在该窗口下会显 示该对象的详细信息,如果模型之间对象被修改或者删除等,这里也会有相应的信息。 作者:姜江 error 310 图 3-142 PDM 更新已有的模型 选择好需要模型中需要更新的部分(如果需要修改,则选中对象前面的复选框),点击【OK】 确定,PowerDesigner 会根据 Merge Models 窗口中的选择对目标模型进行更新,完成后自动跳转 到目标模型中。 图 3-143 更新 XML 模型时的模型合并窗口 作者:姜江 error 311 3.14 对数据库规模的估计(EstimateDatabaseSize) 有时候,我们希望知道我们建立的数据库到底有多大的规模,我们也许仅仅可以估计每张表 大概有多少条记录,但是面对很多张表的时候,用手动的方法估算数据库的规模就显得不够划算, 在本节中我们将学会如何使用 PowerDesigner 估计数据库的规模 计算的依据主要包括:  对表中行数目的估计,包括两个部分:  固定长度的数据类型的占用空间大小  变长数据类型的平均占用空间大小  模型中的索引(因为索引也要占数据库的空间)  包括所有的索引(主键索引,外键索引,备用键(Alternate key)索引,某些特定 数据库的索引,例如 IQ join 索引)。  自动索引约束:有些 DBMS 中会对键自动索引,如果目标数据库也包括对键的自动索 引,那么数据库大小估计时也会将其计算在内。  模型中的表空间(Table Space) 和表相关的表空间默认情况下在估算的范围内,并 且被显示为以下两个部分:  表空间中所有的表  表空间中所有的索引  数据库存储的选项(Database storage options) 数据存储选项和特定的 DBMS 相关,用户可以根据目标数据库支持的数据存储选相进行定 义,最终会反映在对数据库规模的估计当中。 1. 指定表的记录数目 选择【Model】→【Tables】,打开表的列表的窗口【Customize Columns and Filter】 ,使得“number”显示出来,在“学生”“班级”“教师”三个表中分别输入 10000 /500/1000。注:也可以直接双击表,打开表的属性窗口,在 General 属性页中下方 的 Number 输入框中输入表的估计行数。 2. 指定数据类型的平均长度 在估计数据长度大小的时候,这些 variable length data types(变长数据类型) 的数据的大小的估计是根据平均长度,而不是最大长度。 选择【Model】→【Columns】,打开所有列的列表的窗口【Customize Columns and Filter】,使得列“Average Length”显示出来,根据自己的需要输入特定的值, 如图 3-144 所示。 批注 [e21]: 此处原为“如果目标数据 库......选项” 作者:姜江 error 312 图 3-144 在列的列表窗口中指定列的平均长度 估计数据库规模大小选择【Database】→【Estimate database size】,弹出窗口,如图 3-145 所示。 图 3-145 “Database Size Estimation”窗口 3. 点击上图手状图标所指的【Include Sub-packages】工具,目的在于包括模型中的子包 中的元素 4. 在窗口的下放选择本次估计要包括进入的那些表。 注:可以在 Selection 下面的下列框中选择要估计的模型,如果模型中包含“子包”,也 可以选择单独对某个包中的表进行估计 5. 点击【确定】按钮,可以在 Output 窗口中看到以下文本结果: =========================================================================== Estimate of the size of the Database "test"... Number Estimated size Object 500 31 KB Table "班级" 8 KB Primary key index "Key_1" 1,000 162 KB Table "教师" 14 KB Primary key index "Key_1" 100,000 14,494 KB Table "学生" 1,106 KB Primary key index "Key_1" 作者:姜江 error 313 --------------------------------------------------------------------------- 15,815 KB Total estimated space Database size estimation successful. =========================================================================== 同时,也可以通过 Result List 窗口以图形的方式查看估计结果,如图 3-146 所示。 图 3-146 估计数据库规模的结果列表 3.15 对 DBMS 进行定制 进入 E:\Program Files\Sybase\PowerDesigner 9\Resource Files\DBMS(读者的安装目录可 能不同),发现该目录下有 43 个后缀名为“xdb”的文件,我们用任何一个文本编辑器打开其中的 一个,即可发现,这些实际上都是 xml 格式的文件,如图 3-147 所示。 图 3-147 用文本查件查看 xdb 文件 PowerDesigner 之所以如此强大,能够根据我们定义的模型生成各种代码,靠的就是这些 xml 的文件,因为 PowerDesigner 支持大多数的 DBMS,而 DBMS 各自之间又不尽相同,所以每一个 PowerDesigner 支持的 DBMS 就有一个相应的 xdb 文件。 我们用文本编辑器打开 sqlsrv2k.xdb,这个文件是 SQL Server 2000 的 DBMS 定义文件,通 过查找,我们发现以下代码: ========================================== EXEC sp_addlogin '%USER%', '%USER%', '%DATABASE%' go 作者:姜江 error 314 sp_grantdbaccess %USER% ========================================== 细心的读者会记得,这段代码我们在 2.9.5 生成权限控制脚本中曾经在 SQL Server 2000 的 DBMS 定义中修改了对 User 的创建脚本的模板,添加了行代码, ========================================== EXEC sp_addlogin '%USER%', '%USER%', '%DATABASE%' Go ========================================== 而最终生成的权限控制的脚本中也反映出了这段脚本的作用,因此,我们可以确认, PowerDesigner 正是通过这些 xml 的文件,才能够生成各种脚本,实现其强大的功能。不过,我 们希望读者不要直接修改该 xml 文件,以免出错,最好通过 PowerDesigner 提供的 GUI 工具进行 定制,在修改之前,最好能够将这些文件备份,以免出现意外情况无法恢复。 这些文件在 PowerDesigner 中被成为“Resource files”,在 PowerDesigner 中可以通过 Resource Editor 对 DBMS 进行定制和修改,它提供了查看和定制 resource 文件的接口,包含一 系列代表不同源文件的值和设置。可以通过选择【Tools】→【Resources】→【DBMS】,在弹出的 窗口中选择需要查看或者修改的 DBMS 定义文件,可以打开如图 3-148 所示窗口: 图 3-148 DBMS 属性窗口 如图所示,左侧为 DBMS 中的不同的数据库元素,可以进行适当的选择,右面部分随时根据选 择对象显示相应属性,如 name、code 以及 value 和 comment 等属性。 3.15.1 对 DBMS 源文件进行管理 可以通过使用源文件列表窗口打开 resource editor。选择【Tools】→【Resources】→【DBMS】, 弹出窗口,如图 3-149 所示。 作者:姜江 error 315 图 3-149 DBMS 源文件列表窗口 该窗口中上访的工具条的各工具含义如表 3-81 所示。 表 3-81 “List of DBMS”窗口各工具含义 工具 含义 描述 属性 打开 DBMS 定义源文件属性窗口,即 Resource Editor 新建 使用现有定义文件作为模板创建一个新的 DBMS 定义文件 保存 保存在列表中选择的定义源文件 保存所有 保存在列表中所有的定义源文件 路径 浏览包含定义源文件的目录 导入 将定义源文件导入到源文件库中。可以导入 PowerDesigner 6 使用的 DEF 格式的文件,PowerDesigner 9.5 会自动转化为 XDB 格式的 xml 文 件 比较 选择两个需要比较的定义源文件 合并 选择两个需要合并的定义源文件 A.创建一个定义源文件 在 PowerDesigner 9.5 中,可以使用现有的定义源文件的结构和内容来创建一个新的定义源 文件,也就是拷贝后作修改。如果你想修改一个 DBMS 的定义文件,最好通过拷贝来创建一个新的 DBMS 定义文件,这样可以保证 PowerDesigner 自带的文件完好无损。具体的操作方法如下: 1. 选择【Tools】→【Resources】→【DBMS】,弹出 DBMS 列表窗口 2. 点击【New】工具 ,弹出如图 3-150 所示窗口,在 name 输入框中输入新文件的名称,在 Copy from 下拉框中选择新文件的模板文件,点击【确定】按钮: 作者:姜江 error 316 图 3-150 新建 DBMS 定义文件 3. 点击【OK】,在弹出的“另存为”窗口中输入需要保存的文件名称,点击【保存】按钮 4. 弹出 DBMS 属性窗口,在这里可以对 DBMS 定义文件修改和定制 5. 点击【确定】按钮,发现新创建的 DBMS 定义文件已经加入到 DBMS 列表中,点击【Close】。 B.导入一个定义源文件 可以将 PowerDesigner 6 中的 DEF 文件导入到 PowerDesigner 9.5 中,自动转化为 XDB 格式 的 xml 文件,操作步骤如下: 1. 选择【Tools】→【Resources】→【DBMS】,弹出 DBMS 列表窗口 2. 点击【Import】工具 ,弹出文件打开窗口 3. 选择需要导入的 DEF 文件 4. 点击【确定】按钮,DBMS 列表中会出现导入文件的名称 C.比较合并 DBMS 定义源文件 可以在两个 DBMS 之间进行比较,进一步还可以合并 DBMS 定义源文件,在比较的过程中 PowerDesigner 会自动突出显示出 DBMS 定义源文件中不同的地方。合并则允许把同一个团队内的 不同成员定义的 DBMS 源文件合并在一起,则是从左到右进行的,最终将合并到窗口右边的模型中。 比较模型的具体的操作步骤如下: 1. 选择【Tools】→【Resources】→【DBMS】,弹出 DBMS 列表窗口 2. 在列表中选择一个 DBMS 定义源文件 Microsoft SQL Server 2000 3. 点击【Compare】工具 ,弹出 Select DBMS to Compare 窗口,如图 3-151 所示。 图 3-151 选择要比较的 DBMS 定义源文件 4. 选择我们刚刚创建的 DBMS 文件 MyTestDBMS,点击【OK】 5. 弹出 DBMS 定义源文件比较窗口 合并模型的具体的操作步骤如下: 合并模型的具体的操作步骤如下: 作者:姜江 error 317 1. 选择【Tools】→【Resources】→【DBMS】,弹出 DBMS 列表窗口 2. 在列表中选择一个 DBMS 定义源文件 Microsoft SQL Server 2000 3. 点击【Merge】工具 ,弹出 Select DBMS to Merge 窗口 4. 选择我们刚刚创建的 DBMS 文件 MyTestDBMS,点击【OK】 5. 弹出 DBMS 定义源文件合并窗口,基本和比较窗口类似,可以合并两个 DBMS 定义源文件 3.15.2 使用 Resource editor 在 Resource editor 中可以通过 categories(种类)和 entries(条目)在 DBMS 定义源文件 中导航。Category 是一系列条目的集合,它对应于 DBMS 定义文件中的一个逻辑组,例如:Script 种类收集所有和数据库生成以及反向工程相关的条目。每个 category 包含一个或者多个 entries。 Entry 是 DBMS 定义文件中的一条信息,例如:你可以为一条数据库命令和一个报告文档项定义一 个可 entry。如图 3-152 所示。 图 3-152 使用 Resource Editor 该窗口上方的工具的含义如错误!未找到引用源。所示。 表 3-82 “Resource Editor”窗口部分工具栏含义 工具 功能 描述 快捷键 Back 返回前面访问的条目或种类,点选向下箭头,可 以直接选择回到以前访问的某个条目或种类 ALT+LEFT Forth 返回后面访问的条目或种类,点选向下箭头,可 以直接选择跳至后面访问的某个条目或种类 ALT+RIGHT 作者:姜江 error 318 Save/Save As 保存当前 DBMS 定义文件,点选向下箭头,可以选 择另存为一个新的文件 CTRL+SHIFT+S Find in Items 查询文本、命令、模板、自定义约束以及标准生 成的文件条目 CTRL+SHIFT+F Replace In Items 查询并替换文本、命令、模板、自定义约束以及 标准生成的文件条目 CTRL+SHIFT+H 错误!未找到引用源。为 Resource Editor 中不同的 item 的类型的图符及其含义。 表 3-83 “Resource Editor”窗口不同 Item 含义 符号 条目名称 描述 Char 单个字符 String 一行文本 Boolean 布尔值 Numeric 数字 Text 长文本 Map 一系列值 List 下拉列表中可选的值 Command 生成的命令 Task 生成之后可以执行的命令的列表 Option 生成选项(boolean、list、string type) Template 普通文本,其中夹杂着包含模型信息的变量,允许定制生成 Extended attribute type 用户定义的数据类型和经过核定的扩展属性的一系列值 Extend attribute 对 metaclass 定义的补充,也可以控制生成 Generated file 包含生成文件的类型 Custom check 定制化检查的定义 作者:姜江 error 319 Criterion 选择的 metaclass 的标准条件的定义 Stereotype 某个实例的子分类 Custom symbol 对象符号的定制 3.15.3 理解 Resource 文件的 SQL 语法 要学会如何定义和修改 DBMS 的 Resource,就必须先熟悉 Resource 文件的 SQL 语法,以及 各个部分定义的含义,才能知道 PowerDesigner 是如何利用 DBMS 的 Resource 文件来完成如此强 大的功能,才能有效地运用它们解决实际问题。参考:第 7 章 高级应用&网友常见疑难解答 (FAQ)。 PowerDesigner 通过使用在 DBMS 的 Resource 定义文件中定义的语法来完成脚本生成,或者 反向工程数据库的任务。这些语法用于在常见或者修改 PowerDesigner 对象的过程中使用合适的 变量完成任务。PowerDesigner 在生成脚本或者 ODBC 是同样使用这些语法 用户可以在为特定的 DBMS 在 SQL 语句中包含特殊的变量。PowerDesigner 中的变量是用百 分号(%)括起来的。 生成数据库生成时,PowerDesigner 按照特定的顺序执行从 DBMS 的 Resource 文件中读取出 来的 SQL 命令,与此同时,Resource 文件中所有的变量都会被从模型中取出的实例的值代替。这 有些类似于参数的附值。 反向过程时,如果 DBMS 的 Resource 文件中定义的语法和实际的 DBMS 的 SQL 向匹配, PowerDesigner 就会以特定的顺序从 DBMS 中取出和变量对应的值,将它们以对象属性的方式保 存在模型中。 保留关键字 通常情况下,如果列或者域的数据类型被认为可能时字符串类型或者时间类型时, PowerDesigner 会自动加上引号(单引号和双引号随着 DBMS 的不同而不同)。但是以下情况不会 为生成的脚本加上引号:  如果定义的数据类型没有被 PowerDesigner 识别为字符串类型  如果值被发音字符包围(一些西班牙语字符上有发音字符,如:lã, pão.,表示鼻音)  如果值是 DBMS 中定义的保留字(如 Table)  如果值已经被引号包围 对保留字修改的应用请参考:第 7 章 高级应用&网友常见疑难解答(FAQ)7.7 问题七。 可选的关键字和变量 在 PowerDesigner 中,DBMS 的 Resource 文件中可以使用方括号“[ ]”:  在 SQL 语句的语法中用于包括可选的关键字和变量,使用的方式为:[%--%]  用于验证变量的值,然后根据验证的结果插入或者重新使用一个值,使用的方式为[% 批注 [e22]: 去除“额”字 批注 [e23]: 原为“发引” 作者:姜江 error 320 --%?is true:is false]  测试变量的内容,使用的方式为[%--%=--?if true:if false] 具体的应用参考表 3-84。 表 3-84 变量使用方法 变量 生成数据库时 反向工程时 [%--%] 如果变量定义则生成变量的值,如果变 量为空或者值为NO 或者FALSE则生成 时被忽略 如果语法检查器检测到和该变量所 匹配的 SQL 命令则给该变量赋值, 如果变量为空或者值为 NO 或者 FALSE 则被忽略 [%--%?: Is true : Is false](条件值) 如果变量的值为 true,则生成 is true 的 值,否则生成 Is false 的值,Is true 和 Is false 都可以是变量或者某个具体的值, 这种用法有点类似于 C 语言中的: int i=(白骨精= ='妖精')?1:0 如果语法检查器检测到变量的值为 True,则在反向工程时使用 Is true 代表的变量或者值,否则,使用 Is false代表的变量或者值完成反向工 程 [%--%=--?:Is true : Is false] 如果变量等译某个常量值,则生成 Is true 的值,否则使用 Is false 的值 如果语法检查器检查到 Is true 则该 常量值被加到变量中,如果检测到 Is false,则不添加 下面通过一些具体的实例来进一步了解这些语法的应用:  [%--%] 例:[%OPTIONS%] 如果%OPTIONS%的值不是FALSE,则生成该变量,该变量将被%OPTIONS%的值取代 (在对象的属性窗口中的Options属性页中规定的对象的物理属性选项) 例:[default %DEFAULT%] 反向工程时,如果发现default 10这样的文本,那么将给变量%DEFAULT%附值为10,但 这种说明不是强制性的,即使没有这样的说明文本,SQL命令也会被反向工程到模型中,可 以用“可有可无”来理解它的作。在脚本生成时,[default %DEFAULT%]又会被default 10所 取代。  [%--%?: Is true : Is false] 可以为可选关键字或者变量使用条件值。可选关键字或变量的包含在方括号中,两个条 件使用冒号隔开。 例:[%MAND%?Is true:Is false] 在生成数据库的过程中,如果检测到%MAND%的值为True,则使用Is true代表的变量或 者值,否则,使用Is false代表的变量或者  [%--%=--?: Is true : Is false] 可以使用关键字测试变量的值 作者:姜江 error 321 例:[%DELCONST%=RESTRICT?:[on delete %DELCONST%]] 使用关键字 在方括号之间的关键字一定会被生成,但是无论该关键字是否在SQL语句中出现,对该SQL 语句进行反向工程都会继续进行,因为在SQL语法中这些关键字是不是必须的,例如,创建一个 视图的SQL语句的语法包括:create [or replace] view %VIEW% %SQL% 对脚本进行反向工程时,无论是只包含create或者仅包含create or replace,该语句都会被反向 工程到模型中,因为这些关键字是可选的。 此外,在Resource文件的语法中还大量使用了对变量及文本的格式化,请参考3.16.2 PowerDesigner中对变量格式化,关于PowerDesigner中各种变量,请参考3.16.1 PowerDesigner变量 列表。关于Script\DataType部分,请参考:第7章 高级应用&网友常见疑难解答(FAQ)7.10 问 题十。 3.15.4 修改 Resource 文件 Resource 文件既可以在不同模型之间共享(share),也可以拷贝到某个模型中使用。如果你 在不同模型之间共享一个 Resource 文件,那么在任何一个模型中修改 DBMS 的 Resource 文件都会 在其他模型中有相应的改变,但如果是创建了一个 Resource 文件的拷贝则不会影响到其它模型。 新建两个 PDM,都采用 Microsoft SQL Server 2000 作为 DBMS,其中,一个模型选择“Share: Use the shared DBMS definition”,另存为 PDM1,另一个模型选择“Copy:Create a copy of the DBMS definition in model”,另存为 PDM2,可以不在这两个模型中建立任何图形和对象,然后 关闭这两个模型。进入存放这两个模型的目录,可以发现,PDM1 大概不到 22k,而 PDM2 却有 127k 左右, 进入 DBMS Resource 文 件 存 放 的 目 录 E:\Program Files\Sybase\PowerDesigner 9\Resource Files\DBMS\可以得知 Microsoft SQL Server 2000 的 Resource 文件 sqlsrv2k.xdb 大约有 107k,可以发现:使用“copy”的模型的大小基本=Resource 文件的大小+使用 share 的模型文件。如图 3-153 所示,在创建模型的时候可以选择 share 或者 copy: 图 3-153 新建模型是选择共享或拷贝 DBMS 定义文件 修改 Resource 文件的方法: 作者:姜江 error 322 1. 选择【Tools】→【Resources】→【DBMS】,弹出 DBMS 列表窗口 2. 在列表中选择一个 DBMS 定义源文件(Resource 文件)Microsoft SQL Server 2000,双击或者 点击【Properties】工具 3. 在弹出的窗口中,扩展左边树状视图中的节点,选择 category 和 entry,而这些 category 和 entry 的 name,comment 以及 value 都会在树状视图右边显示出来,在这里修改 4. 点击【确定】按钮,回到 DBMS 列表窗口,点击【Close】关闭该窗口 5. 弹出确认对话框,询问是否要保存对 Resource 文件的修改,如果要保存点击【Yes】确认 此外,还可以在该窗口中右键根节点或者 category ,在弹出的菜单中选择 new category, 也可以在右键根节点或者 category ,在弹出的菜单中选择新建某个 item。 关于修改 Resource 文件,对 DBMS 进行定制解决实际问题的应用,请参考:第 7 章 高级应用 &网友常见疑难解答(FAQ)。 3.15.5 使用扩展属性 扩展模型定义(Extended Model Definitions)提供了定制 PowerDesigner 参数和生成的途径。 在 PDM 中,我们可以在 DBMS 的 Resource 文件或者扩展模型定义(Extended Model Definitions) 中定制 PDM 的扩展属性(Extended Attributes),可以根据自己的需要定义扩展属性类型(Extended Attribute Types)和扩展属性(Extended Attributes),然后便可以将这些扩展属性作为变量在生成数据 库脚本时像 PowerDesigner 自带的变量一样使用,从而达到扩展 PowerDesigner 元模型(metamodel) 以及进一步完善模型对象定义的目的。 A.通过修改 DBMS 的 Resource 文件来创建扩展属性 可以创建: 1. 不同模型之间共享的、和 DBMS 的 Resource 文件相关的扩展属性 2. 某个特定模型使用的特定的扩展属性 创建共享的扩展属性定义的步骤如下: 1. 选择【Database】→【Edit Current DBMS】,弹出 DBMS 属性窗口,即 Resource Editor 2. 如图 3-154 所示,要创建扩展属性和扩展属性类型都必须在 Profile 的种类下面创建,而 Shared 表示各种模型对象之间共享,在 Shared 下面包含一个子类型“Extended Attribute Types”这里 存储 WithOptionList 这样的扩展属性类型,读者可以在右边的编辑窗口中查看扩展属性类型的 定义 作者:姜江 error 323 图 3-154 在 Profile 结点下创建扩展属性类型 3. 右键 Shared 种类,在弹出的菜单中可以选择新建 Extended Attribute Types,点击新创建的扩展 属性类型,或者在 Extended Attribute Types 种类上点击右键,在弹出的菜单中选择 new,都可 以创建新的扩展属性类型。 在窗口右侧中可以对 name 和 comment 进行定义,同时还可在如下的编辑框中定义扩展属 性类型的值的列表,如图 3-155 所示。 图 3-155 编辑扩展属性值的列表 其中,工具栏中各个工具的含义分别为:插入一个值、增加一个值、删除一个值、编辑 值、将某个值设为默认值、向上移动、向下移动。 4. 鼠标右键 Profile,在弹出的菜单中选择 Add Metaclasses,表示增加新的元类,如图 3-156 所 示。 图 3-156 “Metaclass Selection”窗口 弹出的窗口中列出了可以定义扩展属性的模型对象,选择需要创建扩展属性的 Metaclasses, 点击【OK】,SQL Server 2000 默认情况下已经添加了 Table 和 View 两个对象,同时 View 已经定 义好一个扩展属性 WithOption。 作者:姜江 error 324 5. 在刚刚添加的 Metaclasses 上点击鼠标右键,在弹出的菜单上选择【New】→【Extended Attributes】,此时 PowerDesigner 会自动在改 Metaclasses 下面创建一个 category:Extended Attributes,同时创建一个扩展属性,命名为:Attribute_n,其中 n 为创建扩展属性的次序,在 窗口右边的各编辑框中分别输入扩展属性的 name 和 comment,选择数据类型,并且设置默认 值,某些数据类型也可以点击右边的 工具设置默认值,如图 3-157 所示。 图 3-157 为数据项设置默认值 6. 点击【确定】按钮,在弹出的确认窗口中点击【是(Y)】,确认保存这次修改。 为某个特定的模型创建扩展属性的步骤如下: 为模型创建扩展属性,首先要创建扩展模型定义(Extended Model Definitions),然后才可以在 扩展模型定义中创建扩展属性。具体操作步骤如下: 1. 选择【Model】→【Extended Model Definitions】,弹出当前模型中包含的扩展属性的列表 2. 点击空白行或者点击添加工具 ,可以新创建一个扩展模型定义,输入 name 和 code,点击 【Apply】按钮应用 3. 双击该行或者选择该行点击属性工具 ,弹出扩展模型定义的属性窗口 4. 以下的创建步骤同创建共享的扩展属性的方法相同 B.使用扩展属性 扩展属性往往被用于 PDM 进行数据库脚本生成,每个扩展属性都可以作为一个变量,但必 须加上“% %”扩起来,同时,这些扩展属性和变量名一样,都是大小写敏感的。 例如:Oracle version 9I 的 Resource 文件自带了扩展属性,其中,Table 自带一个扩展属性为 ExtTableType,选择【Script】→【Objects】→【Table】→【Create】,右端显示的时创建表的脚本 模板,可以看到该脚本模板使用了扩展属性 ExtTableType,使用的方式为%ExtTableType%,将该 扩展属性作为一个变量使用,如图 3-158 所示。 作者:姜江 error 325 图 3-158 将扩展属性作为变量使用 C.创建和使用扩展模型定义 在各个不同模型之间创建可以共享的扩展模型定义(Extended Model Definitions)的方法如下: 1. 选择【Tools】→【Resources】→【 Extended Model Definitions】→【Physical Data Models】, 弹出 PDM 的扩展模型定义的列表 2. 这里可以双击扩展模型定义,对扩展模型定义进行修改,点击【New】工具 ,弹出新建扩 展模型定义的对话框,可以输入 name,选择新建的模板,如果是 PDM,默认情况下 PowerDesigner 自带 PowerBuilder 的扩展属性定义文件,可供选择。如图 3-159 所示。 图 3-159 新建扩展模型定义窗口 3. 点击【确定】按钮,弹出保存文件对话框,可以发现扩展模型定义的后缀名为“XEM” 4. 输入文件名,选择存放路径后弹出扩展模型定义的属性窗口,可以在这里定义扩展属性 5. 点击【Close】关闭 6. 这时,刚才创建的扩展模型定义(Extended Model Definitions)就会出现在扩展模型定义的列 表对话框中 7. 点击【Close】关闭 选择扩展模型定义 扩展模型定义(.XEM 文件)提供了一种定制和扩展 PowerDesigner 的 Metaclasses、参数和生 成脚本的方式。可以为某个特定的模型创建扩展模型定义,也可以在多个模型之间共享。 在创建新的模型时,或者反向工程到一个新的模型时,可以在新建模型的对话框中的 Extended Model Definitions 属性页中为模型附加(attach)一个或者多个扩展模型定义,如图 3-160 所示。 作者:姜江 error 326 图 3-160 为新模型附加扩展模型定义 这里和我们选择 DBMS 一样,也有 share 和 copy 两种方式来使用扩展模型定义。 导入扩展模型定义 建立模型之后,如果要为模型导入扩展属性定义,可以在 选择【Model】→【 Extended Model Definitions】,在弹出的扩展模型定义的列表窗口的上方, 点击工具【Import an Extended Model Definition】,在弹出的窗口中选择需要导入的扩展模型 定义,然后点击【OK】。 丢失扩展模型定义 为某个导入一个扩展定义后,实际上相当于在模型和扩展模型定义文件之间建立了一个连接。 和模型相关的扩展模型定义文件如果被重命名、移动活删除,那么这个连接就被破坏了。 这时,当你打开这个连接被破坏的文件时,就会弹出如图 3-161 所示警告窗口,窗口中显示 了丢失的扩展模型定义的文件名和路径,并且允许进行浏览和选择,打开丢失的扩展模型文件进 行连接,或者删除模型和该扩展模型定义之间的连接。 图 3-161 扩展模型定义连接破坏警告窗口 导入扩展模型定义 建立模型之后,可能为模型定义了扩展模型定义,如果你希望在其他模型中也可以共享这个 扩展属性定义,可以选择导出该扩展模型定义。特定模型中的扩展属性定义在导出之前时不会出 现在 PDM 的扩展模型定义列表中的,到处后就可以在这个列表中看到和选择。 导出的步骤如下: 1. 选择【Model】→【 Extended Model Definitions】弹出的扩展模型定义的列表窗口 作者:姜江 error 327 2. 在窗口右 上方,点击工具【Export an Extended Model Definition】 3. 弹出文件保存窗口,输入文件名,选择保存的路径 4. 然后点击【OK】,即完成导出工作。 这样,以后在其他的模型中就可以使用该扩展模型定义了。 D.为对象使用扩展属性 创建好扩展属性,并且使用扩展属性作为变量以后,我们就可以使用了,假设在这部分前面 的操作中 DBMS 为 SQL Server 2000,并且创建了一个扩展模型定义(New Extended Model Definition)。然后在模型中导入了扩展模型定义 PowerBuilder 和自定义的扩展模型定义(New Extended Model Definition),并且为 SQL Server 2000 和自定义的扩展模型定义文件都创建了一个 Metaclasses 为列的扩展属性。 双击图形模型中的表,在表的属性窗口中选择 Columns 属性页,或者选择【Model】→ 【Columns】,选择需要使用扩展属性的列,进入列的属性窗口,可以发现此时列的属性窗口中会 出现一个属性页 Extended Attributes,如图 3-162 所示。 图 3-162 为列定义相应的扩展属性 在 PDM 中使用扩展属性时,每个扩展属性都包括四个属性值,分别为 Name,Datatype(包括 integer;boolean;color,date,file,float,font 等等,以及自定义的数据类型),这些都是不可以修改的, Value 可以修改,如果不修改则显示为默认值,R 表示是否对 value 值重新设置,如果 Value 值被 修改,那么 R 复选框被选中 同时,可以发现在该属性页的下方:Microsoft SQL Server 2000、导入的 PowerBuilder 以及自 定义的扩展模型定义分别包含一个页面,可以分别使用三种不同的扩展属性:MSSQL SRV2000、 PowerBuilder、New Extended Model Definition。 关于使用扩展属性解决问题的应用,请参考附录:第 7 章 高级应用&网友常见疑难解答 (FAQ)7.6 问题六。 3.15.6 定制和使用物理选项 数据库的物理选项,通常可以用于优化数据库和存储的一些参数,例如,在 MS SQL Server 2000 作者:姜江 error 328 中,出于分配和管理目的,可以将数据库文件分成不同的文件组。一些系统可以通过控制在特定 磁盘驱动器上放置的数据和索引来提高自身的性能,这时就采用文件组(filegroup)的方式来管 理,系统管理员可以为每个磁盘驱动器创建文件组,然后将特定的表、索引、或表中的 text、ntext 或 image 数据指派给特定的文件组。先学习以下代码,从而了解物理选项的含义: ==================================== USE master GO -- Create the database with the default data -- FILEGROUP and the log file. Specify the -- growth increment and the max size for the -- primary data file. CREATE DATABASE MyDB ON PRIMARY ( NAME='MyDB_Primary', FILE NAME= 'c:\Program Files\Microsoft SQL Server\MSSQL\data\MyDB_Prm.mdf', SIZE=4, MAXSIZE=10, FILEGROWTH=1), FILEGROUP MyDB_FG1 ( NAME = 'MyDB_FG1_Dat1', FILE NAME = 'c:\Program Files\Microsoft SQL Server\MSSQL\data\MyDB_FG1_1.ndf', SIZE = 1MB, MAXSIZE=10, FILEGROWTH=1), ( NAME = 'MyDB_FG1_Dat2', FILE NAME = 'c:\Program Files\Microsoft SQL Server\MSSQL\data\MyDB_FG1_2.ndf', SIZE = 1MB, MAXSIZE=10, FILEGROWTH=1) LOG ON ( NAME='MyDB_log', FILE NAME = 作者:姜江 error 329 'c:\Program Files\Microsoft SQL Server\MSSQL\data\MyDB.ldf', SIZE=1, MAXSIZE=10, FILEGROWTH=1) GO ALTER DATABASE MyDB MODIFY FILEGROUP MyDB_FG1 DEFAULT GO -- Create a table in the user-defined FILEGROUP. USE MyDB CREATE TABLE MyTable ( cola int PRIMARY KEY, colb char(8) ) ON MyDB_FG1 GO ==================================== 这个例子在 SQL Server 2000 的默认实例上创建数据库。该数据库包括一个主要数据文件、 一个用户定义的文件组和一个日志文件。主要数据文件在主文件组中,而用户定义文件组有两个 次要数据文件。ALTER DATABASE 语句将用户定义文件组指定为默认文件组。之后,通过指定 用户定义的文件组来创建表。 在 PowerDesigner 中物理属性的可以通过两种方式来定义,一种是【Database】→【Default Physical Options】(默认物理属性),另外一种是对某个特定的对象设置物理属性。默认物理属性 可以被当前模型中的所有对象使用,也可以指定应用于模型中的某些对象。而对某个特定对象指 定的物理属性则可以覆盖默认的物理选项而使用自己的物理选项。 前面在创建表的过程中,已经讲到如何使用表的物理选项,请参考:3.4.2 创建表(D.表的 物理选项)在这里我们将学习如何在 PDM 中定制和使用 DBMS 的物理选项。 选择【Database】→【Default Physical Options】,弹出如图 3-163 所示窗口: 作者:姜江 error 330 图 3-163 定义默认的物理选项 图 3-163 所示,图中包含六个属性页,分别为:Table、Index、Alternate key、Primary key、 Storage 以及 Database。中间的三个工具按钮的含义分别为:Add selected item :将在左侧 Syntax 页中选择的 Item 加入到右边的 Items 页中;Synchronize selected item :将两侧的 物理选项的 Item 对齐;Removed selected item :将加入到右边的 Items 页中的物理选项 Item 删除。读者可以根据自己的需要定义合适的物理选项。 具体的操作办法如下: 1. 在左侧 Syntax 页中选择需要定义的项,点击【Add selected item】工具 ,如图 3-163 所 示,我们在 Primary keys 属性页中添加(%)项 2. 在右侧下方的编辑框中设置默认值为(该例中为 clustered) 如果模型中已经定义了 Storage,那么也可以点击编辑框右侧的 ,弹出 Storages 列 表,亦可选择【Model】→【Storages】,定义模型中的物理存储选项,定义好的 Storages 都 会出现在这里的编辑框的下拉列表中,这时,可以点击右侧窗口的 SQL 页面,观察产生的代 码。 3. 默认情况下,这里的物理属性会引用与模型中所有的对象(不包括那些在自己属性窗口中单 独设置了相应物理属性的对象),如果用户不希望对所有对象都应用这些默认物理属性,可以 选择对哪些对象应用默认物理属性,操作方法是:点击该窗口左下角的【Apply to... 】按 钮,在弹出的选择窗口中选择需要应用该物理选项的对象,点击【确定】按钮。如图 3-164 所示。 作者:姜江 error 331 图 3-164 选择要应用物理选项的对象 设置好之后点击【确定】按钮,关闭窗口。即完成了对物理属性的定义和修改。 接下来,我们双击图形模型中的表,进入 Keys 属性页,双击主键,在主键的属性窗口中点击 Options 物理属性页,可以看到,默认物理属性已经应用于该主键,而不需要另外定义,如图 3-165 所示。 并且表的生成代码也发生了相应的改变: ========================================== Create table tableName ( NAME char(10) not null, YR char(10) null, VER char(10) null, MOBILE char(10) null, constraint PK_ACCNT primary key clustered (NAME) ) ========================================== 图 3-165 已经应用默认物理选项的主键 而那些点击【Apply to„】 按钮后没有选中的表则不会受到默认物理属性的影响,还可以对已 作者:姜江 error 332 经使用了默认物理属性的对象的物理属性进行修改。 3.16 PowerDesigner 中的变量 3.16.1 PowerDesigner 变量列表 很多对象都既包含一个代码变量(code variable)又包含一个生成代码变量(generated code variable)。代码变量是在对象属性窗口中定义的属性代码,而生成代码变量则是根据对象的属性 代码和生成选项计算而产生的。以下的几种情况将向大家展示代码和生成代码的不同:  如果 Code 是保留字或者其中包含无效字符,则生成代码会用引号括起来  如果 Code 的长度超过了 DBMS 中限制的最大长度,则会自动截取 code 产生生成代码 命名对象变量: 表 3-85 命名对象变量 变量名 描述 @OBJTNAME 对象名称 @OBJTCODE 对象代码 @OBJTLABL 对象卷标 @OBJTDESC 对象描述 所有对象定义的变量: 表 3-86 所有对象定义的变量 变量名 描述 COMMENT 对象描述,如果没有定义描述则使用对象的 name OWNER 对象所有者或者对象的父对象的生成代码 DBPREFIX 对象的数据库前缀,如果定义了数据库,就是:数据库的名称+’.’ QUALIFIER 完整的对象限定词,数据库前缀+所有者前缀 OPTIONS 定义对象物理属性的 SQL 文本 CONSTNAME 对象约束的名称(name) CONSTRAINT 对象的约束 SQL 语句,例如 (A<=0) AND (A>=10) RULES 和对象相关的业务规则的服务器端的表达式的连接 用于定义表的变量: 表 3-87 定义表的变量 变量名 描述 作者:姜江 error 333 TABLE 表的生成代码 TNAME 表名称(name) TCODE 表代码(code) TLABL 表描述 PKEYCOLUMNS 主键列的列表,例如:学号,身份证号 TABLDEFN 表的完整定义部分,包括对列、约束以及键的定义 CLASS 抽象数据类型的名称 CLUSTERCOLUMNS 聚簇列的列表 用于定义域和列的检查参数变量: 表 3-88 定义域和列的检查参数变量 变量名 描述 UNIT 标准 check 的 Unit 属性 FORMAT 标准 check 的 Format 属性 DATATYPE 数据类型,例如:int,char(10),或者 numeric(8,2)等 DTTPCODE 数据类型的代码,例如:int,char 或者 numeric 等 LENGTH 数据类型的长度,例如:0,8,10 等 PREC 数据类型的精度,例如:0,2 等 ISRDONLY 如果标准 check 的只读(read-only)被选中,则值为“TRUE” DEFAULT 默认值 MINVAL 最小值 MAXVAL 最大值 VALUES 值的列表,例如:(0,1,2,3,4,5) LISTVAL 和值列表相关的 SQL 约束,例如:constraint1 in (0,1,2) MINMAX 和最大最小值相关的 SQL 约束,例如:(C1<=0) AND(C1>=5) ISMAND 如果是值为 TRUE,则表示 domain 或者 column 不可以为空 MAND 依赖于关键字是可以为空或不可为空,关键字“null”或者“not null”, NULL 如果 domain 或者 column 不是强制的,则关键字为“null” NOTNULL 如果 domain 或者 column 是强制的,则关键字为“not null” IDENTITY 如果 domain 或者 column 为 identity(标志),则关键字为“identity” WITHDEFAULT 如果 domain 或者 column 带有默认值,则关键字为“with default” ISUPPERVAL 如果标准检查的 upper-case 被选中,值为“TRUE” ISLOWERVAL 如果标准检查的 lower-case 被选中,值为“TRUE” 用于定义列的变量: 作者:姜江 error 334 表 3-89 定义列的变量 变量名 描述 COLUMN 列的生成代码 COLNNO 表中该列的位置编号 COLNNAME 列的名称 COLNCODE 列的代码 PRIMARY 如果该列为主键列,则包含关键字“primary” ISPKEY 如果列是主键的一部分,则值为“TRUE” FOREIGN 如果列是外键的一部分,则值为“TRUE” COMPUTE 计算约束的文本 用于定义抽象数据的变量: 表 3-90 定义抽象数据的变量 变量名 描述 ADT 抽象数据类型的生成代码 TYPE 抽象数据类型的数据类系国内,如“array”或者“list” SIZE 抽象数据类型的大小 ISARRAY 如果抽象数据类型的类型为 array,则值为“TRUE” ISLIST 如果抽象数据类型的类型为 list,则值为“TRUE” ISSTRUCT 如果抽象数据类型的类型为 structure,则值为“TRUE” ISOBJECT 如果抽象数据类型的类型为 object,则值为“TRUE” ISJAVA 如果抽象数据类型的类型为 JAVA class,则值为“TRUE” ADTDEF 包含抽象数据类型的定义 用于定义抽象数据类型属性的变量 表 3-91 定义抽象数据类型属性的变量 变量名 描述 ADTATTR 抽象数据类型属性的生成代码 用于定义域的变量 表 3-92 定义域的变量 变量名 描述 DOMAIN domain 的生成代码(对于列也有用) 用于定义业务规则的变量: 表 3-93 定义业务规则的变量 作者:姜江 error 335 变量名 描述 RULE 业务规则的生成代码 RULENAME 业务规则的名称 RULECODE 业务规则的代码 RULECEXPR 业务规则在客户端的表达式 RULESEXPR 业务规则在服务器端的表达式 用于定义索引的变量: 表 3-94 定义索引的变量 变量名 描述 INDEX 索引的生成代码 INDEXNAME 索引的名称 INDEXCODE 索引的代码 UNIQUE 如果是唯一性索引,则包含关键字“unique” INDEXTYPE 索引的类型,不同的 DBMS 中有不同类型 CIDXLIST 索引列的列表。例如:A asc,B desc,C asc INDEXKEY 根据索引的类型,包含关键字“primary”“ unique”“ foreign” CLUSTER 如果是聚簇索引,则包含关键字“cluster” INDXDEF 索引的定义(列的列表) 用于定义索引列的变量: 表 3-95 定义索引列的变量 变量名 描述 ASC 根据排序的类型,包含关键字“ASC”或者“DESC” ISASC 如果排序的类型是升序,则值为“TRUE” 用于定义引用的变量: 表 3-96 定义引用的变量 变量名 描述 REFR 引用的生成代码 PARENT 父表的生成代码 PNAME 父表的名称 PCODE 父表的代码 PQUALIFIER 父表的限定词 CHILD 子表的生成代码 作者:姜江 error 336 CNAME 子表的名称 CCODE 子表的代码 CQUALIFIER 子表限定词 REFRNAME 引用的名称 REFRCODE 引用的代码 FKCONSTRAINT 外键引用约束名称 PKCONSTRAINT 用于引用对象的主键的约束名 CKEYCOLUMNS 父键列的列表,例如:C1,C2,C3 等 FKEYCOLUMNS 子键列的列表,例如:C1,C2,C3 等 UPDCONST 删除 declarative 类型的约束,可能包含以下几种类型的关 键字:Restrict,Cascade,Set null,Set default DELCONST 更新 declarative 类型的约束,可能包含以下几种类型的关 键字:Restrict,Cascade,Set null,Set default MINCARD 最小基数 MAXCARD 最大基数 POWNER 父表所有者名称 COWNER 子表所有者名称 CHCKONCMMT 当选择了引用的 check on commit 时,则值为“TRUE” JOINS 引用连接 REFRNO 子表中引用的编号 用于定义引用列的变量: 表 3-97 定义引用列的变量 变量名 描述 CKEYCOLUMN 父表(主键)的生成代码 FKEYCOLUMN 子表(外键)的生成代码 PK 主键列的生成代码 PKNAME 主键类的名称 FK 外键类的生成代码 FKNAME 外键列的名称 AK 候选键的生成代码 AKNAME 候选键的名称 COLTYPE 主键列的数据类型 DEFAULT 外键列的默认值 HOSTCOLTYPE 使用在存储过程定义中的主键列数据类型,例如:without 作者:姜江 error 337 length 用于定义键的变量: 表 3-98 定义键的变量 变量名 描述 COLUMNS COLNLIST 键 column 的列表,例如:A,B,C ISPKEY 如果键是表的主键,则值为“TRUE” PKEY 主键约束名称 AKEY 候选键约束名称 KEY 键的约束名称 ISMULTICOLN 如果键多于一个列,则值为“TRUE” CLUSTER 聚簇关键字 用于定义视图的变量: 表 3-99 定义视图的变量 变量名 描述 VIEW 视图的生成代码 VIEWNAME 视图的名称 VIEWCODE 视图的代码 VIEWCOLN 视图的列的列表,例如:“A,B,C” SQL 视图的 SQL 脚本,例如:select * from student VIEWCHECK 如果在视图的属性窗口中选择了“with check option”复选框,则 包含 with check option 关键字 SCRIPT 完整的视图的脚本,例如:create view View_1 as select *from student 用于定义触发器的变量: 表 3-100 触发器的变量 变量名 描述 ORDER 触发器执行的顺序号(前提是当前 DBMS 支持多个同类型触发器) TRIGGER 触发器的生成代码 TRGTYPE 触发器的类型,例如:“BeforeInsert”,“AfterUpdate” TRGEVENT 触发器的事件,例如:“Insert”,“ Update”,“ Delete” TRGTIME 触发器触发的时间,例如:“Null”,“ Before”,“After” 作者:姜江 error 338 REFNO 表的引用列表中该引用的编号 ERRORNO 用户定义错误消息表中的错误号的列的名称 MSGTXT 用户定义错误消息表中的错误信息的列的名称 SCRIPT 触发器或者存储过程的 SQL 脚本 TRGBODY 触发器体(仅仅在 Oracle ODBC 反向工程时才可用) TRGDESC 触发器的描述(仅仅在 Oracle ODBC 反向工程时才可用) TRGDEFN 触发器的定义 用于定义数据库、触发器、存储过程的生成变量: 表 3-101 定义数据库、触发器、存储过程的生成变量 变量名 描述 DATE 生成的日期和时间 USER 执行生成时的登录的用户名 PATHSCRIPT SQL 脚本的存放路径 NAMESCRIPT SQL 脚本的文件名称 STARTCMD 如何生成脚本的描述 ISUPPER 如果选择了 upper-case 复选框,则值为“TRUE” ISLOWER 如果选择了 lower-case 复选框,则值为“TRUE” DBMSNAME 和生成模型相关的 DBMS 的名称 DATABASE 和生成模型相关的 DBMS 的代码 用于定义反向工程的变量: 表 3-102 定义反向工程的变量 变量名 描述 R 在反向工程时,将该值设为“TRUE” S 允许跳过一个单词,字符串通过语法检查,但是在反向工程时不被生成 D 允许跳过一个数字值,数字值通过语法检查,但是在反向工程时不被生成 A 允许跳过所有的文本,文本通过语法检查,但是在反向工程时不被生成 ISODBCUSER 如果当前用户是已经连接在数据库上的用户,则值为“TRUE” CATALOG 在 ODBC 反向工程查询时使用的 Catalog 名称 SCHEMA 在 ODBC 反向工程查询时使用的 Schema 名称 SIZE Column 或者 domain 的数据类型的大小。在 ODBC 反向工程时如果系统表中没 有定义数据类型的长度,则使用该长度 VALUE Column 或者 domain 的值的列表中的一个值 用于定义数据库同步的变量: 作者:姜江 error 339 表 3-103 定义数据库同步的变量 变量名 描述 OLDOWNER 对象的新所有者的名称 NEWOWNER 对象的旧所有者的名称 OLDQUALIFIER 对象的新的限定词 NEWQUALIFIER 对象的新的限定词 OLDTABL 表的旧代码 NEWTABL 表的新代码 OLDCOLN 列的旧代码 NEWCOLN 列的新代码 用于定义数据库安全的变量: 表 3-104 定义数据库安全的变量 变量名 描述 PRIVLIST 以 grant/revoke 的顺序列出 privilege 的列表 PERMLIST 以 grant/revoke 的顺序列出 permission 的列表 GRANTEE 以 grant/revoke 的顺序列出 user、group 和 role 的列表 ID User 的名称 GROUP Group 的名称 ROLE Role 的名称 OBJECT 数据库对象(表、视图、列等等) PERMISSION 数据库对象的 grant/revoke 顺序的 SQL 脚本 PRIVILEGE 某个 user、group 或者 role 的 grant/revoke 顺序的 SQL 脚 本 GRANTOPTION Grant 的选项:with grant option/with admin option REVOKEOPTION Revoke 的选项:with cascade 用于定义元数据(Metadata)变量: 表 3-105 定义元数据(Metadata)变量 变量名 描述 @CLSSNAME 对象类的局部名称,例如:Table,View,Column,Index @CLSSCODE 对象类的代码,例如:TABL,VIEW,COLN,INDX 用于定义 DBMS,数据库选项变量: 表 3-106 定义 DBMS,数据库选项的变量 作者:姜江 error 340 变量名 描述 TABLESPACE TABLESPACE 的生成代码 STORAGE Storage 的生成代码 用于定义 ASE&SQL Server 变量: 表 3-107 定义 ASE&SQL Server 变量 变量名 描述 RULENAME 和 domain 相关联的业务规则对象的名称 DEFAULTNAME 和 domain 相关联的默认对象的名称 USE_SP_PKEY 使用 sp_primary key 创建主键(SQL Server) USE_SP_FKEY 使用 sp_foreign key 创建外键(SQL Server) 用于定义 Sequence 变量: 表 3-108 定义 Sequence 的变量 变量名 描述 SQNC Sequence 的名称 用于定义存储过程变量: 表 3-109 定义存储过程的变量 变量名 描述 PROC 存储过程的生成代码(如果触发器使用存储过程实现,则也可以用于触发器) FUNC 存储过程的生成代码,其中存储过程为函数(带一个返回值) 用于定义连接索引的变量: 表 3-110 定义连接索引的变量 变量名 描述 JIDX 连接索引(join index)的产生代码 JIDXDEFN 连接索引(join index)的完整的定义 REFRLIST 针对 ODBC 的引用的列表 RFJNLIST 针对 ODBC 的引用连接列表 3.16.2 PowerDesigner 中对变量格式化 表 3-111 变量格式化代码 格式化代码 脚本中变量值的格式 作者:姜江 error 341 .L 将字符串转化为小写 .T 删除字符串首尾的空格 .U 将字符串转化为大写 .n 字符串的最大长度 N 字符串的固定长度 -n 从右端开始截取字符串中固定的长度,长度不足则使用空格补齐 如表 3-111 所示。对变量进行格式化的格式:%.format:variable%,例如:%.L:TABLE%,例 如表“学生”(code 为 student),格式化变量之后的结果为如表 3-112 所示。 表 3-112 变量格式化实例 变量名 最终脚本语句 Create trigger %TABLE% Create trigger student Create trigger %.L:TABLE% Create trigger student Create trigger %.U:TABLE% Create trigger STUDENT Create trigger %.4:TABLE% Create trigger stud Create trigger %.4U:TABLE% Create trigger STUD 3.17 PowerDesigner 10 中 PDM 模型的不同表示方法 第一章在介绍 PowerDesigner 10 的新特性的时候提到过,CDM 模型和 PDM 模型都增加了对 IDEF1X 表示方法的支持,下面我们就以一个模型为例,如图 3-166 所示。 图 3-166 未改变显示方法之前的模型实例 选择【Tools】→【Model Options】,弹出模型属性窗口,如图 3-167 所示。在 Notiation 下拉 列表中可以选择图形模型表示方法为 Relational、CODASYL(Conference on Data System Languages 数据系统语言会议)、Conceptual 以及 IDEF1X 四种,选择需要的表示方法后,点击【OK】确定。 作者:姜江 error 342 图 3-167 在模型选项窗口中选择不同的表示方法 各种表示方法的含义如表 3-113 所示。 表 3-113 PDM 不同表示方法 Notation 显示 图符 Relational 箭头指向主键 CODASYL 箭头指向外键 Conceptual 使用 Crow‟s feet 根据基数 的方法表示 IDEF1X 根据基数(Cardinality)和 是否可为空(Mandatory) 的状态显示在 Reference IDEF1X 表示方法: 某个表如果依赖另一个表(外键列同时还是主键),则该表显示为圆角矩形,如 图 3-168 所示。 图 3-168 IDEF1X 的表示方法 作者:姜江 error 343 是否可为空显示在 Reference 图形上的结果也不同,如图 3-115 所示。 表 3-114 是否 Mandatory 的不同显示情况 Mandatory Non Mandatory 不同的基数(Cardinality)的图形显示也不同,如所示。 表 3-115 基数对图形显示的影响 1 到多 0 到多 1 个 0 到 1 本例中的模型选择 IDEF1X 的转化结果如图 3-169 所示。读者可以通过该图形进一步认识 IDEF1X 的表示方法。 图 3-169 选择 IDEF1X 表示方法的模型图形 选择 Conceptual 的转化结果如图 3-169 所示。 图 3-170 选择 Conceptual 表示方法的模型图形 作者:姜江 error 344 关于 CODASYL 表示方法 世界上第一个网状数据库管理系统也是第一个 DBMS 是美国通用电气公司 Bachman 等人在 1964 年开发成功的 IDS(Integrated Data Store)。 IDS 奠定了网状数据库的基础,并在当时得到 了 广泛的发行和应用。1971 年,美国 CODASYL(Conference on Data Systems Languages,数据系统 委员会)中的 DBTG(Data Base Task Group,数据库任务组)提出了一个著名的 DBTG 报告,对 网状数据模型和语言进行了定义,并在 1978 年和 1981 年又做了修改和补充。因此网状数据模 型 又称为 CODASYL 模型或 DBTG 模型。 选择 CODASYL 表示方法的转化结果如图 3-171 所示,和最初的关系模型比较可以看出,关 系模型箭头指向主键,而在 CODASYL 表示方法中箭头指向外键。 图 3-171 选择 CODASYL 表示方法的模型图形 作者:姜江 error 345 第4章 数据仓库多维模型的创建和使用 本章首先介绍数据仓库、OLAP 的基本概念,然后结合 SQL Server 中自带的数据库 Northwind 为实例,系统讲述如何从需求出发设计数据仓库的模型,同时使用 PowerDesigner 进行多维模型 建模,还进一步介绍如何在 PowerDesigner 中通过 Objects Mapping(对象映射)功能完成数据仓 库的数据转移。 4.1 数据仓库的基本概念 在讲述如何使用 PowerDesigner 创建数据仓库的多维模型之前,有必要先了解数据仓库、OLAP 以及多维模型的一些基本概念。 随着计算机的广泛使用与普及,软件大量应用于企业中,为企业提供各种业务支持,从最基 本的信息录入与查询发展到现在的 ERP、CRM、DSS 等大型系统应用,数据库已经无所不在的应 用于几乎所有软件能够涉及的领域中。数据库与 OLTP(On Line Transaction Processing)已经成为 过去很多年最受到关注的话题之一。 但是,随着市场竞争的加剧和信息社会需求的发展,计算机的应用已经不仅仅是为了:“用信 息流代替肉流”这么简单,企业在面临大量数据,如企业财务状况、产品销售情况、产品的市场 占有率、供应商状况、客户的偏好等等。如何有效的利用这些数据,挖掘出有用的信息,从而更 好的为企业提供决策支持、提高自己的竞争力就成为发展的一个必然趋势,于是数据仓库、OLAP、 数据挖掘也就成为近来最热门的话题之一。 4.1.1 什么是数据仓库 企业经理人员需要对现有的数据进行系统组织、分析、理解,同时使用这些数据制定出更好 的战略决策,传统的数据库与 OLTP 主要是为了数据处理而产生的,而数据仓库的出发点则是分 析功能,数据仓库中不仅仅包含了分析所需要的数据,而且还包含了处理数据所需的应用程序, 因此数据仓库提供了能够支持这些工作的体系结构和工具。 简单的讲,数据仓库是同组合的操作型数据库分理的,数据仓库允许不同的应用系统能够整 合使用。数据仓库是面向主题(subject)的、集成的、随时间变化而变化的、稳定可靠的数据的 集合,能够支持管理决策过程。  面向主题:数据仓库通过一些主要主体进行组织,例如:客户,供应商,产品,销售, 而不是仅仅专注于每天的数据处理,因此数据仓库能够以主题为中心提供简单和清晰的 视图,辅助决策过程。  集成的:数据仓库通常将不同类型的数据库进行整合,例如关系数据库,文件数据库等 等,或者不同类型 DBMS 的数据库。数据仓库通过数据清洗、数据转化、数据集成等步 作者:姜江 error 346 骤将数据集成应用。  随时间变化而变化:存储在数据仓库中的数据试图从历史的角度提供信息,例如:过去 5 到 10 年,数据仓库中每个主要结构都显性或者隐性的包含着时间的元素。  稳定可靠的:数据仓库一般都是以单独服务的形式存在的,在物理位置上和数据源(一 般的操作型数据)是不同的,数据仓库不需要事务处理,数据恢复,并发控制等机制。 可以将数据仓库的应用理解为两个步骤:1:初始化载入数据;2:访问数据。 数据仓库和操作型数据库系统的不同 大部分软件开发人员都比较熟悉关系数据库的基本结构,因此,就比较容易理解数据库和数 据仓库的不同。 在线(On-Line)操作型数据库的主要任务是执行在线事务以及查询处理。这种类型的系统被 称为 OLTP(On-Line Transaction Processing)系统。OLTP 的应用覆盖了组织的日常操作的方方面 面,例如:购买,库存,生产,志福,注册,帐号管理等等。 另一方面,数据仓库系统的服务对象是那些需要进行数据分析和决策支持的用户或者知识工 作者。这种类型的系统能够根据不同用户的需求以不同的形式组织和表示数据。这样的系统就被 称作 OLAP(On-Line Analytical Processing)系统。 OLAP 与 OLTP 的主要不同有以下几点:  用户和系统导向:OLTP 系统是客户导向的,通常应用于事务处理和查询处理,用户通 常是客户、职员以及技术专家等。而 OLAP 系统是市场导向的,通常被知识工作者、管 理者应用于数据分析。  数据内容:OLTP 系统的数据一般是非常细节的当前操作型数据,不太适合决策支持的 使用,而 OLAP 系统则包含大量的历史数据,并且提供了数据聚合、概要的便利,以不 同的粒度和级别存储和管理信息,这些特点都是的 OLAP 能够较好的应用于决策支持。  数据库设计:OLTP 系统一般使用 ER(Entity-Relationship)实体关系模型的面向应用的 数据库设计,而 OLAP 系统则采用雪花模型或者星型模型的面向主题的数据库设计方法。  视图:OLTP 系统主要应用于企业或者部门的层面上的数据,而不参考历史数据或者其 他组织的数据。相反,OLAP 系统通常涉及不同架构的数据库(随着组织的发展,使用 的数据库也会变化),OLAP 处理的数据往往来源于不同组织,将许多数据源整合,因此 通常是海量数据。  访问模式:OLTP 中数据的主要访问模式是一些原子的、短暂的事务处理,这种系统要 求并发控制和恢复机制的完善。而 OLAP 中尽管可能会涉及到非常复杂的查询,但是一 般只对数据进行读的操作(因为大多数数据仓库中的数据是历史数据而不是实时的信 息)。 总之,OLTP 和 OLAP 系统之间有着诸多的不同,如表 4-1 所示。 表 4-1 OLAP 与 OLTP 系统对比 作者:姜江 error 347 特征 OLTP OLAP 特点 事务处理 信息处理 定为 事务 分析 用户 职员,DBA,数据库专家 知识工作者(例如,管理者、分析员) 功能 日常处理 长期信息需求,决策支持 数据库设计 基于 ER 模型,面向应用 星型/雪花型,面向主题 数据 当前数据;确保数据及时更新 历史数据;定时维护确保数据准确度 概要程度 原始的细节信息 概括信心,经过整理和固化的 视图 详细的水平关系 摘要概括的多维视图 工作单元 短并且简单的事务 复杂查询 访问 读/写 大部分都是读 集中点 数据的输入 信息的输出 操作 对主键的建立索引和哈希表 大量数据扫描 访问记录的数量 数十个 百万级 用户的数量 千量级 最多几百个 数据库规模 100 MB 到 GB 100 GB 到 TB 优先级 高性能,高可用性 灵活以及最终用户的自主权 衡量标准 事务吞吐量 查询吞吐量,响应时间 4.1.2 数据仓库中的基本概念 A.数据立方(Data Cubes) 数据立方允许数据通过多维模型建模,能够以多维的形式查看,数据立方通过维度和事实表 定义。 B.维度(Dimensions) 组织希望通过哪些视角或者实体来记录数据,通常,这些视角或者实体就是维度。例如销售 数据可能希望从时间、销售项目、位置、销售分部等视角来观察销售数据。每个维度可能都有一 个单独的表,这些表被称作维度表(Dimension Table)。 C.事实表(Fact Table)以及测量度(Measures) 事实通常是一些数字度量,这些数字度量往往是我们需要分析的业务数据,例如:销售额、 销售量以及预算费用等等。通常,事实表包含事实表的名称、测量度(Measures),以及相关的维 度表的键。 D.概念层次(Concept Hierarchies) 概念层次(Concept Hierarchies)定义了一系列从低层次概念到高层次(或者更一般的)概念 的映射关系,层次可能是一种组织性的导航的路径(例如,维度表中最一般属性的到最特殊的属 作者:姜江 error 348 性,是一个有顺序的属性的子集),也可能是一种合并的路径(例如:时间的层次可能是将 day 合 并到 week 中;将 week 合并到 months 中;将 month 合并到 quarter 中;将 quarter 合并到 year 中)。 例如,如图 4-1 所示,该图展示的层次关系是维度“Location”的层次关系: 图 4-1 维度“Location”的层次关系 很多概念层次在数据库架构中都是不明显的,例如,维度表“Location”中包含以下属性: number, street, city, province_or_state, zipcode 以及 country,这些属性可以形成一个概念 层次:“street 等表示属性在层次中所处的层级。 使用相同的方法,对模型中其他的维度表进行层次定义。 维度表 Time 在创建时仅仅添加了一个属性 orderDate,这是因为时间属性本身就具有层次, 作者:姜江 error 360 这里为了多维模型处理的方便,添加另外的几个属性,如图 4-25 所示。 图 4-25 为维度表“Time”添加好属性 4.2.5 重建立方体(Rebuild Cubes) 重建立方体(Rebuild Cubes)根据模型中定义的事实类型或者维度类型的表来自动创建立方 体。重建立方体的功能会自动将事实表转化为一个相同名称的事实和一个立方体,事实表中的列 则会自动转化为事实中的 Measure,而维度表则会转化为维度。 因此,可以先在物理数据模型图中设计数据仓库的架构,即设置表的事实类型或者维度类型, 然后利用重建立方体的功能自动生成事实、维度以及立方体。然后再根据需求对自动生成的多维 对象进行修改定制,满足特定的需求。 定义表的类型 PDM 中的表可以在表的属性窗口的 General 属性页中指定表类型,有两种类型:维度表(Fact Table)和事实表(Dimension Table),维度表如图 4-26 所示,事实表如图 4-27 所示。 图 4-26 维度表的图形显示 图 4-27 事实表的图形显示 重建立方体的操作步骤如下: 1. 如果在物理数据模型图下面选择【Tools】→【Multidimension】→【Rebuild Cubes】,如果在 多维模型图形中则选择 Tools—Rebuild Cubes 2. 如果 PDM 中不包含定义为 Fact 类型的表,则弹出错误窗口,如图 4-28 所示。 图 4-28 重建立方体的错误警告信息 3. 如果 PDM 中已经定义了相应的 Fact 类型的表则会弹出重建窗口,如图 4-29 所示。 作者:姜江 error 361 图 4-29 选择是否保留以前的对象 4. 选择 Delete and Rebuild(重建之前删除以前重建的对象)或者 Preserver(保留所有以前重建 的对象) 5. 点击【确定】按钮,如果当前物理数据模型中不存在多维模型图,则 PowerDesigner 会自动创 建,生成多维模型图,如图 4-30 和图 4-31 所示。 其中,反向工程生成的模型已经自动找出了多维对象(Retrieve Multidimensional Objects),请 参考下一节:4.2.6 自动找出多维对象(Retrieve Multidimensional Objects)。 图 4-30 重建立方体生成的多维模型图形一 作者:姜江 error 362 图 4-31 重建立方体生成的多维模型图形二 可以看出,事实表转化为立方体,而事实表相关的维度表则转化为维度,同时,和事实表相 关的维度表如果还有父表,则父表和子表合并为一个维度,采取的命名方式为:“父表名称_子表 名称”。 4.2.6 自 动 找 出 多 维 对 象 ( Retrieve Multidimensional Objects) 前面主要介绍了根据需求确定事实表和维度表,然后可以根据这些维度表和事实表自动创建 事实、维度以及立方体。PowerDesigner 可以根据物理数据模型中表的关系,自动找出多维对象 (Retrieve Multidimensional Objects),这个功能主要通过分析表之间的引用关系来推断出多维对 象,其中:  子表被转化为事实表  沿着子表到父表的路径,所有的父表都会被转化为维度表(即使它同时也是其它表的子 表) 操作步骤如下: 1. 选择【Tools】→【Multidimension】→【Retrieve Multidimensional Objects】,弹出如图 4-32 所 示窗口: 图 4-32 “Multidimensional Object Retrieval”窗口 作者:姜江 error 363 2. 在 General 属性页中选择要取出的多维对象类型,在 Selection 属性页中选择需要转换的表,该 例中选择全部,点击【确定】按钮,该物理模型转化为如图 4-33 所示模型: 图 4-33 找出多维对象后的模型图形 由此图可以看出,沿着子表到父表的路径,所有的父表都会被转化为维度表(即使它同时也 是其它表的子表)。 但是,不论是 Retrieve Multidimensional Objects 还是 Rebuild Cubes,这些自动功能都不能代 作者:姜江 error 364 替真正的设计工作,毕竟软件无法判断那些数据对于业务分析能够起到真正的作用,因此,这些 功能只是为用户提供一些便利,自动生成的这些模型还必须进行手动修改和定制,切勿盲目使用。 4.3 在 PDM 中映射对象 对象映射是指在不同模型的不同图形中的不同对象只见建立一种对应关系。在 PDM 中,可 以在物理对象和多维对象之间建立连接,从而满足以下需要:  关系和关系映射:物理对象之间的映射,目的是产生将业务运营数据填充到数据仓库中 的提取脚本。  关系到多维:物理对象和多维对象之间的映射,目的是生成包含立方体数据的文本文件, 这些文本文件最终要添加到 OLAP 的数据库中。 可以在 PDM 中的对象之间创建映射关系的结构,这样可以在数据源和目标数据库之间建立 映射关系,从而顺利的完成数据移动和数据转化工作。数据转化(Transformation)在数据仓库设 计中是非常重要的一部分内容。 在 PowerDesigner 中数据源和目标数据库都可以在物理数据模型中设计。如图 4-34 所示。 图 4-34 数据库设计和数据仓库设计的关系 从上图可以看出其中转化的类型包括:  从业务运营数据到数据仓库数据的转化  从数据仓库到 OLAP 数据库的转化  从业务运营数据到 OLAP 数据库的转化:这种转化方式不常见 通常运营数据需要先存储到数据仓库的数据库中然后再到 OLAP 引擎中使用。不过如果 数据量不是很大的话,也可以考虑跳过数据仓库这一步,直接将运营数据库中的数据转化到 OLAP 引擎中。 其中,DataSource(数据源)通常是一数据集市,数据源中的数据被抽取出来转化到目标数 据库中,对象映射主要是将数据源中的对象和需要接收数据的我数据库中的对象之间建立连接: 批注 [e25]: 此处图形已翻译 作者:姜江 error 365  关系到关系之间的映射:在数据源模型中的表和视图与目标模型中的表之间建立关联。  关系到多维之间的映射:在数据源模型中的表和视图与目标模型中的立方体(cubes)和 事实(facts)之间建立关联。 映射可以理解为一种查询,实际上在目标表或者立方体中映射也以查询的方式表示,相当于 通过映射关系从数据源中取出数据转化到目标数据库中。 下面继续以 Northwind 数据库为例,学习如何在 PowerDesigner 中完成对象之间的映射。 创建数据源 假设前面的部分中,反向工程生成的物理数据模型名称为 North,创建事实、立方以及维度产 生的模型名称是 North_DW。因此,需要为多维模型 North_DW 创建数据源。 创建数据源的步骤如下: 1. 选择【Model】→【DataSource】,,弹出数据源列表窗口 2. 点击空白行或者添加工具 ,添加一个新的数据源 3. 输入 Name 和 Code 为 DW_Source,点击属性工具 ,进入数据源属性窗口 4. 进入 Models 属性页,点击窗口中的添加模型工具 ,弹出模型选择窗口,选择数据源的模 型,窗口中显示当前 Workspace 中打开的模型,如图 4-35 所示。 图 4-35 选择模型作为数据源 5. 点击【OK】,进入 ODBC 属性页,定义该数据源的 ODBC 数据源,连接 SQL Server 中的数据 库 Northwind,这里就不再赘述 ODBC 的建立方法,如图 4-36 所示。 作者:姜江 error 366 图 4-36 在数据源属性窗口的“ODBC”页定义 ODBC 数据源 6. 点击【确定】按钮。 4.3.1 关系模型到多维模型之间的映射 比较合理的路径是:先通过关系和关系之间的映射将数据库的数据转化到数据仓库中,然后 通过关系模型之间的映射将数据仓库中的数据映射到 OLAP 中。 A.在维度和关系型数据库之间进行映射 操作步骤如下: 1. 双击图形模型中的维度 Products,弹出维度属性窗口,进入 Mapping 属性页,Add a mapping for a Data Source ,在弹出的窗口中选择定义好的数据源 DW_Source,点击【OK】。点击窗口 上方的【Add Objects】工具 ,弹出的窗口中列出数据源 Dw_Source(即物理数据模型图形 North)中的表作为这个维度的数据源,选择 Products,点击【OK】。如图 4-37 所示。 图 4-37 为维度表添加数据源 2. 进入映射 Tab 页中下方的 Attributes Mapping 的 Tab 页,进行属性的映射,点击工具【Add Mapping】,弹出如图 4-38 所示的选择窗口: 作者:姜江 error 367 图 4-38 定义属性映射 3. 选择所有的属性,表示需要为这些属性定义映射,点击【OK】 4. 如果要根据数据源进行映射,则点击【Create from Sources】工具 ,弹出如数据源中列的选 择窗口,如图 4-39 所示。 图 4-39 根据数据源定义属性映射 5. Generate Mapping 工具 ,则表示如果存在数据源和属性名称和代码的对象,建立映射 6. 在 Attributes Mapping 的 Tab 页面上进行属性映射,结果如图 4-40 所示。 图 4-40 映射关系页“Mapping” 7. 在 Criteria 属性页中可以设置映射的条件,相当于 select 语句中的 where 条件,例如:输入 作者:姜江 error 368 productID>500,在 Select 的属性页中可以看到生成的数据抽取代码,如图 4-41 所示。 图 4-41 数据抽取代码(SQL 语句) 8. 点击【确定】按钮。该维度的映射关系建立。 使用同样的方法,对其他的维度建立各自的映射。不同的映射需要不同的 sql 语句进行数据 抽取,根据需要进行定制,例如:时间维度的 SQL语句为:select distinct Orders.OrderDate "orderDate" from Orders,因为订货日期可能会重复,因此使用了 DISTINCT 关键字。 B.在事实和关系型数据库之间进行映射 在事实和关系型数据库之间进行映射,操作的步骤同维度的操作基本相同,为事实表建立数 据映射,数据源为 Orders、Order Details、Employees、Products、Suppliers、Customers,这里就不 再描述操作方法。值得一提的是,比较复杂的 SQL 语句可以在 Attributes Mapping 的 Tab 页中点 击 工具来编辑,如图 4-42 所示。 图 4-42 使用“SQL Editor”编辑数据映射代码 最后生成的 SQL 语句也可以通过点击【Edit】工具 编辑,如图 4-43 所示。 作者:姜江 error 369 图 4-43 使用“SQL Editor”编辑生成的数据抽取代码 最后产生的映射 SQL 语句如下: =======================================select Employees.EmployeeID "employeeID", Products.ProductID "productID", Suppliers.SupplierID "supplierID", Customers.CustomerID "customerID", Orders.OrderDate "orderDate", Products.UnitPrice "unitPrice", dbo."Order Details".Quantity*dbo."Order Details".Quantity*(1-dbo."Order Details".Discount) "total", "Order Details".Quantity "quantity", "Order Details".Discount "discount" from Employees, "Order Details", Orders, Products, Suppliers, Customers where Orders.CustomerID = Customers.CustomerID and Orders.EmployeeID = Employees.EmployeeID and "Order Details".OrderID = Orders.OrderID and "Order Details".ProductID = Products.ProductID and Products.SupplierID = Suppliers.SupplierID ======================================= C.自动映射 作者:姜江 error 370 可以使用 Rebuild Cubes(重建立方体)自动根据 Fact 和 Dimension 类型的创建 Cubes 和 Dimensions,源表和生成的 OLAP 之间的对象会自动建立映射,例如,双击在自动重建(请参考: 4.2.5 重建立方体(Rebuild Cubes))部分生成的维度 Categories_Products,进入 Mapping 属性页, 可以发现映射已经自动建立,如图 4-44 所示。 图 4-44 重建立方体时自动建立的映射关系 4.3.2 生成立方体数据(Generate Cube Data) 立方体数据生成功能可以生成一些文本文件,而这些文本文件可以通过 OLAP 工具用于从业 务运营数据源中创建立方体,同事填充数据到立方体。定义好之后关系和多维模型之间的映射之 后,就需要生成立方体数据了。 在多维模型中,每个立方体都和一个查询语句向关联,而这个查询语句实际上就是和该立方 体相关的 Fact(事实表)的查询语句。如图 4-45 所示,可以直接从数据库生成立方体数据到 OLAP 数据库中,但是如果数据量比较大的话,最好通过数据仓库转化数据。数据源的创建是定义数据 的来源。 图 4-45 立方体数据到 OLAP 数据库 批注 [e26]: 此图已经过翻译 作者:姜江 error 371 具体的操作步骤如下: 1. 在多维模型状态下,选择【Tools】→【Generate Cube Data】,弹出 Cube Data Generation 窗口, 如图 4-46 图 4-47 所示。 图 4-46 立方体数据生成窗口 2. 设置生成文件的目标保存目录 3. 在 Selection 属性页中选择需要生成的立方体和数据源 4. 点击【确定】按钮。生成的一个文件如图 4-47 所示。 图 4-47 生成的立方体数据文件 4.3.3 关系模型和关系模型之间的映射 数据仓库需要从数据源中抽取、转化数据,可以在数据仓库和业务运营数据库的对象之间建 立关系和关系的映射。如图 4-48 所示。 作者:姜江 error 372 图 4-48 关系和关系之间的映射 定义关系模型和关系模型之间的映射,操作的方法与关系模型和多维模型之间的映射方法基 本相同,这里不再赘述。 4.3.4 生成数据抽取脚本 完成映射之后,就需要生成数据抽取脚本,该脚本用于从数据源中抽取数据填充到数据仓库 中,在 PowerDesigner 中可以为每个数据源都单独生成一个数据抽取脚本,脚本的名称和数据源 的名称相同,如果没有定义数据源,则不会产生任何文件,也不会报错,具体的操作步骤如下: 1. 在物理图形状态下,选择【Database】→【Generate Extraction Script】,弹出 Extraction Script Generation 对话框,如图 4-49 所示。 图 4-49 生成数据抽取脚本窗口 2. 选择生成文件的存放目录,在 Options 属性页中设置生成脚本的相关参数 3. 在 Selection 属性页中选择需要在脚本中生成的对象的抽取数据脚本。 4. 点击【确定】按钮。生成的文件会自动保存在选定的目录中。 注意:即使该模型中没有定义数据源,PowerDesigner 也会提示:Script Generation completed, 批注 [e27]: 此图已经过翻译 作者:姜江 error 373 Generation successful,但并不生成任何文件。 4.4 设计数据仓库的步骤 在 PowerDesigner 中,比较合理的设计数据仓库的步骤是:先通过关系和关系之间的映射将 数据库的数据转化到数据仓库中,然后通过关系模型之间的映射将数据仓库中的数据映射到 OLAP 中。在这一节中,我们将通过 PowerDesigner 自带的示例模型来了解设计的大致过程,这部 分内容设置在本章的最后部分,主要目的是希望能使读者对前面学习的内容有一个总体的把握和 回顾,起到提纲挈领的作用。 PowerDesigner 的文件目录 Sybase\PowerDesigner 9\Examples\Tutorial 中,包含两个 PDM 文件, 分别是 pdmbusin.pdm 和 pdmafter.pdm,其中,文件 dmafter.pdm 中包含一个物理数据模型图形 Publishing industry *,而 pdmbusin.pdm 中的模型 Business Intelligence 包含一个物理模型图形 PhysicalDiagram_1 和一个多维模型图形 MultidimensionalDiagram_1。 如图 4-50 所示,该模型为 OLTP 数据库的结构: 作者:姜江 error 374 图 4-50 设计 OLTP 数据库结构 根据业务数据分析的需求,创建数据仓库的应用,建立数据仓库模型,设置表的类型(事实 表或者维度表),产生如图 4-51 所示的数据仓库模型: 图 4-51 创建多维数据仓库模型 作者:姜江 error 375 创建数据仓库模型完成之后,完成数据库到数据仓库之间的映射,也就是关系模型到关系模 型之间的映射。最后生成数据库的数据抽取脚本(Generate Extraction Scripts)。最后,设计多维模 型,设计相关的事实和维度,以及立方体,并在立方体和事实之间建立关联,如图 4-52 所示。 图 4-52 创建数据库到数据仓库的映射后的多维模型 上图中没有显示出立方体和事实之间的关系,可以使用重建立方体(Rebuild Cubes)功能完 成立方体的自动生成,也可以在立方体属性窗口中指定 Fact。 然后建立数据仓库到多维模型之间的映射,即关系模型到多维模型的映射,映射完成之后, 生成立方体数据(文本文件)。至此多维模型的设计和映射基本完成。 作者:姜江 error 376 第5章 文档生成―Report 随着软件危机的出现、以及软件行业的不断进步与发展,软件工程越来越受到人们的重视, 而文档在软件工程中具有举足轻重的地位。文档的目的是用来尽可能详细地记录项目过程中的各 种材料和信息,方便开发团队内部分析设计成员、测试人员、管理人员、客户、维护人员之间的 交流和沟通,从而提高软件开发质量,降低维护成本。文档虽然重要,但却要切忌 “为了文档而 文档”,目前比较普遍的情况是:很多软件人员不做设计,而是一开始就直接编码,至于文档,则 在程序开发完之后,为了“完成组织交代的任务”而“补文档、补设计”。我们必须清楚的认识到: 文档并不是目的,而是一种手段。有了正确的认识才能确保“动机”始终在正确的轨道上,利用 文档,真正的提高软件开发的效率与质量。 本章主要内容和学习思路如下:  ReportEditors 和 Report Template Editor  通过实例学习对模型中的各种对象和图形创建 Report 文档  预览并生成 HTML 或者 RTF 格式的文档  报告中的节(Section)以及多模型 Report  学习 Report Language Editor 创建和修改编辑模板语言的 resource 文件(源文件),并且通 过实例以向导的形式学习如何创建“数据词典”。 5.1 使用 ReportEditors 这一节中主要介绍使用 Report Template Editor(报告模板编辑器)创建和编辑报告模板,并 且使用 Report Editor(报告编辑器)和 Multi-Model Report Editor(多模型报告编辑器)为一个或 者多个模型创建和编辑报告。 5.1.1 ReportEditors 介绍 Report 是用户定义的关于模型、对象的结构以及选择模型中的哪些对象等一系列信息的集合。 在 PowerDesigner 中可以使用预定义的报告结构,也可以根据自己的需要添加特定的对象。 Report Template Editor(报告模板编辑器)则是一个单独的模块,可以通过它来创建和修改报 告的模板。在没有任何模型的情况下也可以打开报告模板编辑器。 而 Report template(报告模板)是独立的、可以被重用的一些存储在磁盘上的文件,它指出 最终生成的报告中包含哪些信息。 Report Editor(报告编辑器)和 Multi-model Report Editor(多模型报告编辑器)分别为一个模 型或者多个模型定义报告的结构,选择报告中需要包含的对象,这两种编辑器使用相同的图形界 作者:姜江 error 377 面。 Report Language Editor(报告语言编辑器)也是一个单独的模块,在当前 workspace 没有打开 模型的情况下也可以打开该编辑器。可以通过该编辑器创建或修改 Language Resource File(语言 源文件),而语言源文件可以和报告之间建立连接,从而使得可以生成出英语之外的其他语种的报 告。 5.1.2 使用 Report Template Editor(报告模板编辑器) 使用 Report Template Editor(报告模板编辑器)可以创建或者修改报告的模板,也可以将模 板文件存为后缀名为 RTP 的文件。 打开报告模板编辑器 1. 选择【Tools】→【Resources】→【Report Template】,弹出报告模板的列表窗口 List of Report Template,如图 5-1 所示。 图 5-1 报告模板列表窗口 可以在 Type 下拉列表中选择模板的类型,选择具体的类型后,下面的列表框就只显示该 类型的模板,如图 5-2 所示。 图 5-2 选择新建报告模板类型 打开报告模板列表窗口的另外一种方法是在当前 workspace 中有模型打开时,选择 【Model】→【Reports】,弹出如图 5-3 所示窗口,点击【Manage Templates】按钮: 作者:姜江 error 378 图 5-3 当前模型报告列表 2. 选择某模板,然后点击属性工具 ,或者双击该模板,弹出模板编辑窗口,如图 5-4 所示。 图 5-4 报告模板编辑窗口 该窗口左侧列出了 Available items,即所有的可用项目,右侧是 Template items,即当前模板 中包含的项目和模板的结构。 标准报告模板 默 认 情 况 下 ,PowerDesigner 会自带一系列预定义的报告模板,标准的模板安装在 PowerDesigner 的目录 PowerDesigner 9\Resource Files\ Report Templates 目录下面,如图 5-5 所示。 图 5-5 标准报告模板文件 每种类型的模型都包括三种类型的标准模板,模板类型如表 5-1 所示。 表 5-1 报告标准模板类型 模板类型 命名规则 生成报告中的内容 作者:姜江 error 379 Full modelFULlanguage.RPT 目录,所有主要的模型项目 Standard modelSTDlanguage.RPT 目录,模型图,包图,大部分 list 对象 List modelLISlanguage.RPT 标题对象,所有 list 对象 注意,language 为报告模板使用的语言,通常用两个字母表示,例如:一个 PDM 的 List 类型 的报告模板的文件名称为:pdmlisus.rtp. 创建报告模板 如果列表中没有适合的模板,而需要自定义模板,具体的操作方法如下: 1. 选择【Tools】→【Resources】→【Report Templates】,弹出报告模板列表窗口,点击该窗口上 方的【New】 工具,弹出如图 5-6 所示窗口。 图 5-6 选择新建报告模板的类型 2. 在该窗口中输入模板的名称 3. 在 language 下拉列表中选择语言的类型 4. 在 Type 框中选择模型的类型,点击【确定】按钮,弹出该模板编辑窗口,如图 5-7 所示。 图 5-7 报告模板编辑窗口 可以右键左侧 Available items 中的项目,在弹出的菜单中选择 Add,将该 item 添加到右侧的 模板定义中。 5. 要保存该报告模板,选择【File】→【Save】,弹出标准的保存窗口,为该文件指定保存的路 径,输入文件名,点击【保存】按钮。 注意:在 workspace 的浏览器部分,右键 workspace,在弹出的菜单中选择 Add,在弹出的文 件打开窗口中选择一个 rtp 文件,可以打开报告模板。 作者:姜江 error 380 5.2 创建模型 Report 这部分将学习如何在 PowerDesigner 中创建模型报告,并使用模型报告生成 RTF 或者 HTML 格式的文档。 5.2.1 创建模型报告 要为模型创建报告,必须保证该模型在 Workspace 中处于打开状态,为模型创建报告的具体 操作步骤如下: 1. 选择【Model】→【Reports】,弹出报告列表窗口 List of Reports,该窗口会以字母顺序列出当 前模型的所有报告,如果还没有为当前模型创建报告,则除了 New Report 工具 以外,其 他工具栏中的工具都为灰化,如图 5-8 所示。 图 5-8 当前模型报告列表窗口 2. New Report 工具 ,弹出创建报告对话框 New Reports,如图 5-9 所示。 图 5-9 新建报告窗口 3. 在 Report name 编辑框中输入报告的名称 4. 在 Language 下拉列表中选择报告的语言,英语为默认语言。 5. Report template 下拉列表中选择该报告的模板,如果不希望应用任何模板,可以选择 none 6. 点击【OK】确定,弹出报告编辑窗口,如图 5-10 所示。 作者:姜江 error 381 图 5-10 浏览树中的报告结点以及报告编辑窗口 7. 如图 5-10 所示,Workspace 中当前模型中多了一个包 Reports,并且产生一个 Item,该 Item 名称即为创建的报告的名称。 8. 可以在该 Report 编辑窗口中对报告的结构进行定制。这部分内容请参考:5.3 定制模型报告。 在报告编辑窗口的状态下,PowerDesigner 都提供了一组快捷工具,可以在工具栏点击鼠标右 键,在弹出的菜单中,使得 Report 工具变为选中状态,或者选择【Tools】→【Customize Toolbar】, 在弹出的窗口中选中复选框 Report,如图 5-11 所示。 图 5-11 打开“Report”工具栏 工具栏中个工具的含义参考表 5-2。 表 5-2 “Report”工具栏各工具含义 工具 名称 功能 Print Preview 打印预览报告 Print 打印报告 Generate RTF 生成 RTF 格式的报告文件 Generate HTML 生成 HTML 格式的报告文件 Add Item 将 Available items 中的 item 增加到 Report 中 作者:姜江 error 382 Up One Level 当前项目向前移动一个位置 Down One Level 当前项目向后移动一个位置 Raise Level 当前项目提高一级 Lower Level 当前项目降低一级 5.2.2 预览生成报告 在报告编辑窗口状态中,可以选择【File】→【Print Preview】或者点击【Report】工具栏中 的【Print Preview】工具 ,打开打印预览窗口,如图 5-12 所示。 图 5-12 预览生成报告 在预览窗口中查找对象 在打印报告或者生成报告以前,用户可以在打印预览窗口中查找特定的对象,从而快速浏览 报告,具体的操作方法如下: 1. 在预览窗口中点击查找工具 ,如果报告为多模型报告,则需要选择在哪个模型中查找,如 图 5-13 所示。 作者:姜江 error 383 图 5-13 在预览窗口中查找对象 2. 在 Object type 下拉列表中选择需要查找的对象类型 3. Available objects 中的对象会随着选择对象类型的不同而变化 4. 点击【Find】,查询结果会显示在最下方的表格中显示查找的结果的主题和所属页的页码。 5. 选择需要查看的主题,点击【Display】,预览窗口会自动跳至包含该主题对象的页面中。 5.2.3 生成模型报告 生成模型报告可以生成 RTF 格式、HTML 格式,也可以直接打印,操作步骤如下: 1. 在 Workspace 的当前模型中双击 Reports 包下面的一个 report 节点(node),或者选择【Model】 →【Reports】,在弹出的列表窗口中选择要生成的报告,点击【OK】。 2. 根据需要选择【File】→【Print(Print Preview) 】或者【File】→【Generate】→【RTF】或者 【File】→【Generate】→【HTML】 3. 如果选择了 HTML 或者 RTF,会弹出保存文件窗口。 快捷方法:鼠标右键 workspace 的 Browser 中的一个 report 节点,在弹出的菜单中选择【Print】、 【Preview】、【Generate】→【RTF】或者【Generate】→【HTML】 5.3 定制模型报告 5.3.1 管理报告中的项目 在模型报告中可以使用如表 5-3 所示几种类型的项目: 作者:姜江 error 384 表 5-3 模型报告中 Item 类型 Item(项目) 描述 Node(节点) 包含子项目的节点,在 Report Editor 显示为书状 图标 Model-dependent item(依赖模型的项目) 包含模型或者包的信息的项目 Object list(对象列表) 模型或者包中对象的里列表 Object-dependent item(依赖对象的项目) 包含某个特定对象类型的信息,只能包含在对象节 点下面作为子节点 Independent item(独立项目) 能够在报告中的任何位置出现(例如:内容目录或 者图形) 向 Report 中添加项目 在 Report Editor 中可以使用 Available Items 面板中的项目添加至 Report Items 面板中,具体的 操作方法有以下三种:  用鼠标将项目拖拉至 Report Items 面板 拖动项目时,必须为项目在 Report Items 面板中寻找一个位置,目标位置通常显示为一 跳横线。如果拖动一个项目在一个节点上,如果显示为一条线,则项目被插入到该位置,如 果该节点显示为包含在一个方框中(高亮显示),那么该项目被插入为该节点子项目,位置在 最后;如果拖动一个项目到另一个项目上,Report Items 面板中的 item 如果显示为高亮或者 被一个方框包含,则项目被插入到该项目后面。 注意:拖动方法如果在目标位置显示为禁止符号,则表示该位置不可以插入该项目。  双击项目 双击 Available Items面板中的项目时,则该项目被插入到 Report Items面板中光标的位置。 如果光标所在的节点还包含子节点,那么被双击的节点将作为该节点的子节点插入,否则插 入到该节点后面。如果光标在根节点或者是 Report Items 面板中最后一个项目上,那么项目 被插入到最后的位置上。  在 Available Items 面板中鼠标右键项目,在弹出菜单中选择 Add 注意:用鼠标选取项目的时侯,可以同时按住 CTRL 键选择多个项目,也可以同时按 SHIFT 键选择连续的几个项目。 某个项目被添加至 Report Items 面板后,该项目仍然会在 Available Items 中显示,并且可以将 相同的项目插入到同一个报告中的不同位置。 添加 Node:节点,即包含子节点的项目,该项目的所有子项目也会被自动添加,如果用户不 需要这些子项目,可以是用右键菜单或者工具栏工具将子项目删除。 添加 Table of contents:table of contents(目录项目)完整的规定了节点标题和对应的页码, 可以在报告中的任何位置插入目录项目。插入目录项目后,不需要再插入 Page Break(分页项目) 作者:姜江 error 385 项目,因为 PowerDesigner 会自动在每个目录项目后面分页。 添加 Text paragraph:文本段落在 Report Editor 中显示为: 。插入文本段落后,可以双击 该项目,或者右键鼠标在弹出的菜单中选择 Edit,都会弹出文本编辑窗口,如图 5-14 所示。 图 5-14 项目文本编辑窗口 输入文字,可以点及 Format 按钮设置文本的字体格式等,点击【OK】确定。 添加图形和文本文件:报告中可以插入 ASCII 格式的文本文件(Text file)或者图形文件 (Graphic file)。在 Available Items 面板中双击文本文件或者图形文件的项目图标,会弹出标准的 打开文件窗口,选择要添加的文件,点击【确定】按钮。 添加图形:可以为 Report Items 面板添加模型中的图形,插入某个包中的图形项目时,报告 就会打印包中的所有图形。如图 5-15 所示,该图打印模型中的所有图形。如图 5-16 所示,该图 打印模型中每个包的图形。 图 5-15 添加模型中所有图形到报告中 图 5-16 添加每个包的图形 重新定位项目在报告中的位置:通过在 Report Items 面板中拖拉的方法可以改变报告中项目 的顺序。报告中唯一不能重新定位或者删除的项目是报告中每个节(Section,参考:5.5 报告中 的 Section(节))的根节点。拖动一个节点(Node)时,和依赖于该节点的项目也会随着该节点 被拖动。除了拖动外,还可以在 Report Items 面板中通过在需要重定位的项目上点击鼠标右键, 在弹出的菜单中选择 Up 或者 Down。 改变项目在报告中的深度:项目在报告中的深度就是指它所处的结构级别(可以理解为目录 级别),一般而言,项目在报告中的深度都是可以改变的,但是依赖对象的项目必须在从属于某个 作者:姜江 error 386 节点时不可以改变深度。操作方法是:在 Report Items 面板中选择需要改变深度的项目,右键鼠 标,在弹出的菜单中选择 Raise Level 或者 Lower Level。 在报告中拷贝项目:除了根节点之外,Report Items 面板中其他的项目都可以被复制,操作时, 只需要选择好需要复制的项目,按住 CTRL 键,同时拖动选定的项目到适当的位置。 5.3.2 选择报告中需要包含的模型中的对象 操作方法如下: 1. 在图形模型中选择适当的对象,如图 5-17 所示。 图 5-17 在模型图形中选择报告中要包含的模型的对象 2. 在报告编辑窗口状态下,选择【Report】→【Select Objects】,弹出报告对象选择窗口 Report Objects Selection,如图 5-18 所示。 图 5-18 在报告菜单中选择报告要包含的模型对象 3. 默认情况下所有的对象都被选中,如果要使用图形中选定的对象,点击该窗口中的【Use 作者:姜江 error 387 Graphical Selection】工具 ,如果与此同时按下 CTRL 键,则该选择应用于所有 Tab 页中的 对象。 5.4 生成报告的实例练习 学习了如何创建模型报告以及如何定制模型报告之后,下面通过使用前面的知识结合一个例 子学习如何生成和定制报告,模型为前面章节中创建的 PDM 模型,创建一个 Report,选择需要 生成报告的对象,添加如图 5-19 所示几个项目: 图 5-19 创建报告实例 鼠标右键 Diagrams-图%ITEM%,在弹出的菜单中选择 Edit 编辑节点(Node)的 Title,修 改“图%ITEM%”为“测试文档:图%ITEM%”,也可以点 Insert 插入 PowerDesigner 自带的变量: Date,Time,Application Name,Item,Item Code,Item Name,Model Code,Model Name,Module Name,Parent,Parent Code,Parent Name 等,如图 5-20 所示。 图 5-20 编辑结点的 Title 编辑好节点(Node)的 Title 后,可以点击以上窗口的 Format 属性页,设置该 Title 的格式, 设置好之后点击【确定】按钮,如图 5-21 所示。因为 PowerDesigner 选择中文后默认的翻译和我 们的习惯用法很不匹配,所以同时修改 Table Card 的 Title 为:“表%ITEM%的属性表”;修改 List of table columns 的 Title 为:“表%PARENT%的列清单”。 作者:姜江 error 388 图 5-21 设置 Title 的格式 鼠标右键模型报告中的 Graphics 项,在弹出的菜单中选择 Format,弹出窗口,如图 5-22 所 示。 图 5-22 定义图形的格式 选择 One Page 表示将一个图形强行放在一个页面上,同时选择 Central 表示图形在页面中居 中,选中单选框 As Paragraph 则表示该图形作为一个单独的段落存在。选择 Custom 后,可以在 Zoom 输入框中输入缩放的百分比,这样图形就会以该百分比在多页显示。而 Frame 则表示在图 形和其他内容之间的分割框架,可以规定对齐方式,以及 Frame 的宽度。 鼠标右键点击 Table Card―表%ITEM%的属性表,在 弹出的菜单中选择 Layout,弹出窗口 Card Layout 窗口,可以选择显示哪些列,选择 E 表示 Enable 即显示,如图 5-23 所示。 图 5-23 选择要显示表的内容 鼠标右键点击 List of Table Columns―表%PARENT%的列清单,在弹出的菜单中选择 Layout, 作者:姜江 error 389 弹出窗口 List Layout 窗口,可以选择显示哪些列,选择 E 表示 Enable 即显示,同时,还可以指定 列的显示宽度,可以使用百分比符号%、mm、inch 等方式表示列的宽度,如图 5-24 所示。 图 5-24 选择报告中的列的宽度 报告中的 Card 指对象的属性,其他相关的概念还有 Description(描述)、Annotation(注释), List of object(对象的列表,以表格的形式出现)、Page break(分页),这里就不再赘述,读者可以 根据自己的需要尝试。 此外,还可以对报告进行页面设置,但这种定义仅应用于当前 Section(关于 Section,请参考: 5.5 报告中的 Section(节))。为报告定制页面具体体现在以下两个放面:  在每个报告的 Section 中定义页眉(Header)和页脚(Footer) 选择报告的根节点,选择【Report】→【Header and Footer】,或者用鼠标右键,在弹出 的菜单中选择 Header and Footer,弹出页眉页脚修改窗口,如图 5-25 所示。 图 5-25 定义报告的 Header 和 Footer 根据需要进行修改,并定义格式  为整个报告定义标题页(Title Page) 报告的标题页即生成报告的第一页,定义的方法如下:选择【Report】→【Title Page】, 弹出窗口 Title Page,在图中可以定义作者、生成报告的时间、报告的版本、简要描述信息等, 如图 5-26 所示。 作者:姜江 error 390 图 5-26 定义报告标题页的信息 在 Report 工具栏中点击 生成 RTF 文档,或者 生成 HTML 文档或者通过工具 预览报 告,生成的 HTML 文档如图 5-27 所示。 图 5-27 生成的 HTML 报告 这里将部分生成结果(RTF)摘录,便于读者理解: ========================================== 某某公司信息管理信息通 姜江 2003-12-15 1.0 作者:姜江 error 391 这是一个教学案例 ==================这里会换页================ 1 测试文档:图student_org 第一个图形省略,如果定义为 One Page,也会换页 2 测试文档:图test FK_Student_Class FK_Class_Teacher FK_SUBJECT_REFERENCE_BOOK FK_SUBJECT_REFERENCE_TEACHER FK_BOOK_REFERENCE_COUNTRY 学生 学号 身份证号 班级编号 姓名 性别 电子邮件 手机 电话 住址 年龄 已婚 备注 integer varchar(20) integer varchar(20) smallint varchar(50) char(11) varchar(15) varchar(20) smallint smallint varchar(50) 班级 班级编号 班级名称 班主任 备注 integer varchar(20) integer varchar(50) 教师 教师编号 姓名 性别 电子邮件 手机 电话 住址 备注 integer varchar(20) smallint varchar(50) char(11) varchar(15) varchar(50) varchar(50) 课本 课本编号 国家ID 课本名称 ISBN 备注 价格 出版日期 integer integer varchar(50) char(10) varchar(50) F%16 timestamp 课程 课程编号 课本编号 教师编号 课程名称 备注 integer integer integer varchar(50) varchar(50) 国家 国家ID 国家名称 所属洲 numeric(6) varchar(20) varchar(20) TestTable testTableID numeric(6) 3 表格ACCNT 3.1 表ACCNT的属性表 名称 ACCNT 代码 ACCNT 4 表格教师 4.1 表教师的属性表 名称 教师 代码 Teacher 5 表格课本 5.1 表课本的属性表 名称 课本 代码 Book 6 表格课程 6.1 表课程的属性表 名称 课程 代码 Subject 其他表格省略 7 表格学生组织 7.1 表格学生组织的列清单 作者:姜江 error 392 名称 代码 学生组织 ID studentOrgID 学生组织编码 studentOrgCode 学生组织名称 studentOrgName 备注 Description ========================================== 可以看出,生成的文档为文档的各个部分自动编号,如果不希望自动编号,则选择【Report】 →【Report Properties】或者在 workspace 的报告节点上点击鼠标右键,在弹出的菜单中选择 Properties,弹出窗口,如图 5-28 所示。 图 5-28 报告属性窗口 在 General 属性页上选择 No paragraph numbering 复选框,就可使生成的文档不会自动产生编 号。此外,还可以在该窗口的 HTML Format 属性页中规定生成 HTML 文件的格式,可以指定 CSS (层叠样式表)文件,也可以定义 Header 和 Footer 等属性。如图 5-29 所示。 图 5-29 报告属性窗口“HTML”页中指定格式 如果读者希望修改生成文档中的词汇,前面已经告诉读者修改 Title 的方法了,只需要在对象 上点击鼠标右键,在弹出的菜单中选择 Edit,编辑 Title,输入自己需要的文字,规定适当的格式, 即可满足生成文档格式上的需求。这个例子只是为了向读者说明如何使用报告并且定制,比较简 单,实际项目中的文档可能要复杂很多,希望读者能够根据自己的需要,结合前面介绍的各种报 告的相关知识,多做些尝试,以达到熟练掌握、能够快速高效的生成需要的文档的目的。 另外,要生成比较满意的报告还必须结合修改 Report Resource Language,从上面的例子中我 作者:姜江 error 393 们可以看出,语言如果选择 Chinese,很多翻译的词语不符合我们习惯的命名方式,例如 ForeignKey 就翻译为“外来键”,而不是我们习惯的“外键”,Primary key 没有翻译为“主键”,而翻译为“主 要键”,这可能会使得部分用户对 PowerDesigner 生成文档的可理解性产生了一定程度的怀疑,也 就自然想到希望可以根据自己的需要进行定制,虽然可以使用这部分讲述的方法在报告中修改 Title 等属性的值,但是这种方法毕竟仅仅比较适用于模型中的报告,而且复用性不好,而修改 Report Resource Language 则有利于语言修改可以在多个模型间实现共享。请参考:5.7 使用报告 语言编辑器(Report Language Editor),这部分会结合一个实例讲述如何进一步自定义文档的生成。 5.5 报告中的 Section(节) 一个报告中至少要包含一个 Section(节),节在报告编辑窗口(Report Editor)中显示为 Report Items 面板的底部的一个 Tab 页。如图 5-30 所示。 图 5-30 报告中的节 在报告中使用 Section 可以使得设计者将模型分为不同的部分,从而帮助设计人员方便的分析 模型每个 Section 都包含自己的特定的对象,并且只能属于一个种类(PDM,CDM,OOM,BPM, FEM)。 不论是创建单模型报告或者多模型报告,PowerDesigner 都会默认的创建一个 Section。在单 模型报告中,Section 的类型就是创建报告的模型的类型。在多模型报告中,Section 可能是多种类 型,例如,一个多模型报告可能既包括 PDM 类型的 Section,也可能包括 OOM 类型的 Section, 但前提是这些模型在当前 Workspace 中处于打开状态。 5.5.1 创建 Section(节) 在 PowerDesigner 9.5 中,可以创建、删除、修改或者重命名 Section,可以创建空的 Section, 也可以创建基于模板的 Section,默认情况下 Section 会在生成的报告中自动编号,但是用户可以 在报告属性窗口中修改。 创建报告 Section 的步骤如下: 1. 在 Report Editor 编辑窗口状态下,选择【Report】→【Manage Sections】,弹出 Section 列表窗 口,如图 5-31 所示。 作者:姜江 error 394 图 5-31 报告节的列表窗口 2. 点击空白行或者点击添加工具 或 ,添加一个新行 3. 输入 Section 的 name,如果是单报告模型,则 Mode 列显示为当前模型,不可修改,如果是多 报告模型,则该列显示当前 Workspace 中包含的所有模型,选择适当的模型 4. 如果要使用报告模板,则在 Template 列中选择报告模板,Ap 列表示是否应用模板 5. 如果选择模板为 None,则点击【OK】后,报告编辑窗口中的 Report Items 面板中会增加一个 空白 Section,否则增加一个以模板创建的 Section。 5.5.2 由报告中的 Section(节)创建模板 在报告中创建号的 Section 可以另存为模板,供以后在其他模型中使用该模板创建其他报告。 操作方法是: 1. 点击需要保存的 Section 的 Tab 页,则该 Tab 页显示在 Report Items 面板中,如图 5-32 所示。 图 5-32 选择要保存的 Section 2. 选择【Report】→【Create Template From Section】,弹出报告模板编辑窗口,格式和结构同选 择的 Section 相同,如图 5-33 所示。 图 5-33 由节创建生成的报告模板 作者:姜江 error 395 3. 选择 File—Save,弹出保存文件对话框,输入模板的名称 4. 点击 Save 将文件保存为 RTP 格式的报告模板文件。 5.6 创建多模型 Report 多模型报告(multi-model report)能够通过使用 Section 在同一个报告中包含不同类型模型中 的对象。多模型报告能够通过将不同模型结合起来提供一起全局的综合报告。但是每一个 Section 只能是一种模型类型,并且只能使用一个模板类型,而且模板的类型必须与模型的类型相同,这 些相关的模型也必须在当前 Workspace 中处于打开状态。 创建多模型报告 创建多模型报告时,当前 Workspace 中至少要有一个模型处于打开状态,多模型报告创建后 会自动创建一个 Section,而这个 Section 的类型就是创建时选择的模型的类型。具体的创建方法 如下: 1. 在当前 Workspace 中至少打开一个模型,选择【File】 → 【New】,弹出新建窗口,选择 Multi-Model Report,点击【OK】。 注意:也可以在浏览器(Browser)窗口中鼠标右键点击 Workspace,在弹出的菜单中选择【New】 →【Multi-Model Report】。 2. 弹出新建多模型报告的定义窗口,如图 5-34 所示。 图 5-34 新建多模型报告窗口 3. 输入报告的名称,选择报告的语言,同时在 Model name 下拉框中选择第一个 Section 将要描 述的模型。模型类型的中的内容会自动随着选择的模型而改变 4. 如果需要选择一个报告模板,则通过 Report template 下拉框选择,选择好之后点击【OK】, PowerDesigner 会自动打开该多模型报告编辑窗口,如图 5-35 所示。 图 5-35 多模型报告编辑窗口 作者:姜江 error 396 如果没有选择报告的模板,则该 Section 中内容为空白。 5. 可以选择【File】→【Save】保存该多模型报告,在弹出的保存窗口中选定保存路径,输入文 件名,将多模型报告保存为 MMR 格式的文件。 6. 创建好多模型报告之后,可以为多模型报告添加 Section,可以针对不同的需要加入报告的模 型创建适当的 Section,这部分内容请参考:5.5 报告中的 Section(节)。其他的修改、定制、 生成报告以及打印等操作,都和单模型报告的操作方式相同,请参考本章其他部分内容。 5.7 使用报告语言编辑器(Report Language Editor) 5.7.1 报告编辑器简介 使用 Report Language Editor 可以创建或者修改报告语言的源文件(Resource files)。报告语言 源文件是以 XRL 为后缀名的 XML 格式的文件。其中包含了报告中所有可以打印的文本,并且可 以被任何模型的报告共享使用,从而确保数据一致性,节省用户创建文档的时间。PowerDesigner 在安装目录\Sybase\PowerDesigner 9\Resource Files\Report Languages 目录下面自带了几种不同语 言的报告语言的源文件:Chinese.xrl、Dutch.xrl、English.xrl、French.xrl、German.xrl。不过也许负 责翻译 Chinese 部分的人员不是专业的软件人员,所以如果读者使用 Chinese 生成文档,就会发现 很多术语翻译的非常走样,比如:Primary key 翻译为“主要键”,Foreign key 翻译为“外来键”。 这难免会让人对 PowerDesigner 生成报告能力和可读性产生怀疑,但是不必担心,在这部分,笔 者将向演示如何通过报告语言编辑器(Report Language Editor)随心所域的创建满足自己需要的 文档报告,再次领会 PowerDesigner 的强大功能。 打开报告语言编辑器的方法如下: 1. 选择【Tools】→【Resources】→【Report Languages】,弹出报告语言列表,如图 5-36 所示。 图 5-36 报告语言列表 2. 选择某种语言,点击【Properties】工具 ,或者双击该行,弹出的报告语言编辑窗口,如图 5-37 所示。 作者:姜江 error 397 图 5-37 报告语言属性窗口 如图 5-37 所示,报告语言编辑窗口的左侧的目录树主要包含三个部分,分别是:  Object Attributes:对象属性,包含了所有和对象关联的字符串,例如对象属性的名称、 代码等。主要用于对象属性的翻译。  Report Titles:报告标题,包含了所有报告项目的标题的字符串。  Values Mapping:值映射,包含了在属性值中使用的和关键字相关的字符串,例如: Undefined 和 None,主要用于对象的关键字的翻译。 其中,Object Attributes 和 Report Titles 每个部分分别包含不同模型特定特征的种类 (category),例如:Physical Data Model,以及一个 Common Objects 种类。Values Mapping 部分 则包含两个子类别:  Forms:Cards 和 Checks 中的对象属性的关键字  Lists:List 中的对象属性的关键字 如图 5-38 所示。 图 5-38 查看报告语言映射表格 默认情况下 Form 和 List 下各有一个 Standard 条目,Standard 条目中包含了应用于所有模块的 作者:姜江 error 398 映射表。不论是预览报告还是生成报告,在 Name 列的这些关键字都将被 Value 列中的值替换取 代。可以在这里修改以适应自己的需求,但是如果希望只应用于某个特定部分,则需要为特定模 块定义相应的映射表。 修改报告语言的方法如下:在 Report Language Properties 窗口左侧的目录树中选择需要修改 的条目,在右侧相应的编辑框中修改值,点击【确定】按钮。在报告语言列表窗口中点击【Close】, 弹的确认对话框询问是否保存修改,点击【是(Y)】 确认。如图 5-39 所示。 图 5-39 修改报告语言 5.7.2 实例学习生成数据词典 这部分将结合实际的例子学习如何通过修改 Report Language Resource Files(报告语言源文 件)来满足特定的需要。 模型以在 PDM 部分创建的模型为列,如图 5-40 所示。 FK_Student_Class FK_Class_Teacher FK_SUBJECT_REFERENCE_BOOK FK_SUBJECT_REFERENCE_TEACHER FK_BOOK_REFERENCE_COUNTRY 学生 学号 身份证号 班级编号 姓名 性别 电子邮件 手机 电话 住址 年龄 已婚 备注 integer varchar(20) integer varchar(20) smallint varchar(50) char(11) varchar(15) varchar(20) smallint smallint varchar(50) 班级 班级编号 班级名称 班主任 备注 integer varchar(20) integer varchar(50) 教师 教师编号 姓名 性别 电子邮件 手机 电话 住址 备注 integer varchar(20) smallint varchar(50) char(11) varchar(15) varchar(50) varchar(50) 课本 课本编号 国家ID 课本名称 ISBN 备注 价格 出版日期 integer integer varchar(50) char(10) varchar(50) F%16 timestamp 课程 课程编号 课本编号 教师编号 课程名称 备注 integer integer integer varchar(50) varchar(50) 国家 国家ID 国家名称 所属洲 numeric(6) varchar(20) varchar(20) TestTable testTableID numeric(6) 图 5-40 生成数据字典实例模型 创建如图 5-41 所示的一个报告: 作者:姜江 error 399 图 5-41 创建一个模型报告 通常情况下,做数据库设计都要求有数据字典文档,下表就是一个简单的数据字典的格式: 业务计划表,如错误!未找到引用源。所示。 表 5-4 数据字典实例 Field Type Relation Not null Description Operation_plan_id Smallint PK √ 业务计划 id Time_from Datetime √ 业务起始时间 Time_to Datetime √ 业务结束时间 Prospective_return Money √ 预计回收额 为了在生成的文档中包含数据字典需要的子段,鼠标右键点击“List of Table Columns- 表%PARENT%的专栏清单”,在弹出的菜单中选择需要显示的对象,如图 5-42 所示。 图 5-42 为表的列的列表选择要显示的内容 因为篇幅的原因,这仅仅将生成的文档截取部分分析,目的主要是学习如何解决问题的思路 和方法,如下表: ==================================================================== 表格班级 表班级的专栏清单 名称 代码 数据类型 主 要 的 外 来 键 序列 强 制 班级编号 classID integer TF T 作者:姜江 error 400 R U E A L S E R U E 班级名称 className varchar(20) F A LS E F A L S E T R U E 班主任 teacherInCharge integer F A LS E T R U E F A L S E 备注 Description varchar(50) F A LS E F A L S E F A L S E ==================================================================== 很显然,读者百分之百的会对这份生成的文档不满,存在的问题包括:  词语翻译不符合习惯用法:“外键”译为“外来键”,“主键”译为“主要键”,“列”翻译为“专 栏”  列的比例分布不恰当:很多字符串未在同一行显示  关键字不一定是读者希望看到的:如,读者希望 True 显示为“是”,False 显示为“否”或者 不显示  有些字符串显示的比较多余:表格班级的专栏清单前面可能不需要显示字符串:只需要显示 为“表”即可 针对这些问题,我们打开报告语言编辑窗口(Report Language Editor), 根据存在的问题,打开报告语言编辑窗口,依赖于左测的目录树导航,查找到需要修改的对 象,进行如下修改: 1. 选择 Object Attributes\Physical Data Model\Column\Primary,将值“主要的”修改为“主键” 2. 选择 Object Attributes\Physical Data Model\Column\ForeignKey,将值“外来的键”修改为“外 键”,如图 5-43 所示。 批注 [e28]: 此处格式请不要另外调 整 作者:姜江 error 401 图 5-43 修改翻译不当的模型预言 3. 选择 Report Titles\Physical Data Model\Table\Columns list ,将值“表格%PARENT%的专栏清单” 修改为“表%PARENT%的列清单” 4. 选择 Object Attributes\Physical Data Model\TestDataProfile\Column 将值“专栏”修改为“列” 5. 鼠标右键点击 Report Items 面板中的“List of Table Columns-表%PARENT%的专栏清单”项 目,在弹出的菜单中选择 Edit,将“表%PARENT%的专栏清单”修改为“表%PARENT%的列 清单”, 弹出如图 5-44 所示窗口。 图 5-44 修改项目内容模板 6. 读者在报告语言编辑窗口中查找对象可以依赖于左测的目录树导航,也可以使用查找功能。 例如:如果希望将语言文件的中的所有不正确的(翻译不恰当的)词语一次性替换,可以点 击报告语言编辑窗口中右上方的 Find 工具 或者 Find and Replace 工具 ,进行替换,如 图 5-45 所示。 作者:姜江 error 402 图 5-45 将所有“专栏”替换为“列” 修改以后如果不希望修改改变 PowerDesigner 自带的语言文件,可以点击报告语言编辑窗口 右上角的保存菜单,选择 Save As…将修改后的文件另存为某个文件,如图 5-46 所示。 图 5-46 将报告语言另存为其他文件 在退出报告语言编辑窗口时,弹出确认对话框,点击【否(N)】,不保存对 PowerDesigner 源文件的修改(这样做比较保险)。 这时,再次生成报告,发现变化如下: ==================================================================== 表格班级 表班级的列清单 名称 代码 数据类型 主 键 外 键 序列 强 制 班级编号 classID integer T R U E F A L S E T R U E 班级名称 className varchar(20) F A LS E F A L S E T R U E 班主任 teacherInCharge integer F A LS T R U F A L 作者:姜江 error 403 E E S E 备注 description varchar(50) F A LS E F A L S E F A L S E ==================================================================== 到目前为止,还有两个问题没有解决,一个问题是列的显示宽度的问题,另外一个是关键字 的显示问题(即关键字可以转化为其他的显示方式,例如 False 可否显示为 F 或者)  列的比例分布不恰当:很多字符串未在同一行显示 这个问题比较好解决,可以直接在生成的 Word 文档中调整,也可以采用以下方法:鼠标右 键 Report Items 面板中的“List of Table Columns-表%PARENT%的专栏清单”项目,在弹出的菜 单中选择 LayOut,在弹出的窗口中对各列宽度进行适当的调整,如图 5-47 所示。 图 5-47 定义报告中表格列宽 ==================================================================== 表格班级 表班级的列清单 名称 代码 数据类型 主键 外键 序列 强制 班级编号 classID integer TRUE FALSE TRUE 班级名称 className varchar(20) FALSE FALSE TRUE 班主任 teacherInCha rge integer FALSE TRUE FALSE 备注 description varchar(50) FALSE FALSE FALSE ==================================================================== 最后还有一个问题:关键字不一定是读者希望看到的:例如,读者希望 True 显示为“是”, False 显示为“否”或者不显示。如果需要模型中所有的 True 和 False 都进行转化,该表为 List, 批注 [e29]: 此处格式请不要调整 批注 [e30]: 此处格式请不要调整 作者:姜江 error 404 因此在 Values Mapping\Lists\Standard 映射表中添加 True 和 False 的转化列,如图 5-48 所示。 图 5-48 定义关键字映射表 ==================================================================== 表格班级 表班级的列清单 名称 代码 数据类型 主键 外键 序列 强制 班级编号 classID Integer 是 否 是 班级名称 className varchar(20) 否 否 是 班主任 teacherInCha rge Integer 否 是 否 备注 description varchar(50) 否 否 否 ==================================================================== 如果只希望对模型中一部分关键字进行转化,则可以创建自己的映射表(Mapping table),这 里加设创建一个仅仅转化是否主键关键字的映射表。操作方法如下:在 Lists 上点击鼠标右键,在 弹出的菜单中选择【New】→【Map Item】,创建后修改名称为 PrimaryKey,添加两个值 Name 分 别为“True”和“False”, Value 分别为“是”和“否”,如图 5-49 所示。 作者:姜江 error 405 图 5-49 新建映射表 创建好映射表之后,还必须将映射表和特定的模块或者对象关联起来,这要求在 Forms 或者 List 中创建一个对象属性,在该例中需要为 PDM 中的列的是否主键属性创建相应的对象。操作 步骤如下: 1. 在 Lists 上点击鼠标右键,在弹出的菜单中选择【New】→【Category】,创建后修改名称为 “Physical Data Model”,添加两个值 Name 分别为“True”和“False”, Value 分别为“是” 和“否” 2. 在新建的“Physical Data Model”上点击鼠标右键,在弹出的菜单中选择【New】→【 Map Item】, 创建后修改名称为“Column”,添加两个值 Name 分别为“True”和“False”, Value 分别为 “是”和“ ”(空值),如图 5-50 所示。 图 5-50 新建列的映射表 生成的部分报告如下: ==================================================================== 表格班级 表班级的列清单 名称 代码 数据类型 主键 外键 序列 强制 作者:姜江 error 406 班级编号 classID integer 是 否 是 班级名称 className varchar(20) 否 是 班主任 teacherInCha rge integer 是 否 备注 description varchar(50) 否 否 ==================================================================== 而不是预期中下面的格式: ==================================================================== 表格班级 表班级的列清单 名称 代码 数据类型 主键 外键 序列 强制 班级编号 classID integer 是 是 班级名称 className varchar(20) 是 班主任 teacherInCha rge integer 是 备注 description varchar(50) ==================================================================== 这是因为前面在 Standard映射表中添加了相应的值,因为主键有自己独立的映射表,所以 False 就显示为空,而外键和强制则仍然根据 Standard 中设置的映射关系显示。这表明具体模块或对象 的关键字的转化将覆盖全局的转化关系。 这部分通过实例讲述了如何根据需要定制自己的报告,例如,还可以将“强制”修改为“是 否可为空”,这里提供的仅仅是一种实现目的的方法和手段,实际的应用中不同类型的模型(FEM、 OOM、CDM、PDM 等)的报告类型不同,而且不同使用者的对报告格式和内容的需求也不尽相 同,因此,要熟练应用生成特定需求的文档,还需要不断练习。 5.8 PowerDesigner 10 生成文档的新特性 第一章介绍 PowerDesigner 10 的新特性是曾提到过,PowerDesigner 10 生成文档方面主要有两 个新特性:  可以从报告中移除每个 Item 的 Title(标题),这样可以在生成的报告中把标题去掉  目录的上下文菜单(右键菜单)上的 Hierarchical display 命令可以根据内容的层次在生成的文 档中也可以显示出包的层次结构 下面逐一介绍这两项新特性。 批注 [e31]: 此处格式请不要调整 作者:姜江 error 407 5.8.1 移除 Item 的标题(Title) 在 PowerDesigner 10 中,可以移除每个 Item 的 Title(标题),从而增强预览文档或者生成文 档的可读性。 操作方法如下:  在去除 Title 的 Item 上鼠标右键,在弹出的菜单上使得【Show Title】处于不选中状态  双击 Item,弹出 Item 的编辑窗口(Editor),使【Show Title】前面的复选框处于不选中 状态,点击【OK】确定,如图 5-51 所示。 图 5-51 不显示 Item 的标题 下面举例进一步说明: 参考 5.4 生成报告的实例练习中的例子,以表“班级”为例说明,在移除 Item 和 Title 以前 “班级”的列清单如表 5-5 所示: 表 5-5 移除 Item 的 Title 以前“班级”的列清单 表格班级 表班级的列清单 名称 代码 数据类型 主要的 外来键 顺序 强制 班级编号 classID integer TRUE FALSE TRUE 班级名称 className varchar(20) FALSE FALSE TRUE 班主任 teacherInCharge integer FALSE TRUE FALSE 备注 description varchar(50) FALSE FALSE FALSE 鼠标右键【Table-表格%ITEM%】,在弹出的菜单中去除对 Show Title 的选择,如图 5-52 所 示。再次生成 RTF 或者 HTM 文档,此时,“班级”列清单如表 5-6 所示。 作者:姜江 error 408 图 5-52 通过右键菜单选择不显示表的 Title 表 5-6 表“班级” 表班级的列清单 名称 代码 数据类型 主要的 外来键 顺序 强制 班级编号 classID integer TRUE FALSE TRUE 班级名称 className varchar(20) FALSE FALSE TRUE 班主任 teacherInCharge integer FALSE TRUE FALSE 备注 description varchar(50) FALSE FALSE FALSE 鼠标右键【List of Table Columns-表%PARENT%的列清单】,在弹出的菜单中去除对 Show Title 的选择,如图 5-53 所示。再次生成 RTF 或者 HTM 文档,此时,“班级”列清单如表 5-7 所 示。 图 5-53 通过右键菜单选择不显示列的列表的 Title 表 5-7 新生成的“班级”列的清单 名称 代码 数据类型 主要的 外来键 顺序 强制 班级编号 classID integer TRUE FALSE TRUE 班级名称 className varchar(20) FALSE FALSE TRUE 班主任 teacherInCharge integer FALSE TRUE FALSE 备注 description varchar(50) FALSE FALSE FALSE 读者可以根据此例自行比较去除 Title 后生成文档的不同。 5.8.2 显示包的层次 如果在 Report 中加入了 Package 节点,则可以通过鼠标右键 Package,在弹出的菜单中选择 作者:姜江 error 409 【Hierocratical Display】。举例如下,示例模型如图 5-54 所示。 图 5-54 实例模型 Report 结构如图 5-55 所示(不选中 Hierocratical Display 的情况下),生成文档截取部分如下: ========================================== 3 Package User management 3.1 Details Name User management Code USER Comment 4 Package Package_1 4.1 Details Name Package_1 Code Package_1 Comment 5 Package Physical Data 5.1Details Name Physical Data Code PDM Comment This package contains the extended information on objects from Physical Data Models. 6 Package Package_2 6.1 Details Name Package_2 Code Package_2 Comment ========================================== 作者:姜江 error 410 图 5-55 显示包的层次结构 鼠标右键 Package,在弹出的菜单中使得【Hierocratical Display】处于选中状态,如图 5-55 所示,生成文档截取部分如下所示,读者可明显的观察到,在选择【Hierocratical Display】之后生 成的文档中包含了包的层次结构,这样,就进一步增强了文档的可理解性: ========================================== 3 Package User management 3.1Details Name User management Code USER Comment 3.2 Package Package_1 3.2.1 Details Name Package_1 Code Package_1 Comment 4 Package Physical Data 4.1 Details Name Physical Data Code PDM Comment This package contains the extended information on objects from Physical Data Models. 4.2 Package Package_2 4.2.1 Details Name Package_2 Code Package_2 Comment ========================================== 作者:姜江 error 411 5.8.3 文档美观的改善 PowerDesigner 10 生成的 HTML 格式的报告在美观上也有了一定程度的改善。下面举例说明: 为当前模型新建一个 Report,在弹出的 New Report 窗口中选择生成语言为“English”, Report template(报告模板)为 Standard Physical Report(标准物理报告),生成的报告如图 5-56 所示。 图 5-56 调整好的报告 PowerDesigner 9.5 和 PowerDesigner 10 两个版本下生成的 HTM 文档分别如图 5-57 和图 5-58 所示,显然,Sybase 在 HTML 文档的美观上做了一些工作,在一定程度上提高了软件的友好性。 作者:姜江 error 412 图 5-57 PowerDesigner 9.5 中生成的 HTML 报告 图 5-58 PowerDesigner 10 中生成的 HTML 报告 作者:姜江 error 413 第6章 版本控制系统 Repository 版本控制系统是软件配置管理中非常重要的一个概念,一些主流建模开发工具软件商纷纷在 自己的工具中加入版本控制的功能,例如 IBM 的 Rational Rose 同 Clearcase 的完美整合,并且支 持微软的 VSS(Visual Source Safe)。同时 Visual Studio .Net、 PowerBuilder、RationaRose、Jbuilder、 XmlSpy 等主流工具中也都加入了对 VSS 等版本控制系统的支持;此外,CVS 也获得了 Jbuilder、 Eclipse 以及 Linux 界的大力推崇,取得了广泛的应用。另外一类版本控制系统就是设计和开发工 具自身携带的版本控制功能,例如:Delphi 中的 TeamSource 以及 PowerDesigner 中的 Repository 等等。笔者认为,未来软件的发展趋势必然是:需求管理、分析、设计、开发、配置管理、项目 管理、软件测试、文档生成等在传统方法中分散的一系列工具的整合应用。这一点相信读者也可 以从当前软件的发展趋势当中有所体会。PowerDesigner 中也加入了 Repository(版本控制数据库) 来实现对 PowerDesigner 中文档和模型的版本控制功能,这一章将介绍这部分内容。 本章主要内容如下:  版本控制系统的基本概念,主流的版本控制系统的特点和比较  PowerDesigner 中版本控制系统的基本概念  Repository 的定义,以及文档的 Consolidate(固化)和 Extract(抽取)  Repository 中用户、组以及对 Repository 中文档和模型的管理  Repository 中的 Version(版本)、Configuration(配置)等概念的介绍 6.1 版本控制系统概念 6.1.1 版本控制系统的基本概念 随着软件规模的不断扩大,复杂度的不断增加,70 年代出现了软件危机,正是这软件危机的 出现推动了软件工程思想的迅速发展,使得软件工程的思想深入人心、软件工程的理论体系逐步 完善。 当前,软件的配置管理,作为软件工程中非常重要的一部分, 已经越来越成为软件开发中不 可或缺的一个部分。它是指一套管理软件开发和维护以及其中各种中间产品的方法和规则,配置 管理通过在特定的时间选择软件配置(一组中间软件产品及其描述),系统地控制对配置的修改, 并在整个软件生命周期中维护配置的完整性和可追踪性。 为什么要进行软件配置管理? 随着软件开发规模的不断扩大,软件项目有某个具体的人全部负责已经难以想象而且是极其 不现实的一种做法,项目中涉及到的中间软件产品或者文档的数目随着项目的进行急剧增加,而 对这些中间产品的管理也越来越困难。软件配置管理则是为了解决这些问题而出现的现实有效的 作者:姜江 error 414 技术。 当前的软件项目通常是由一个专门的研发小组负责,项目会涉及到分析、设计、编码、测试、 和维护等多方面的工作。最终交付的软件产品必然是相关成员不断交流的结果,很难想象没有沟 通会产生怎样的软件,这种信息的沟通不仅仅是在研发小组的成员之间及各个研发小组之间,还 存在于客户和研发者之间。 所有的这些交流反馈意见信息都有可能导致对文档、设计或者软件的修改,小的可能只是对 某个源文件中的某个变量的定义改动,大到重新设计程序模块甚至可能是整个需求分析变动。由 于软件开发所固有的特征,可能会形成众多的版本(设计、文档和软件本身等),但是我们不能 保证不出现错误的修改。 例如,可能出现的情况如下: 1. 客户不满意当前界面设计,软件开发人员修改之后,客户又觉得还是以前的界面风格比较适 合,如果没有及时的数据备份,就会出现一些曾经让很多程序员沮丧的情况:“Design & Coding again!”,经常担心操作失误造成代码丢失; 2. 即使研发人员经常备份数据也会因为命名和存放等困难(例如:很多程序员都曾经以“程序 名称—2004 年 2 月 25 日”这样的方式进行备份,经常在自己的硬盘上存有无数个各种日期和 名称的版本),而造成不同版本管理的困难,容易造成混乱。 3. 甲乙两位程序员共同负责某个模块的开发,甲对某段程序修改之后,由于种种原因未能及时 通知乙,而这段程序的修改又造成了乙在程序调试时可能会遇到一些莫名其妙的问题,这就 对软件开发的效率造成了负面影响,传统的操作方式不利于文件交换和更新。 4. „„ 归根结底,这些情况都是没有对软件中间产品的有效地管理和同步机制,这种困难局面非常 现实地摆在项目开发管理者的面前。 具体可能表现为以下几点: 1. 如何以集成统一为基础、分布式开发为主线的方式对项目产品进行综合管理控制; 2. 项目研发人员之间如何以一种有效的机制进行协调; 3. 如果有效地记录对中间产品的修改,使产品管理更具有科学性,而不是随机的、混乱的; 4. 项目进行过程中形成的文档、模型、软件产品的各个版本如何进行标识,管理及差异识辨等 等,代码如何保持同步; 5. 如何快捷方便地追朔到产品不同部分的不同的阶段性成果,并且具有良好的可恢复性; 6. „„ 以往的那种被誉为具有良好编程风格的做法,诸如在对他人的源程序进行修改时注释修改原 因,修改人和日期,如果是多个成员同时进行了修改,那么需要进行及时的人工的差异比较和综 合以便形成一个统一的新版本。这种做法在当前的大型软件的开发中已经越来越没有空间了,可 以说是一种以小作坊的形式来面对软件的社会化大生产,再也不可能行得通了。 版本控制,作为软件配置管理中至关重要的一个部分,则为这些需求提供了解决方案。事实 作者:姜江 error 415 上,软件版本管理的思想就已经产生,只是当前软件开发所处的阶段使得对这种管理思想的需求 表现的更迫切一些。 确切的说,软件配置管理,或者说其中的版本控制是一种管理思想的体现,而不仅仅是技术 实现。很多开发人员在刚开始使用版本控制系统的时,会把它理解为公司的一种任务,理解为管 理层的“官僚作风”,而不是看作开发过程中如同 IDE 一样必不可少的工具了,于是往往把自己 放在版本控制系统的对立面上。因此,对于项目负责人或者配置管理的实施人员而言,重要的是 要让研发人员明白版本控制能够为他们解决哪些问题,带来哪些好处,而不是以 Top-Down 的方 式强制执行。而有些高层管理者,也可能因为对实际的软件开发开发过程不熟悉,可能会怀疑配 置管理的作用,担心在配置管理和版本控制方面的投资是否能够带来相应的收益。 实施策略 作为配置管理或者版本控制系统的实施者,可以采取的策略有:  向管理层递交实施配置管理分析报告,尽可能涉及到投资收益分析,引起他们的注意, 获得管理层的支持;  争取相应的时间对研发人员进行统一培训,便于交流沟通和信息反馈;  书写必要的操作手册和支持文档,排除版本控制的实施过程中可能会遇到的障碍,同时 把这些标准的文档提交管理层,使管理层可随时了解相关技术,为决策提供支持  在介绍配置管理和使用配置管理工具的时候,清楚明了,并且强调这是部门的要求,需 要所有人员参与配合。大家都可以在实施配置管理过程中得到相应的关于软件过程管理 的知识,体现程序员的基本素质,适应软件组织发展的要求;  对实施过程中可能会遇到的困难有足够的思想准备,热心解答研发人员使用系统时遇到 的问题,并在适当的时候将实施情况反馈给研发人员,同时向管理层报告。 6.1.2 主流版本控制系统介绍和比较 为了使读者在学习 PowerDesigner 自带的版本控制系统之前能够对当前市场上主流的配置管 理/版本控制系统有一个简单的了解,笔者根据自己的经验做了简单比较,希望能够为读者提供 一些参考,如表 6-1 所示。 表 6-1 常用版本控制系统比较 系统名 称 易用性 安全性 是否支 持公网 操作 功能特性 对研发工具的 支持 价格 CVS 难度适中,通常使用 明令行操作,有 Win CVS 客户端的支持 Client/Server 型的版本控 制系统,可以 是 功 能 基 本完 备,对软件并 发 控 制 和版 支持 Jbuilder、 Eclipse 等工 具,并获得 开放 源代 码软 作者:姜江 error 416 后易用性有明显提 高 使用 Window 用户,多级权 限控制,安全 性较好 本 冲 突 支持 较好, Linux界的大力 推崇 件,完 全免 费 Rational Clear Case 配置非常复杂,必须 安装在主域服务器 上,但安装调试非常 困难。 没有自己的 用户管理系 统,它的用户 管理是通过 域用户的管 理来实现的, 借助于 Windows 服 务器安全控 制,具有较高 的安全性 是 功能非常强 大 , 有 Rational Unified Process 强大 的 理 论 体系 支持,涉及到 配 置 管 理的 几 乎 所 有方 面 同 Rational Rose 结合非常 紧密 价格 昂贵 Visual Source Safe 属于文件型版本控 制系统,比较简单, 容易上手 很低,因为使 用网上邻居 文件共享的 方式,用户必 须对文件有 写权限,容易 出现误删除、 或者恶意破 坏等情况 否 较弱,不支持 并发控制,不 支持 Branch, 只 适 合 小型 团队应用,只 提 供 了 项 目 ( 对 应 于 目 录)的用户权 限控制,不能 针 对 每 个 文 件 来 设 置 不 同 的 访 问 权 限 支持 Visual Studio .Net 、 PowerBuilder、 RationaRose 、 Jbuilder 、 XmlSpy 等主流 开发工具 价格 较低 6.2 Repository 的基本概念 6.2.1 基本概念/简介 Repository 是 PowerDesigner 中自带的充当版本控制系统的一部分,它是客户机/服务器的架 构,通过使用 Repository,团队内设计人员可以实现信息共享,保证数据完整性,对 Repository 作者:姜江 error 417 中内容的访问也有相应的权限控制。 Repository 中的文档可以是模型,多模型报告,也可以是 Microsoft Word 文件,甚至是图片等。 Repository 建议有以下几种不同的角色:  数据库管理员:  创建 Repository 用户,并定义他们的权限;  创建 Repository 组,并定义他们的权限;  数据管理员:  使用目录组织 Repository 浏览器;  设定用户或者组对这些目录和文件的访问许可(Permission);  团队领导:  锁定文档或者对文档分配许可;  管理 Repository 中文档的版本,管理分支和配置;  用户:  抽取(Extract)和固化(Consolidate)文档;  在已经固化的文档中查找对象; 这类用户在 Repository 版本控制系统的实施过程中充当着不同的角色,如图 6-1 的活动图向 展示了一个大致的实施过程,用户在实际操作的时候可以按这种思路进行实施。 图 6-1 使用 Repository 的实施步骤 PowerDesigner 中的 Repository 是客户机/服务体系结构的。服务器端通常会用一个关系型数 批注 [e32]: 该图形已翻译 作者:姜江 error 418 据库管理系统(RDBMS)主要存储 Repository 表,用以收集 Repository 的信息。客户端则可以通 过 ODBC 访问服务器端的 Repository 数据库,可以将文档存储至 Repository 中(Consolidate),也 可以从 Repository 中获得文档(Extract)。如图 6-2 所示。 图 6-2 PowerDesigner 与模型仓库之间的关系 安装服务器和客户端的基本步骤参考图 6-3。 图 6-3 服务器端和客户端配置过程 6.2.2 Repository 的定义/创建和连接 在连接数据库之前,用户必须为数据仓库(Repository)(即用于存储版本控制系统数据的数 据库,所有的版本信息都存储在该数据库中)创建一个定义。数据仓库定义就是在本地计算机为 批注 [e33]: 此图已翻译 批注 [e34]: 此图已翻译 作者:姜江 error 419 数据仓库设置一些参数,例如数据仓库的名字(Repository Name)、注册(Login)、密码(Password)、 数据库数据源的名字(Database Data Source Name)以及用户名(User Name)和密码。用户可以 为一个数据库创建一个或多个定义。 在这里主要以 SQLServer 数据库为主来说明对数据仓库的操作。 创建版本控制系统的 Repository 之前,需要先创建一个 ODBC 数据源,本章以 SQL Server 为 例,创建 ODBC 数据源的步骤这里就不作介绍,读者可以参考相关书籍。 在数据源创建成功以后,接下来的任务就是为 Repository 来定义一个连接到 ODBC 的连接, 在 PowerDesigner 环境中,选择【Repository】→【Repository Definitions】弹出如图 6-4 所示对话 框。 图 6-4 Repository 定义列表 鼠标点击空白行,新建一个 Repository 的定义,输入定义的名称、用户,在 Data Source Name 处点击 工具,弹出如图 6-5 所示的 ODBC 选择窗口: 图 6-5 选择 ODBC 数据源 选择恰当的数据源,点击【OK】确定。在 Repository 定义窗口中,双击该行行首箭头或者选 中该行后点击【Properties】工具 ,弹出如图 6-6 所示窗口。 作者:姜江 error 420 图 6-6 “Define Repository”窗口 在上图所示窗口中输入 Repository 的名称,登录名以及 ODBC 数据源的登录用户名和密码, 点击【Test】按钮测试数据源连接情况。测试完成后点击【确定】按钮。 连接 Repository 选择【Repository】→【Connect】,弹出 Connect 窗口,如图 6-7 所示。 图 6-7 连接 Repository 数据源 如图 6-7 所示,在 Repository 下拉列表中选择需要连接的 Repository,输入登录用户和密码, 以及数据源用户名密码,点击【OK】。弹出如图 6-8 所示错误窗口。 图 6-8 连接错误窗口 点击【确定】按钮,弹出如图 6-9 所示窗口。 作者:姜江 error 421 图 6-9 安装 Repository 确认对话框 上图窗口询问是否确认在该数据库上安装 Repository,即 Repository 系统表的定义,点击【是 (Y)】 确定,弹出如图 6-10 所示窗口。 图 6-10 Repository 安装脚本 如图 6-10 所示,编辑框中所示为在数据库中创建 Repository 系统表的 SQL 脚本,点击 【Execute】按钮,由于该过程需要执行大量的 SQL 脚本,因此可能需要执行较长的时间,随不同 机器的配置而不同。创建完成之后弹出如图 6-11 所示窗口,告诉读者 Repository 已经创建成功, 并且以用户 ADMIN 登录,密码为空: 图 6-11 安装完成提示窗口 点击【确定】按钮,这时在 PowerDesigner 的环境中会出现如图 6-12 所示的窗口。 图 6-12 Repository 环境 到此对于 PowerDesigner 中 Repository 和 SQLServer 的连接的操作已完成。 6.3 管理 Repository 用户 在数据仓库连接成功以后,系统就会生成一个默认的 Administrator 用户,即管理员用户,登 作者:姜江 error 422 录名为 ADMIN,密码为空。该用户能在数据仓库中定义用户和用户组,具有所有的权限。所谓 权限就指用户所具有的对数据仓库中文档管理的能力。下面我们就创建几个用户和用户组并分别 赋予一定的权限。(在没有连接数据仓库以前这些菜单都是不可用的) 6.3.1 创建管理用户/定义用户权限 1. 选择【Repository】→【Users】,弹出用户列表窗口,如图 6-13 所示。 图 6-13 Repository 用户列表窗口 2. 可以点击空白行,或者鼠标点击【Add a Row】工具 来添加新用户,在 Full Name 处输入 为 User_1,可以通过点击【Delete】工具 来删除所选用户。当输入用户名称时,就会发现 Full Name 与 Login Name 的内容在同时改变,当然如果用户不喜欢用默认的 Login Name 也可 以改变它。这里参数的具体含义请参考表 6-2。 表 6-2 Repository 用户参数 参数 内容 Full Name 数据仓库用户的名称 Login Name 在数据仓库中定义的名称,即注册 Comment 用户的一些其它信息 在 PowerDesigner 中大部分话框的选项都是动态的,上表所示的对话框所显示的参数用户可 以通过【Customize Columns and Filter】工具 按钮来改变,点击该按钮弹出窗口,如图 6-14 所示。 作者:姜江 error 423 图 6-14 定义要在列表上显示的列 选择需要显示的内容,点击【OK】确定。在用户列表窗口中,点击【Apply】按钮应用。 3. 双击该行行首箭头,弹出 User Properties 窗口(或选择该行,点击【Properties】工具 )。 如图 6-15 所示。 图 6-15 “User Properties”窗口 如图 6-15 所示,在 General 页中还可以为 User_1 修改一些参数,如 Password、 Email 等。 注意:在 Full name 及 Login name 后面的“=”是为它们之间的变化关系而定的,按钮凹进 去它们一起变化,否则相反。左下方 是选择该对话框页的显示情况。 在该窗口中选择 Rights 属性页,可以为 User_1 赋予它应有的权限如图 6-16 所示,在该页中 列出了所有的权限,默认情况下定义一个用户它只有 Connect 的权限,除此之外它没有任何权限, 属于 Public 组,需要 Administrator 为它赋予权限,当然默认情况下 ADMIN 用户具有所有的权限。 作者:姜江 error 424 图 6-16 在“Rights”页中为用户定义权限 此外,在 Groups 属性页中可以定义该用户所属的组(在下节中将讲到组)。属性页 Version Info 也中显示的是该用户的一些版本信息(在后续章节中将陆续讲到)。 4. 定义完参数后点击【OK】按钮返回用户列表窗口。至此我们就完成了一个用户的定义过程。 在这里我们以建立一个用户名为 User_1 的用户为例来说明创建一个用户的全过程。读者可以 按照下表进行练习,如表 6-3 所示。 表 6-3 创建用户实例 用户名 权限 User_1 Connect /Freeze Versions User_2 Connect/Lock Versions User_3 Connect/Mange Branches User_4 Connect/ Mange Configurations User_5 Connect/ Mange All Documents User_6 Connect/ Mange Users User_7 Connect/ Mange Repository 在本小节中我们学习了用户的创建以及用户权限的赋予,在下节中我们将学习用户组的创建 即其权限的赋予。 6.3.2 创建管理用户组/定义用户组权限 组是一些有共同权限的用户的集合,它是 Repository 为了方便用户的管理而创建的一个模块, 在数据仓库中组是有层次的,一个定义好的用户组可以有其自己的 Parent-Groups(父组)和 Sub- Groups(子组)。 关于用户组的一些操作和用户很相似,在这里我们以创建 MyGroups 为例来演示用户组的创 建过程。 首先从 Repository 中选择 Groups 进入 List of Groups 窗口,如图 6-17 所示。 作者:姜江 error 425 图 6-17 组的列表窗口 如图 6-17 所示,在连接数据仓库后系统自动生成两个用户组:  组 Administrator的 Code为 ADMN 默认情况下它具有 Freeze Versions/Lock Versions/Manage Branches/Manage Configurations/Manage All Documents 权限。默认情况下它只包含 ADMIN 用户。  组 All users 的 Code 为 PUBLIC 这个组没有定义任权限,一些新定义的用户默认属于该组。 点击列表中空白行或者点击【Add a Row】工具 添加一个用户组,将其命名为 MyGroups, (操作基本上和创建用户相同)也可以通过点击 选中该行,然后点击【Properties】工具 ,按出 Group Properties 窗口,如图 6-18 所示。 图 6-18 “Group Properties”窗口的“Members”页 和用户属性窗口不同的是该列表框多了两个属性页,即 Members 和 Parent Groups,后面将陆 续介绍相关概念。 进入 Rights 属性页,给该组赋予一定的权限:Connect/Freeze Versions。 注意:当创建好一个用户组后必须为它赋予一些权限,以便让组中的用户能够继承它的权限, 否则它下面的用户将没有任何访问权限。 到此一个用户组已经创建完了,读者可以按照下表进行练习,如表 6-4 所示。 作者:姜江 error 426 表 6-4 创建组实例 用户组 权限 MyGroups Connect /Freeze Versions Groups_1 Connect/Lock Versions Groups_2 Connect/Mange Branches Groups_3 Connect/ Mange Configurations Groups_4 Connect/ Mange All Documents Groups_5 Connect/ Mange Users Groups_6 Connect/ Mange Repository 6.3.3 管理用户和组及组与组之间的关系 A.用户和组之间的关系 可以向一个组中插入用户,在用户属性窗口的中点击 Groups 属性页面,弹出如图 6-19 所示 选择窗口。 图 6-19 为用户选择组 注意:所用用户组都隶属于 All users 组,也就是说该组包含所用的用户。而 ADMIN 默认情 况下它只隶属于 All Users 和 Administrators。 如图 6-19 所示,中 表示使全部选中, 表示全部不选, 表示的所选项的排序。 这里为 User_1 选择 MyGroups 组,点击【OK】按钮完成用户与组之间的操作。 同上操作一样为其他用户选择用户组,读者自己可以自行练习。 除此之外用户还可以在这里为自己的用户组添加用户,例如我们将上面给的操作反向进行, 选择【Repository】→【 Groups】,弹出组列表窗口,选择 MyGroups 组,点击【Properties】工具 , 在组属性窗口中选择 Members 属性页,点击 图标,在出现的 Selection 对话框中选择 Users 页 作者:姜江 error 427 框,此时页框中显示了你定义的所有用户,从中选择要为该用户组添加的用户即可。在此我们选 择用户 User_1,如图 6-20 所示。 图 6-20 为组添加用户 B.组与组之间的关系 PowerDesigner 中组是可以有层次的,也就是说它可以有子组也可以有父组。这里我们以 MyGroups 组为例来为它分别定义一个父组和一个子组。在组的属性窗口中进入 Parent Groups 属 性页,点击【Add Groups】工具 ,弹出如图 6-21 所示选择窗口: 图 6-21 定义组的层次关系(父组) 在该窗口中选择要被定义为父组的组,点击【OK】确定。 此外,还可以为组定义子组,操作的方法如下:假设为组 Administrator 定义子组,在 Administrator 组属性窗口中进入 Members 属性页,在该属性页上点击【Add 工具】,弹出选 择成员窗口,该窗口中包含连个属性页,即 Users 和 Groups,在 Groups 属性页中可以为该组定义 子组,在这里我们选 Group_1 作为它的子组。如图 6-22 所示。 作者:姜江 error 428 图 6-22 定义组的层次关系(父组) 到此用户与组、组与组之间的关系以介绍完了,下面我们再来讨论一下他们之间的权限是如 何继承的。 当向一个用户组中插入一个用户时,如果该用户没有被赋予任何权限,而该用户组也没有被 赋予任何权限时,当该用户连接数据仓库时,他将看不到任何文件;而如果该用户被赋予一些权 限,即使该用户组没有被赋予任何权限,该用户也能继续行使它本身被赋予的权限,而当该用户 组被赋予权限时,该用户除了继承该用户组的权限外还保留其自身的权限,但它自带的权限在用 户组中是不能被显示的。对于用户组的权限,不论是 Parent Groups 还是 Sub Groups 都又其类似的 情况。 在定义了用户及用户组后,团队中的成员就可以通过各自的权限对数据仓库中的文档进行管 理了,下面继续学习对数据仓库中的文档管理。 6.4 将文档固化(Consolidate)至 Repository 中 要通过 PowerDesigner 对模型和文档进行有效的版本控制,就必须先将相关的模型和文档固 化(Consolidate)到 Repository 中,这和 CVS(Concurrent Version System)中的 Commit(提交) 的概念比较类似。本节将对固化的操作进行讲解。 创建一个物理数据模型 Project Management,如图 6-23 所示。并且分别将该模型转化为概念 数据模型和面向对象模型,转化的方法请参考:3.13 PDM 模型的转化/比较/合并。 图 6-23 模型实例 作者:姜江 error 429 6.4.1 以不同方式将文档合并(Consolidate)至 Repository 中 固化文档有三种方法,一是从数据仓库的 Repository 的下拉菜单中选择 Consolidate,一种是 在 Local 中的工作空间右击在下拉菜单中选择 Consolidate,以上两种方法都可以对多文档进行固 化。都会出现如图 6-24 所示的对话框。所不同的是,第一种方法需要选择固化的文档;而第二种 方法则把该工作空间中所有文档都列在该对话框中了。如图 6-24 所示。 图 6-24 固化多文档窗口 其中,各个工具按钮的含义如下:  Add Document 工具 ,弹出 Consolidate Document 窗口  Add Modified Documents in Workspace 工具 ,添加 Workspace 中的所有修改过的文档,  Consolidation Options 工具 ,对固化模型的参数进行设置  Add all Documents in Workspace 工具 ,添加工作空间中的所有文档 第三种方法是鼠标右击需要固化的文档,在弹出的菜单中选择 Consolidate,如图 6-25 所示。 图 6-25 “Consolidate Document”窗口 作者:姜江 error 430 在上图窗口中可以选择对 Workspace 中模型固化也可以选择 File 单选框,然后在 Name 处 Select a File 工具 ,在弹出的菜单中选择需要固化到 Repository 中的文件。 该窗口中的一些参数的含义如错误!未找到引用源。所示。 表 6-5 “Consolidate Document”窗口部分参数 参数 属性 Extract after consolidation 固化后抽取 Extract dependencies 创建一个新文档 New 以一个新模型的方式出现 Update 更新当前版本中的文档 Branch 在当前版本中允许创建第一个新版本 Integrate 允许和另一个分支中的文档结合 Freeze current versions create a new version 冻结当前版本创建一个新版本 Freeze after consolidation 表示固化后冻结 Unlock after consolidation 表示固化后解锁 当点击 时会弹出选择框,它与 Consolidate 窗口中的工具 作用相同,如图 6-26 所示。 图 6-26 选择固化选项  Interactive:表示是以交互式的形式固化文档  Batch: 比实施以批处理的方式固化文档,只有选择此选项时,下面的一些选项才可以选.在这 里是为了在固化时一些冲突的选取而设置的参数。 Resolve conflicts  Use my changes:固化时文档以 Local 中的为主  Keep repository changes:固化时如固有异同,保持数据仓库中的文档不变  Resolve manually:它的选择是为了出现固化冲突时会自动出现表较对话框 当所有的参数设置好以后点击【OK】按钮,此时该文件就被固化到数据仓库中了,如图 6-27 所示。 作者:姜江 error 431 图 6-27 固化到 Repository 中的文档 到此我们已经将一个文件从 Local 中固化到了 Repository 中。 6.4.2 固化时产生的冲突(Conflict) 固化模型时,如果本地文件和 Repository 库中的文件不同,则会出现一些冲突,此时则会弹 出模型合并窗口,左右两方显示模型之间的对比(例如我们把 Project Management (CDM)*中 的 Entities 的 Customer 中的 Attributes 的最后一个属性删除),如图 6-28 所示。 图 6-28 固化冲突的模型比较窗口 这里关于模型合并窗口的各种符号的含义,请参考:3.8.3 比较、同步模型和数据库、通过模 型修改数据库。 其他一些符号的含义如表 6-6 所示。 表 6-6 模型合并窗口部分符号含义 符号 含义 符号 含义 作者:姜江 error 432 [=] 完全相同 <- 从…….移动 [+-] 增加的 -> 移动到……. [-+] 删除的 [#<-] 从……修改并移动 [#] 修改的 [->#] 修改并移动到…. [!] 子修改 [„?] 冲突 6.4.3 固化时可能出现的问题 很多用户在使用 PowerDesigner 的 Repository 功能时,都遇到过这样一个问题,选择物理数据 模型或者概念数据模型固化,如果数据库选择 Oracle 或者 Microsoft SQL Server 时,固化无法进 行,以 SQL Server 2000 会弹出类似如图 6-29 所示警告窗口。 图 6-29 固化 PDM 模型到 SQL Server 2000 时的错误信息 以下为一些网友的问题 ========================================== myseagate:我在 PowerDesigner 中使用 repository 的 consolidate 时,出现一个了错误。 [Oracle] [ODBC][Ora]ORA-01401:插入的值对于列过大 SQL STATE=S1000。” ODBC 是用的 oracle 9.0.1,pd 的版本是 9.0 评估版(破解后的无时间限制),我也在头疼这个问题。 ========================================== lizhm:当我想把 PDM 文件 consolidate 到 REPOSITORY 时,返回错误信息字符被截掉。我分别 试了 ORACLE,SQL SERVER 2000 作为后端数据库,均是如此。 但在采用 ACCESS 进行数据存放时, 成功了。 只对 MS ACCESS、SQL ANYWHERE 和 SYBASE SQL SERVER 支持的比较好,对其他的数据 库可就有问题,不过 REPOSITORY 和目标数据库可以使用不同的 DBMS,所以并没有很大的影响。 ========================================== 笔者在使用的时候也遇到过这个问题,并且一直没有能够有较好的解决方案,只是在 PowerDesigner 9.0 中使用 SQL Server 2000 时可以正确固化,但也不是每次都能够成功。 网友 lizhm 提到,如果使用 MS ACCESS 即可顺利执行,但是笔者曾经尝试 PowerDesigner 9.5+Microsoft Access 2003,也未能顺利通过,弹出如图 6-30 所示窗口。 图 6-30 固化 PDM 模型到 Microsoft Access 2003 时的错误信息 作者:姜江 error 433 为了确认 PowerDesigner 的这个 Bug,笔者曾经和 Sybase 的技术支持人员取得联系,可惜也 没有得到准确的解决方案,只是说好像有个补丁可以解决该问题,但是没有备案。 值得注意的是,固化 PDM、CDM、OOM 才会出现这种问题,如果固化的模型是业务流程模 型(BPM),则在任何一个版本中都可以顺利进行。 6.5 管理 Repository 中的文档 在这一节中我们将来学习一些关于 Repository 文档的简单管理操作。这是为以后学习文件的 提取和固化以及不同文件版本的控制作铺垫的。 6.5.1 浏览 Repository 中对象的内容 在 Repository 中为了方便对用户的管理 PowerDesigner 中使用了浏览器,在这里用户可以很方 便的对文档进行管理,能通过浏览器组织和管理用户对文档的创建和删除操作;还可以通过浏览 器显示固化(存储)的模型的内容;显示固化文档和对象的版本号;搜寻用户所要查找的文件; 打开固化后只读文件的特性对话框;提取和设计固化后的文件的版本;审核数据仓库的活动者以 及比较本底模型和数据仓库中的模型、数据仓库内部的模型。可以通过鼠标右键来操作,如图 6-31 所示。 图 6-31 鼠标右键操作 Repository 6.5.2 在 Repository 中使用目录 在 Repository 的目录中大体上包含的文件如表 6-7 所示。 表 6-7 Repository 目录包含文件类型 作者:姜江 error 434 节点 描述 Root 当一个连接已经开始时,它显示所定义各数据仓库的名字,用户的注册 以及当前的分支 Folder 文件夹只不过是个容器,用于管理当前数据仓库里的子文件夹和文件 Document 包括 Repository 中的模型文件、多模型报告以及外部的文件、图形 Package Repository 中自带的一个文件 Object category Repository 中对象的分类 OOM 等 Diagram Repository 中的一些图,例如时序图,类图等 Object Repository 中的一些对象如 CDM 等 可以对 Repository 在浏览中显示的内容进行设置,选择【Tools】→【General Options】,弹出 General Options 窗口,如图 6-32 所示。 图 6-32 在“General Options”窗口中设置 Repository 显示的内容 在该对话框中左边选中 Repository,在右边显示一些关于相应的选项,可以在此通过对复选 框的选中与否来定义在浏览器中的显示情况:  Auto-Connect 选项的对选中与否来决定在启动 PowerDesigner 时是否自动连接  Auto-Refresh 选项的选中与否,来设定文件是否自动更新,以及还可以通过 Refresh Every 选项来定义文件的刷新频率。 其他的选项用户可以自己学习,这里就不再赘述。 6.5.3 文档对象的属性(包括版本属性) 打开固化到数据仓库中的文档时,就会发现无论打开哪个类型的窗口,在该窗口中总会有一 些页面是呈灰色的,也就是说是不能被更改的。此外,当用户把文件固化到数据仓库中,一些文 件将不能被看见,这一节中我们将逐步介绍这些相关的内容。 作者:姜江 error 435 为了说明文档对象的属性,我们选择软件自带的一个例子来做一些简单的说明。双击 Project Management(PDM)图标打开它的属性框如图 6-33 所示,发现除了 Permissions 页和 Versions 属 性页以外,其他的属性页中的内容都是灰色的,这表示都不能被修改,只是显示了关于该文件的 一些信息。 图 6-33 Repository 中 PDM 模型的属性窗口 进入 Permissions 属性页,如图 6-34 所示。 图 6-34 查看 Permission 页 第一次对该数据仓库(Repository)进行操作时,并且没有为该数据库创建任何用户,也就是 说是对该文件初始的操作,它会被系统默认的定义为 ADMIN 和 All Users 两个用户访问。该窗口 中部分图标含义如下:  Show All Authorized Users ,显示所有被授权的用户  Copy Permissions to All Children ,将该用户所有的权限都拷贝给它的子类,即继承。 可以点击【Add】工具 ,在弹出的窗口中选择可以访问该对象的用户,如图 6-35 所示。 作者:姜江 error 436 图 6-35 增加可以访问该对象的用户 进入 Versions 属性页,如果发现它的显示框中有一个 ,则表示该文件已被固化,关于版本 的含义及其操作,请参考:6.8.1 管理文档的版本(Version)。 6.5.4 针对 Repository 中对象定义访问权限 用户可以在数据仓库中为所选择的对象定义访问权限。在上图所示的对话框中选择 Permissions 属性页,在该页中显示了所有可以访问该文件的用户和用户组,在此可以为该文件选 择可以访问它的用户,在此我们以 User_1 为例来操作。如图 6-36 所示。 图 6-36 “Repository Model Properties”窗口的“Permission”页 在此可以选择 User_1,点击【Properties】工具 或选定该行,双击该行行首的箭头进入用 户的修改窗口,如图 6-37 所示。 图 6-37 为用户选择权限 点击【Granted Permission】的下拉列表框选择该用户对该文件的访问权限。如图 6-37 所示。 作者:姜江 error 437 6.5.5 Repository 中文档的临时性保护 数据仓库的一个好处就是它可以对它里面的文档进行临时性的保护,当用户固化、冻结、锁 定或删除数据仓库中的一个文件时,数据仓库会自动的为这些文件提供一个完整的临时保护,也 可以认为临时保护是一个虚拟锁。它可以防止非法用户对文件的访问。 但是用户不能同时把同一个版本的文件固化到两个分支(Branch)中去;当用户是某一个团 队中的开发者时,它不能锁定另一个团队的成员正在使用的文件;它也不能冻结令一个团队队员 锁定的文件。但是,当前的工作被完成之后,对文件的临时保护权限就会被释放掉。 当用户在没有固化完一个文件时就断开了数据仓库的连接,虽然说此时用户已经和数据仓库 断开了连接,但是临时保护仍然被加载在没有被固化完的文件上,如果其他用户想该文件,他必 须向管理员用户要一个权限。当用户想修改一个文件时,如果该文件被另一个用户使用着,此时 用户必须等该用户使用完之后才能对该文件进行修改。否则该行为将被禁止。 如果不小心 PowerDesigner 软件出了问题或是 Repository 正在自行固化、冻结、锁定或删除的 事件时突然之间断开了,这是数据仓库的临时保护仍然被加载在那些文件里。如果下次想以非法 的用户访问时,系统会出现一个提示框来警告用户。如果用户想强制获取文件,用户获取的文件 已被毁坏。 6.5.6 比较 Repository 中的不同版本的模型 在数据仓库中可以对不同版本的模型进行比较,选择【Repository】→【compare】或在数据 仓库中右击需要比较的模型,在出现的对话框中进行参数的设置。在此可以从下拉列表中选择 Workspace 或 Repository 中的模型,还可以通过点击 图来查看所选模型的信息。如图 6-38 所 示。 图 6-38 比较不同版本的模型 可以在 Model1 和 Model2 中选择需要比较的文件或者模型,在 Version 处选择需要比较的文 件的不同的版本,定义好参数后点击【OK】确定。 进入比较窗口,如果在上一步的 Location 参数定义的不同,那么在比较窗口中模型的显示位 作者:姜江 error 438 置将不同。当用户在左边(或右边)选择选项时右边(或左边)会随之发生变化,在下面的显示 框中显示了它们的一些信息。如图 6-39 所示。 图 6-39 模型比较窗口 在该对话框中图标 的意思是比较选项的选择,点击此图标时将会弹出如图 6-40 所示的选择 框。在这用户设置比较的参数。 图 6-40 比较选项窗口 在这里用户还可以定义一些模型的显示情况。 当点击 图标时会出现如图 6-41 所示的文本框,此文本框显示的是一些比较信息的预览。 单点击上面的图标,可以打印该文本框的信息,也可以保存该信息。 作者:姜江 error 439 图 6-41 文本比较信息 6.6 从 Repository 中抽取(Extract)文档 如果想对固化到数据仓库中的文档或模型进行修改,则必须将文件从数据仓库中抽取出来, 即在本地机器上有相应的文档或模型,本节中将主要介绍抽取(Extract)的方法,以及抽取过程 中一些参数的控制。从本节我们将尽可能通过实例讲解,便于读者理解。 6.6.1 以不同方式从 Repository 中抽取(Extract)文档 抽取文件可以抽取单个文件也可以同时抽取多个文件。 如果要抽取单个文件,鼠标右击需要 Extract 的模型或者文档,在弹出的菜单中点击【Extract】。 如图 6-42 所示。 图 6-42 鼠标右键抽取文档 弹出窗口如图 6-43 所示,择以 Project Management(PDM)为例,当点击【Extract】按钮时会 直接进如图 6-44 所示的对话框。 此外还可以通过 Repository/Extract 当选择此种方法来抽取文件时将会出现如图 6-43 所示的 作者:姜江 error 440 对话框。 图 6-43 抽取多个文档 用户可以通过点击 来选取要抽取的文件,如图 6-44 所示,当选择完要抽取的文件后,点 击【 OK】按钮回到 Extract Multiple Documents 对话框。用户可以重复此操作来对多文档进行抽取。 图 6-44 “Extract Document”窗口 单用户选好需要抽取的文档时,那么可能会有人想了解在抽取的过程中在后台数据库中究竟 发生了什么呢。在抽取文件之前我们先打开 SQL Server 事件探查器,新建一个跟踪摘要文件。如 图 6-45 所示。 图 6-45 连接 SQL Server 点击【确定】按钮进入跟踪属性的设定窗口,由于该部分内容主要是向大家介绍 Extract(抽取) 作者:姜江 error 441 在后台数据库的执行过程,所以这里的参数就按系统默认的即可。点击【运行】按钮来建立跟踪 摘要文件。如图 6-46 所示。 图 6-46 新建跟踪 点击【OK】按钮,将会显示如图 6-47 所示的窗口。 图 6-47 比较模型后抽取模型 .由于我们的操作是初级的,所以我们在这里不会设计到那些参数的问题。等到下一节我们会 详细的讨论。 点击【OK】按钮来进行文件的抽取,直到 OutPut 窗口显示结果如图 6-48 所示为止,抽取文 件的任务就完成了。 作者:姜江 error 442 图 6-48 抽取过程在 OutPut 窗口的显示 现在我们就来看看在后台的数据库究竟到发生了些什么。如图 6-49 所示,由于篇幅所限,具 体含义这里就不再赘述。 图 6-49 SQL Server 跟踪中显示的信息 6.6.2 抽取(Extract)过程中的参数控制 在上一节中我们完成了一个完整的抽取任务,当然在真正的工程项目中抽取并不是这么简单, 在这一小节中我们将来学习抽取过程中的参数设定。 这里我们还是以前面内容为例,在图 6-44 所示对话框中有个 按钮,点击打开如 图 6-45 所示的对话框,默认情况下提取模型时,所选模型中授权的包将被提取。要提取的包含有 快捷方式时,包选择将包括快捷方式引用的包。即使用户对被应用的包没有读取权限,也能提取. 如果不想提取全部的模型,则可以选择一个或多个包。选择包窗口的列表中只显示用户有访问权 限的包.当选择子包时,系统会自动扩展选择父包,以保证它们之间的联系。如果取消子包的选择, 父包的选择将会被保留,而且会变灰。 作者:姜江 error 443 图 6-50 选择要抽取的包 当选择提取多文档时在出现的对话框中有两个图标,他们功能分别为: 是添加有联系的文 件版本; 是从一个结构中添加文件版本(Repository/Extract)。 当进入抽取对话框时,如图 6-44 有一些参数需要设置,具体的设置方法如表 6-8 所示。 表 6-8 “Extract Document”窗口部分参数 参数名 属性 Name 在下拉列表中选择要抽取的模型 Version 显示要抽取的模型目前的版本 Extract dependencies 是否要见它的依靠同时提取 Lock before extract 是否在抽取前先将该模型锁定 Extract to file 该对话框的选择与否关系到下面参数的设置 Path 选择要抽取模型的路径 Merge document 如果 Local 中已有了该模型是否合并 Open document 提取后是否打开该模型 Read-only 是否已只读的模型抽取 Add to workspace 是否添加工作空间 这里我们设置好参数后点击【OK】按钮进入如图 6-47 所示对话框,来对抽取过程中的参数 作进一步的设置。在这个对话框中主要分为三部分,其中上面各分为左右两部分,分别列出了该 文件从哪来要被放到哪去,在各个部分里列出了该文件中所包含的内容。在下面是关于这两部分 文件内容的比较。你还可以通过选择文件来查看他们信息的比较情况。 这里我们只对 的功能进行详细说明。点击此按钮会出现如图 6-51 所示的对话框在里用户 可以选择要比较的信息来进行比较。 作者:姜江 error 444 图 6-51 设置要比较的内容 点击【OK】按钮,至此我们已经对抽取过程中参数的设定作了简单的介绍。下面我们将对数 据仓库中文件的其它操作进行讲解。 6.7 通过 Repository 更新模型/文档 本小节就是上一节的延伸,它是通过把数据仓库中的文档(模型)抽取出来,在 Local 中进行 修改后在把它固化到数据仓库中去,在固化的过程中要经过上一小节的比较,然后通过一些参数 的设置,把需改后的文档(模型)在 Repository 中更新。(在后面我们将以一个例子来说明) 6.8 在 Repository 中管理文档的版本 在这节中我们讲讲对数据仓库中的文档的管理,主要包括版本的管理、锁的管理、分支的管理 以及配置的管理。 6.8.1 管理文档的版本(Version) 一个文档的版本就是已有文档的一个快照、一种状态,它被保存在 Repository 中。当某个用 户在某个文档上工作时,他必须把文档的版本保存到一个地方,这个地方必须安全、易于被其他 的团队成员看到,同时还要保证该文档的最新进展进行准确的记录。 在 Repository 中所有的文档都可以有版本,但是在类似于文件夹、用户以及用户组的对象则 不存在版本信息。 在当前的版本中如果文档被更新,当它被固化到 Repository 中时,它的版本也是随之更新的。 尽管默认情况下版本是随着文档自动更新的,但是如果用户把该文档的版本被锁定,则在固化新 的被修改过的文档时,旧的版本并不会自动的随之更新,而是在版本树下创建一个新的版本项。 用户可以对版本进行定义、创建(冻结和解冻)以及删除操作,下面就具体操作方法。 作者:姜江 error 445 A.查看和修改文件版本的属性 在文档或模型的属性窗口中有两个和版本有关的 Tab 页面,即:Versions(版本)和 (Version Info(版本信息),如图 6-52 所示。 图 6-52 查看文档的版本信息 在 Versions 页中显示了一个版本树,在这个树中包含了来自不同分的文档,能通过展开节点 来显示其中的文档。也能对文档版本进行管理,但是不能对对象进行操作。在文档版本的 Versions 属性也,用户可以通过一些工具以下工具对不同的版本进行管理,如表 6-9 所示。 表 6-9 Repository 属性窗口“Versions”页工具含义 工具 名字 描述 修改 显示修改页 抽取 抽取选择的版本 比较 比较两个版本 冻结 冻结选择的版本 解冻 解冻选择的版本 锁定 锁定选择的版本 解锁 解锁选定的版本 删除 删除选定的版本 在 Version Info 页中也有一些参数,它能对所选择的文档或对象进一步了解,如图 6-53 所示。 作者:姜江 error 446 图 6-53 在“Version”中查看版本信息 上图中相关信息的含义如表 6-10 所示。 表 6-10 “Version Info”页相关信息 特性 描述 Creation User 显示的是在数据仓库中创建文档或对象的用户 Creation Data 该文档或对象的创建时间 Last modification User 最后一次修改该文件的用户 Last modification Data 最后一次修改的时间 Version Number 版本号 Version Branch 该版本所属的分支的名字 Version Comment 该版本的注释 B.创建文件的版本 文档作为一个版本被存储在 Repository 中。不能直接在 Repository 中创建版本,文档被固化 在 Repository 中的时候,伴随着固化将产生该文档的新版本。 当第一次固化文档在数据库仓库中时,该文档的第一个版本将在数据仓库中被创建。它是可 以被更新的。如果没有冻结该文件的版本,系统不会在每次固化时都产生一个新的版本,只有当 以前的版本被冻结时,固化才会产生一个新的版本。新的版本或当前分支的最后的版本都是可以 被更新的。 可以通过以下几种方法冻结(Freeze)文档或模型:  选择文档菜单下的冻结的命令  使用冻结工具  选择【Tools】→【General Options】,在弹出的对话框中选中 Freeze after Consolidation 复 选框  固化文档时,在 Consolidate Document 窗口中选中 Freeze current version and create a new 作者:姜江 error 447 version 复选框 如果用户有冻结文档和写文档的权限,用户可以直接在数据仓库的浏览器中冻结文档,文档 或模型被冻结时,包含在文档或者模型中的子对象也被冻结。 操作方法如下: 1. 在 Local 中右击要固化的文档,此时会出现如图 6-54 所示的对话框 图 6-54 选择要固化的文档 2. 选择相应的数据仓库中的文档 3. 选择 Freeze current version and create a new version 或选择 Freeze after consolidation 4. 点击【OK】按钮,此时固化将产生一个新文档或冻结最新的版本 5. 在数据仓库中选择该文档,右击选择 Version,弹出如图 6-55 所示窗口。 图 6-55 Repository 模型属性窗口的“Version”页 6. 点击【确定】按钮结束操作。 在解冻的时候用户必须有管理所有文档的所有权限。解冻其中一个版本时,当前分支的其他 版本仍旧处于解冻状态,而 PowerDesigner 中的浏览器(Browser)中则只显示文档的最后的版本, 可以用解冻工具或使用菜单命令使文档解冻(Unfreeze) C.删除文档的版本 作者:姜江 error 448 如果用户有足够的权限时它可以删除文档的版本,当用户删除文档的版本时,文档或者模型 包含的各项子内容也将被删除。 注意:文档版本的删除的操作是不能回滚的,因为该操作会引起严重的数据丢失。 6.8.2 管理 Repository 中的锁(Locks) 如果用户对文档有锁的权限,可以对文档进行锁的操作,给文档加锁就是为了给文档一个暂 时的保护,以防止在固化的过程中其他用户对该文档进行更新。此时被锁定的文档只有设置锁的 用户或对该文档有所有权限的用户允许对该文档进行固化操作。如果另一个用户想对该文档进行 固化操作,则会弹出警告提示窗口提示该文档已被锁定。 总的来说锁的工作有两种方法: 1. 如果用户工作在一个设计团队中并且它有锁定文档版本的权限,如果该用户需要将本 地端的文档或者模型的修改修改更到 Repository 中,可以在每次抽取(Extract)文档 时在该文档上设置锁。当不需要对该文档进行保护时,那么在该文档固化的过程中要 把锁释放掉。如图 6-56 所示。 图 6-56 文档锁定 2. 如果用户是一个团队中的一个设计者,需要对网上的一个设计项目进行锁定的操作, 他可以在一个结构中或在关系模型中锁定单文档版本,也可以锁定多文档版本 2.1 锁定单文档 如果用户有锁的权限,它可以在任何时候锁定数据仓库中的文档。此时用户只需在数据仓库的 浏览器中右击想要加锁的文档,在菜单中选择 Lock,此时会出现下面的对话框,如图 6-57 所示。 (被选文档的版本将变灰),点击【OK】按钮,如图 6-58 所示。 批注 [e35]: 此图已翻译 作者:姜江 error 449 图 6-57 锁定某个文档 图 6-58 文档被锁定后在浏览树中的显示 2.2 锁定多文档 当需要锁定多个文档时,必须使用锁的列表。 1. 选择【Repository】→【Locks】或在在数据仓库的浏览器中右击根节点选择 Lock,弹出 List of Locks 窗口,如图 6-59 所示。 图 6-59 处于锁定状态的文档的列表 2. 在出现的对话框点击 ,来选择要锁定的文档, 是加入模型的版本以及与此模型有 联系的模型的版本, 是对结构的操作。 3. 选定文档后,点击【OK】按钮,重复此操作就可实现对多个文档或模型锁定。 在抽取和固化的时候管理锁 作者:姜江 error 450  在抽取之前锁定文档,是指保证在抽取该文档后,用户在 Local(本地机器上)工 作时,存放在在数据仓库中的该文档的版本不会被其他用户更新,如图 6-60 所示。 图 6-60 选择在抽取之前先锁定文档  在固化之后锁定该文档,当用户在将文档或模型固化到数据仓库之后,然后进行解 锁的操作。只有在抽取时选择了锁定按钮时在固化或该文件已经被锁定的时候,此 选项才可以被使用,如图 6-61 所示。 图 6-61 选择在固化后锁定文档 6.8.3 管理 Repository 中的分支(Branch) 分支是版本树的一个支,它包含文档的版本。团队领导可以用分支组织开发团队的开发工作 同时创建不同的工作环境。用户还可以用分支较好的组织存档的文档。 分支存在 Repository 中可以是个独立的文档版本,即分支可以为空。版本树中的分支可以依 赖另一个分支。起支撑作用的分支叫做基础支,基础分支可以包含它本身,基础分支的复杂程度 是不受限制的。 在用户每次连接数据仓库的时候,都处于某个分支。当前分支是用户在数据仓库中的工作环 境,它提供了一个显示浏览器的文件夹,用户只能看到存在当前分支中的文档的版本,如果当前 分支有其它的依赖分支,也能看到它的基础分支。 作者:姜江 error 451 例如,如图 6-62 所示。 图 6-62 分支控制版本实例 在上图中,版本 3 是版本 2 的基础分支,版本 2 是版本 1 的基础分支,如果用户连接数据仓 库的版本 3,那么数据仓库的浏览器作中显示的是版本 3 的最后的版本。 假设一个软件项目的进展分为以下步骤:需求分析、开发、主版本发布、次要版本发布、后 期维护等。主要版本的发布是对软件中基本的选择,次要版本发布是一些小 Bug 和小的修改。如 图 6-63 所示。 开发的团队工作在三个文档上:  需要 Word 文档详细说明软件的体系结构  需要用 PDM 模型设计软件  需要用 OOM 做软件的原型实现 图 6-63 项目开发分支图 作者:姜江 error 452 该项目的三个分支分别执行不同的任务: 1. MAJOR 分支主要是针对软件的主要版本的发布,该分支中主要涉及到对软件提出的新需 求和设计执行主要的修改 2. MINOR 分支是对于工作过程中一些 Bug 的修改和一些小的修改 3. EBF(Emergency Bug Fix)分支是在主要的分支的修改后,工程师在软件版本发布后修复 Bug 分支的管理主要涉及到分支的创建、分支成员的管理以及分支的删除,下面逐一介绍: A.分支的创建 用户第一次连接 Repository 时,Branch 被自动的创建,这个分支可以被看作比版本 树的树干。在数据仓库中用户能管理分支的权限以及创建分支。通常,一个项目中的领导具有创 建分支的权力。 用户创建分支时,需要设置一些相关参数,如表 6-11 所示。 表 6-11 创建分支的相关参数 参数名 描述 Name 分支的名字 Code 分支的编码 Comment 分支的附加信息 Base Branch 当前分支的基础分支 创建分支的操作步骤如下: 1. 选择【Repository】→【Branches】,弹出 List of Branches 窗口,如图 6-64 所示。 图 6-64 分支列表窗口 该图中显示了当第一次连接数据仓库时系统自动创建的分支的名称。 2. 点击【Add】工具 按钮或者点击列表中的空白行,增加一个新的分支,输入名称和代码 3. 点击【Apply】按钮应用 作者:姜江 error 453 4. 选择刚刚创建的分支所在的行,点击【Properties】工具 ,弹出分支属性窗口,如图 6-65 所示。 图 6-65 分支属性窗口 5. 对分支的属性进行相应的修改,点击【确定】按钮。 B.管理分支中的成员 分支中包含文档的版本,创建一个新的分支时默认情况下是没有成员的。分支具有独立的文 档版本,往一个分支中加入一个版本的方法就是固化。用户固化文档时,在数据仓库的当前分支 中加入了一个版本。每个版本作为当前分支的成员出现。 例如,用户固化好几次同样的文档在数据仓库中,并且每次都可以创建新的版本,既为分支 的成员。 向分支中加入一个文档的操作方法如下: 1. 为想要固化的文档选择分支 2. 选择【Repository】→【Consolidate】,弹出固化文档窗口,如图 6-66 所示。 图 6-66 固化文档窗口 作者:姜江 error 454 3. 点击【Add】 加入文档 4. 选择 Workspace 或 File,选择 New 或 Branch 5. 选择固化的目的地,即文件夹。 6. 点击【OK】按钮,固化的文档成为分支的成员。 7. 选择【Repository】→【Branches】,弹出分支列表窗口。 8. 选择分支,点击【Properties】工具 ,进入 Members 属性页,新的文档或模型成员 出现在此列表窗口中。如图 6-67 所示。 图 6-67 分支包含的文档成员 9. 完成操作后依次关闭窗口。 从成员列表中抽取一个版本的操作方法如下: 1. 【Repository】→【Branches】,分支列表出现 2. 在列表中选择一个分支,点击 ,选择 Members 页,从列表中选择一个成员。点击 图标。 抽取多文档重复 2 第、3 步即可 3. 点击【OK】按钮完成操作。 可以对列表中的成员进行管理,如冻结、锁定。用户还可以删除一个文档的版本,只要该用 户有合法的权限。 用户还可以在数据仓库中改变分支,例如,用户当前的工作环境是 Project 下的 MINOR 分支 中的 Implementation .OOM,如果有用户反映说该软件有 Bug,那么开发者必须在主要的版本中纠 正它,此时用户可以选择分支为了 EBF 分支或者维护 Implementation .OOM 分支。 当改变分支,一个新的分支将在数据仓库中出现,下次连接数据仓库时或是在 PowerDesigner 中定义了 Auto-Connect 时,分支将自动被选中。 在 Repository 中改变分支的操作方法如下: 1. 选择【Repository】→【Change Branch】,弹出选择分支窗口,如图 6-68 所示。 作者:姜江 error 455 图 6-68 改变分支 2. 在其中选择一个分支,点击【OK】,浏览器将刷新显示分支的版本. C.分支的删除 在数据仓库中如果用户有管理分支的权限,那么它能删除一个分支,如果一个分支包含成员 的话它不能被删除,删除分支是不可恢复的操作。从上面的列表框中选择一个分支,点击 图标, 既为删除该分支,在删除的过程中系统将会提示此操作时不可逆的。 到此对分支的管理已经结束,在 PowerDesigner 的 Repository 中还有部分重要的内容,那就是 配置(Configuration),接下来我们将进行本章的最后一节的学习。 6.8.4 管理 Repository 中的配置(Configuration) 配置(Configuration)不同的文档的不同版本的集合,它以较为正规化的方式将不同的文档及 其对应的版本组织起来。在 Repository 通过使用配置可以更方便的恢复特定版本的文档的组合。 配置和分支不同,配置不能是空的,在创建一个配置时,必须向其中插入一个文档的版本,如 果在数据仓库中没有固化的文档的版本,那么不能创建配置。 在 Repository 中如果用户有管理配置的权限,那么该用户就能够创建配置,在项目中能够创建 配置的用户通常是团队的领导者。 创建配置的操作方法如下: 1. 【Repository】→【Configurations】,此时配置列表将会出现。如图 6-69 所示。 作者:姜江 error 456 图 6-69 配置列表窗口 2. 点击空白行或者鼠标点击【Add a Row】工具 ,一个新的配置将会增加到列表中。 3. 输入 Name 和 Code,点击【Apply】按钮应用。 4. 选择该行点击【Properties】工具 ,或者鼠标双击行首箭头,弹出 Configuration 属性窗口, 如图 6-70 所示。 图 6-70 配置属性窗口 5. 在这里设置好参数,然后点击【确定】按钮。 接下来就是在配置中管理文档的操作: 配置是一系列相关的文档版本的集合,创建配置时,同时也必须向该配置中添加文档版本成员。 配置的成员就是一个文档的版本,在同一个配置中不可能添加相同文档的几个版本。 用户可以通过以下的方法相配置中加入版本:  向配置中加入一个单独的文档版本 1. 选择【Repository】→【Configurations】,弹出配置的列表窗口。 2. 在列表窗口中选择一个配置,点击【Properties】工具 ,弹出配置属性窗口 3. 在配置属性窗口中进入 Members 属性页。 4. 点击工具 ,弹出如图 6-71 所示的对话框: 作者:姜江 error 457 图 6-71 向配置中增加文档 5. 在 Name 的下拉列表框中选择一个文档,在 Version 的下拉列表框中选择一个版本。 6. 点击【OK】,文档的版本被加到配置的列表框中,如图 6-72 所示。 图 6-72 配置的文档成员 7. 依次点击【OK】按钮完成操作。  向配置中加入另一个配置中的文档版本 1. 选择【Repository】→【Configurations】,探出 Select Configuration 窗口。 2. 在列表窗口中选择一个配置,点击【Properties】工具 ,弹出配置属性窗口。 3. 在配置属性窗口中进入 Members 属性页。 4. 点击【Add Document Versions from a Configuration】工具 图标,弹出 Select Configuration 窗口,如图 6-73 所示。 图 6-73 向配置中加入另一个配置的文档版本 5. 从列表中选择一个配置。 作者:姜江 error 458 6. 点击【OK】按钮。选择的配置将出现在列表框中。  向配置中加入和模型有关的模型的版本 如果在上述步骤中点击【Add Related Documents】 图标,加入的就是与模型版本相关 联的模型版本文档(即该模型中快捷方式所指向的模型)。在 PowerDesigner 中有关系的模型 版本文档指的是与另一个模型有联系的快捷方式。当向一个配置中添加一个模型时,也能将与 该模型有联系的模型添加到该配置中去。 如果用户有管理配置的权限,则该用户可以在配置中删除文档的版本。但要注意,此操作 只是把该文档与配置分离了并没有从数据仓库中把该文档删除。 在配置中抽取文档能够为用户完成特殊的任务在 Local 中创造适当的工作环境。 作者:姜江 error 459 第7章 高级应用&网友常见疑难解答(FAQ) 前面各章分别介绍了 PowerDesigner 在数据库建模方面的应用,掌握这些内容后,基本可以 完成数据库建模工作中的大部分应用,但是不少读者在使用类似建模工具时,总会遇到这样或者 那样的问题,也会提出一些建模软件本身没有解决的问题。笔者经常在网上看到很多朋友因为 PowerDesigner 方面的书籍太少,碰到很多问题无法解决,而这些问题往往十分典型。因此,读者 尽了自己的一点薄力,对 www.csdn.net 以及 www.smiling.com.cn 等网站的技术论坛中涉及到 PowerDesigner 的问题进行了详细解答,并且在这里归纳总结,形成常见问题(FAQ),希望能 够对读者有所帮助,起到抛砖引玉的作用。 在“建立物理数据模型(PDM)”这一章中,介绍了对 DBMS 进行定制和 PowerDesigner 中的变量,在“文档生成-Report”一章中以实例的方式讲解了如何利用它强大的文档定制功能 生成特定需求的文档。PowerDesigner 正是因为有了这些用户可以自己使用的变量、可以自己定 制的内容,才使得 PowerDesigner 具有非常好的扩展性,灵活的解决许多现实中的难题。 PowerDesigner 自身并没有解决所有的数据库设计实现的相关问题,但是灵活的扩展机制为我们 带来了极大的方便,不过这些机制的掌握属于高级应用,一般情况下,只有用户对数据库系统以 及 PowerDesigner 相当熟悉的情况下才可能会接触到这些高级应用。 这部分的内容组织形式如下:  首先,提出并且描述问题  其次,分析和讨论问题  最后,根据前面的分析讨论,结合 PowerDesigner 的高级应用解决问题 总体上以向导的方式,沿着解决问题的自然思路,对问题进行深入细致的剖析,最后达到解 决问题的目的。笔者之所以采用这种方法,是为了提高读者自身的分析问题和解决问题的能力, 提供一种解决问题的思路,而不是仅仅提出解决方案,读者在看这部分内容的时候就是从问题着 手一步步学会如何解决问题,而不是类似于“Help”或者“帮助”的字典型的手册。 PowerDesigner 的书籍和网站上相关的论坛都非常少,因此,笔者迫切的希望所有对 PowerDesigner 感兴趣的人都能够较好的掌握这个工具,希望有尽可能多的人学会利用 PowerDesigner 的一些高级应用来解决问题,建立一个虚拟的学习社区,起到共同促进、教学相长 的作用。 7.1 问题一 name 和 code 的输入错误:有一位网友使用 PowerDesigner 进行数据库建模,由于对 PowerDesigner 的使用不熟悉,勿以为对表中的列生成脚本会使用 name 而不是 code。该网友的本 意是:使用中文作为注释便于理解和沟通,而 SQL 脚本则采用英文。但是正是由于对这个概念没 作者:姜江 error 460 有弄清楚,恰好将 name 和 code 弄错,code 输入列中输入了中文,name 列中输入了英文。如图 7-1 所示。 图 7-1 输入错误的列的列表 所以生成的脚本如下: ======================================== create table 学生 ( 学号 int null, 姓名 varchar(20) null, 年龄 smallint null, 性别 bit null, 已婚 bit null, 身份证号 varchar(18) null, 备注 varchar(50) null ) ======================================== 这恰恰和他的本意相违背,所以,为了正确的生成英文脚本时,不得不手动将 name 和 code 以正确的中英文次序再重新输入一次,模型中有几十张表,该工作耗费了大量宝贵的开发的时间, 造成了不必要的损失。 讨论: 要解决这个问题我们要首先要了解 PowerDesigner 是如何成脚本。在 3.16 PowerDesigner 中的 变量一节中曾经提到,很多对象都既包含一个代码变量(code variable)又包含一个生成代码变量 (generated code variable)。代码(code)变量是在对象属性窗口中定义的属性代码,而生成代码 (generated code)变量则是根据对象的属性代码和生成选项计算而产生的,如果代码(Code)的 长度超过了 DBMS 中限制的最大长度,则会自动截取 code 产生生成代码(generated code)。而 PowerDesigner 在默认情况下生成脚本既不是采用 name 也不是 code,而是代码(code)生成的“生 作者:姜江 error 461 成代码”(generated code)作为对象的名称。而通常情况下由于 code 本身没有超过 DBMS 规定的 最大长度,所以会给人一种错误的认识,认为脚本生成使用的是 code 作为名称。 这样,在这个例子中解决问题的思路就很清楚了,如果可以采用 name 来生成英文代码就可 以解决该问题,换句话说,就是用 name(名称)替换 generated code(生成代码)。参考 3.16 PowerDesigner 中的变量一节中的变量列表:“用于定义表的变量”,可得知 COLUMN 是列的生成代 码,COLNNAME 是列名称(name), COLNCODE 是列代码(code)。 COLNCODE 和 COLUMN 不同之处在于 COLUMN 是列的生成代码,即 COLNCODE 在 DBMS 最大长度范 围内的 code,如果 code 太长,就会被截取一部分,这时候的 COLUMN 就和 COLNCODE 就不相等了, 但通常情况下 code 不会超过最大长度即与 COLUMN 相等。 解决方案: 如图 7-2 所示,选择 Database->Edit current database,选择 script->object->column->add 图 7-2 选择需要更改的项目 可以在窗口右方的 Value 编辑框中看到定义表中列的代码模板: ========================================== %20:COLUMN%[%COMPUTE%?AS(%COMPUTE%):%20:DATATYPE%[%IDENTITY%?%IDENTITY%:[%NULL%] [%NOTNULL%]][ default %DEFAULT%] [[constraint %CONSTNAME%] check (%CONSTRAINT%)]] ========================================== 参考 3.16.2 PowerDesigner 中对变量格式化一节,此外,由于变量在 PowerDesigner 中的引用 需要加“% %”,所以很容易理解代码模板中的“%20:COLUMN%”表示对列的生成代码(generated code) 采用固定长度 20 位,而我们需要做的正是将 COLUMN 换为 COLNNAME,也就是将“%20:COLNNAME%” 换为“%20:COLNNAME%”,然后点击【确定】按钮,弹出确认窗口,点击【是】表示保存该修改。 进入表中的 preview 属性页中可以查看代码发生变化,基本上解决了这个问题: ========================================== create table 学生 ( 作者:姜江 error 462 studenNo int null, studentName varchar(20) null, age smallint null, gender bit null, isMarried bit null, idCardNo varchar(18) null, description varchar(50) null ) ========================================== 观察代码发现表名称还是采用了这位网友输入的相反的中文,我们可以用相同的方法, Database->Edit current database , 选择 Script->Object->Table->Create 将 %TABLE% 换 为%TNAME%,这样,便会发现脚本中的“学生”也会正确的成为“student”。 通过这种方法,这个问题的解决只需要花费不到一分钟的时间,而不需要动辄手动修改数小 时,让人头晕眼花没有一丝成就感。 7.2 问题二 1. name和 code之间如何自动转化?举例:系统中我们经常输入 name 为“性别”,code 为“ gender”; 输入 name 为“姓名”code 为“name”;输入 name 为“Account”code 为“ACCNT”;输入 name 为“Address”code 为“Addr”,在不同的系统中可能都存在这样一些我们会经常用到的词语, 它们从 name 到 code 之间的映射都是一致的,但是在不同的模型和不同的表中,我们又不得 不一次次的重复输入这些值,即使是拷贝,也需要很大的工作量,如果能够自动转化则会事 半功倍。 2. 网友 Kevin(7434628):最近我刚介入一个系统,在 PD 的目录树中表名全用汉字显示,而数据 库中都为英文或简写,这样给查表造成很大麻烦。有什么方法可解决?(即我希望 code 中即有 表名而且有汉字说明) 讨论: 通常,设计人员为了便于沟通理解,往往将对象的 name 设置为中文或者英文全称(name 往往 用于沟通和理解),而 code 用于生成脚本,所以通常情况下都采用英文,如果字段名比较复杂则 甚至采用英文缩写。但是很多 DBMS 却不支持对列的说明性文字的定义,以 SQL Server 2000 为例, 它不支持对于每个列都有一个备注的说明项来表明该字段的含义,所以网友 Kevin 才提出了这个 让很多设计人员都颇为困惑的一个问题:大量的英文和英文缩写非常不易理解。 笔者认为,良好的系统分析和设计应该有统一的命名和含义。笔者小时候看过一个电视剧, 说的是有个人不太识字,一个人漂流在外。此人有弟弟一个,有幸取得良妻,虽然日子过得很清 苦,但也过的自在。这个弟弟目不识丁他哥哥很有学位,所以言听计从。话说这位哥哥得知家里 过的清苦,就书信一封打算让弟弟把自己的那块地(那个时候称为“地席”)卖掉换些银两度日, 作者:姜江 error 463 不料却将“地席”写成了“弟媳”。这位弟弟收到信后,百思不得其解,但左思右量还是觉得哥哥 既然这么说必定有道理,所以忍痛将妻子卖给一个富贵人家,酿成了终身遗憾。这个具有讽刺意 味的故事其实还蕴含着一个简单的道理:沟通必须由统一的所有人都能够理解,并且理解一致的 词汇。 看过《人月神话》的朋友都知道,仅次于诺亚方舟的历史上的第二大工程—浩大的巴比伦塔 最后失败终归,原因不是技术不先进(金字塔的技术已经足以建造巴比伦塔);不是时间不充足(没 有时间限制);不是资金不足(足够的石块);不是人力资源不充分(有足够多的人)„„,失败 的真正原因是大家没有共同的交流语言,互相不能够理解,最终相互之间产生了怀疑和不信任, 导致了巴比伦塔的彻底失败。 笔者曾经接触过的一个学校的项目中,先定义了一个表“学历”,然后又定义了“学位”,因 为没有明确的规定“学历”使用 education、“学位”使用 degree,所以,团队内的成员经常将“学 历”和“学位”以及“degree”和“education”之间互换使用,也导致沟通产生严重的语义不一 致,给项目造成了负面影响。程序员使用缩写的方式也不一样,例如对于词汇“studentAccount”, 不同的程序员在不同的时候往往使用不同的缩写,如:stuACCNT、studACCNT 和 studACNT 都可能 出现在程序中。还有些程序员习惯使用生僻的词语(大概是希望编程的同时还可以背单词)或者 晦涩的缩写,比如 studACT(studentAccount)、 pedagogue(教师,完全可以使用 teacher)。这 中概念不一致和不完整为日后的合作开发以及维护都带来极大的不便,从根本上降低系统的开发 和维护效率。 举这些例子,就是想说明,团队开发必须有一致的语义,也就是要保持系统概念的一致性。 通常情况下希望团队在分析、设计和开发以及维护的过程中能够及时快速的建立和更新系统词汇 表(system glossary),词汇表的格式是次要的,重要的是所有的人都能够通过它了解他们在系 统中使用的词语的确切的含义,例如表 7-1 所示。 表 7-1 系统词汇表实例 名词 英文全称 英文缩写 定义 毕业生 Grad Grad 目前正在学校就读的、在一年内即将毕业的学生 在校生 Student Stud 目前正在学校就读的学生(包括毕业生) 校友 Alumni Aln 曾在该校就读,现在已经毕业的学生 研究生 Graduatestudent Graduate 目前正在学校就读的研究生(包括毕业生) 这样,就不会有人使用 graduate 作为“毕业生”,有人作为“研究生”了,表仅仅是一个参考, 实际的开发过程中可以使用任何有利于项目组成员理解和沟通的词汇表方式,可以是电子的 (excel、word 或者 txt、csv 格式的文档,也可以是在线词汇表),也可以是纸面的,如果是一些 具有继承性的角色,甚至还可以使用 UML 对 actor 的继承性做出继承图,附加说明文档。总之, 项目应该根据自己的需要建立适合自己使用的词汇表。 解决方案: 作者:姜江 error 464 1. name 和 code 之间的自动转化 参考:3.4.3 对列的操作的常见问题及其解答中的 C(为什么 code 总是随着 name 变化)和 D (如何在模型中不显示 name,而显示 code) 选择【Tools】→【Model Options】,弹出模型选项窗口,如图 7-3 所示。 图 7-3 模型属性窗口 选择 Naming Convention(习惯命名),在右边选择手指向的复选框“Enable name/code conventions”,表示允许 name 和 code 之间相互转化。然后点击到 Name to Code 属性页中,点击 右下角的【Select a conversion table】工具 ,选择一个 csv 的转化表文件,PowerDesigner 在目 录:E:\Program Files\Sybase\PowerDesigner 9\Resource Files\Conversion Tables(读者的安装目录可 能不同)目录下自带的 stdnames.csv,然后在上图中手指向的下列列表中选择我们刚才选择的 stdnames 文件作为 conversion table,在“ Code to Name”属性页中,也选择该表作为 conversion table。 打开 stdnames.csv 如图 7-4 所示。 图 7-4 PowerDesigner 自带的转化表 可以选择上面窗口右下角的 Edit the selected conversion table 工具 ,对 conversion table 进行 编辑,如图 7-5 所示,我们添加几个最常用到的词汇: 作者:姜江 error 465 图 7-5 编辑转换表 在“Name to Code”和“Code to Name”属性页中的 conversion script 编辑框中分别输 入:.convert_name(%Name%) 和 .convert_code(%code%),表示使用脚本采用 conversion table 中的 数据进行转化。 然后点击【确定】按钮,在模型中创建表 test,进入 columns 属性页,新建几个列,以“姓名”、 “手机”、“account”以及“year”等值分别作为各列的 name,可以观察到 code 可以自动生成, 如图 7-6 所示。 图 7-6 输入 Name 时 Code 自动生成 如果要将 code 转化为 name,例如,我们输入“MOBILE”,希望自动生成“手机”(英文通 常比汉字字符少,打起来省力气一些),则如图 7-6 所示,双击 name 列中 ,即可自动在 name 列生成“手机”字符串。 这样,便实现了 name 和 code 之间的自动转化,这里讲的是对整个模型规定 conversion table, 也可以选择 Naming Convention 的子项,如 table、column 等对不同的对象设置不同的 conversion table。 读者可以在使用的过程中建立自己的常用转化词汇表,词汇表积累的越丰富,创建模型的过 程就会起到更加事半功倍的效果。在下个问题的解答中,将学习如何利用现有数据模型生成 conversion table。 2. 如何解决 kevin 的问题 如图 7-2 所示,将%20:COLUMN%改为:%5:COLUMN%,%5:COLNNAME% (请参考:第 7 章 高级应用 &网友常见疑难解答(FAQ)7.1 问题一),其中 5 或者 20 都是可以修改的,表明长度格式,在 特地功能的表上可以生成如下代码: 作者:姜江 error 466 ======================================================================== create table student ( 学号 ,studenNo int null, 姓名 ,studentName varchar(20) null, 年龄 ,age smallint null, 性别 ,gender bit null, 已婚 ,isMarried bit null, 身份证号 ,idCardNo varchar(18) null, 备注 ,description varchar(50) null ) ======================================================================== 如果只希望产生 name 和 code,仅保留代码: %COLUMN%,%COLNNAME%,则生成脚本如下: ======================================================================== create table student ( 学号,studenNo, 姓名,studentName, 年龄,age, 性别,gender, 已婚,isMarried, 身份证号,idCardNo, 备注,description ) ======================================================================== 这些代码即可作为设计者的参考文档,但是这种格式的文档可读性不强,不易形成对应关系, 下面介绍如何将这种设计和开发人员需要参考的文件转化为 excel 的 csv 格式的文档,既进一步 解决了创建 glossary 的问题,又能够为日后的建模工作提供 conversion table。 3.利用现有数据模型生成 conversion table 选择 Database->Edit current database,选择 Script->Object->Table->Create,右边 values 编辑框中出现生成表的脚本模板,去掉%TABLDEFN%前面的空格,改为如下脚本: ======================================================================== create table [%QUALIFIER%]%TNAME% ( %TABLDEFN% ) [%OPTIONS%] ======================================================================== 作者:姜江 error 467 选择【Database】→【Generate Database】,参考:3.6 使用 PowerDesigner 创建数据库生 成脚本(SQL 脚本)这样可以确保最后生成的代码类似如下脚本: ======================================================================== create table student ( 学号,studenNo, 姓名,studentName, 年龄,age, 性别,gender, 已婚,isMarried, 身份证号,idCardNo, 备注,description ) ======================================================================== 可以使用 UltraEdit 等较好的文本编辑软件编辑该脚本,使得最后脚本中仅包含字段的 name 和 code,删除其他的脚。例如:我们使用 UltraEdit 的【File】→【排序】→【文件排序】,这 时脚本会按字母排序,我们可以比较方便的删除我们不需要的行,只剩下包含列的 name 和 code 的行。处理完之后直接将该脚本文件后缀名改为“csv”即 可,或者创建一个 excel 文件,在 excel 中选择菜单【数据】→【导入外部数据】→【导入数据】,然后选择这个脚本文件,在向导中的分 割符号中选择“逗号”,然后将文件另存为“filename.csv”,两种方法生成的文件完全相同,如 图 7-7 所示。 图 7-7 生成的 Name 和 Code 的对应表格 如果我们已经创建好模型,就可以通过这种方法定制数据库生成脚本,然后将脚本转化为 csv 格式的文件,作为 conversion table。设计人员如果能够较好的利用该功能,会为自己的开发建 模工作带来很大的效率提升,而 kevin(这样给查表造成很大麻烦。有什么方法可解决?即我希望 code 中即有表名并且有汉字说明)的问题也得到了较好的解决。 作者:姜江 error 468 7.3 问题三 网友 littlestoneyi (围城): PowerDesigner 创建索引的时候,升序降序不能选择,如果 使用 SQL Server 2000 为何不能规定索引的升降序。 如果将 DBMS 切换为 Oracle version 9i,进入某个表的属性窗口,点击 indexes 属性页,双 击某索引,弹出索引属性窗口,在 columns 中可以指定列的升降序,如图 7-8 所示。 图 7-8 DBMS 为 Oracle 时设置索引的升降序 该设置将最终反映在代码中,如果点击 preview 属性页,可以看到如下代码: create index STU_NAME_IDX on "student"("name" DESC) 但是,如果将 DBMS 切换为 SQL Server 2000,则该属性页中不存在“Sort”列,即使我们使 用【Customize Columns and Filter】s 工具 ,也不能找到该列。 讨论: 通过上述问题可推断,DBMS 为 SQL Server 2000 时没有选择升降序的选项,出现这种情况, 除了搜索索引窗口的各个角落之外,就只能通过定制 resource 原文件了,也就是 DBMS 的配置文 件来修改。所以应该进入 resource editor 对 index 进行修改。 解决方案: 选择 Database->Edit current database,选择 Script->Object->Index, 发 现 有 一 项 EnableAscDesc,它的 comment 为“ASC, DESC keywords allowed”,可以看到右边的 values 值为 “NO”,表示不允许在脚本中使用 ASC,DESC 关键字。在这里我们将它改为 Yes,点击【确定】按 钮。在弹出的确认对话框中点击【确认】。 这时我们再次进入刚才的窗口中,可以看到 Sort 列,也可以选择 ascending 和 descending, 读者不要以为已经大功告成了,虽然这里可以定义升降序,但当点击 preview 属性页之后却会惊 奇的发现生成的代码根本没有 asc 或者 desc 关键字,也就是说这里的修改在生成的代码中将不反 映出来。 显然,问题处在“生成”二字上,我们查看 index 下的 Create 项,代码模板如下: ==================================================================================== create [%UNIQUE%] [%CLUSTER%?clustered:[%R%?[nonclustered]]] index %INDEX% on 作者:姜江 error 469 [%QUALIFIER%]%TABLE% ( %CIDXLIST% )[%OPTIONS%] ==================================================================================== 可以推断出%CIDXLIST%为索引包含的列的列表,而 desc 和 asc 关键字是针对某个具体列的, 所以应该在具体列的定义中来修改。在 index 的 create 项上方有一个 AddColIndex 项,它的 comment 为“Command for defining an index column”,可得知这就是我们需要修改的脚本,它 的代码只有%COLUMN%。所以我们要做的事情就是修改这段代码使得在%COLUMN%后面加上升降序的 关键字。参考:3.16.1 PowerDesigner 变量列表的“用于定义索引的变量”和“用于定义索引列的 变量”两张表,或者参考图 7-9 获得系统变量的一些列表和说明。 图 7-9 在“DBMS Properties”窗口查看索引的变量及其含义 可得知%ASC%是表明索引中列的升降序的变量,因此我们将 index 对象中的 AddColIndex 项的 value 改为:%COLUMN% %ASC%,这时候再设置索引中列的升降序即可在脚本中得到反映,如下面 脚本:create index STU_NAME_IDX on student (name DESC) 7.4 问题四 网友 achess():我在用 pd9.5 把一个物理模型(pdm)生成建表 SQL 脚本的时候,总是发现表名 和字段名带有引号,导致我在建表中出错,大家能否知道怎么解决这个问题? 网友 cultra(飞帆):PowerDesigner(版本是 9.51)生成数据库脚本的疑问,DBMS 为 Oracle 时为什么每个表名和字段名都带引号? 生成代码如下: create table "Oper_Old_Operator" ( "OperId" varchar2(20) not null, 作者:姜江 error 470 "OperName" varchar2(40) not null, "OperStatus" char(1) default '1' not null, "haveRecord" char(1) default '0' not null, "LastLogin" date default 'to_date(''1899-1-1'',''yyyy-mm-dd hh24:mi:ss'')' not null, "LastLoginIP" varchar2(16) default '0.0.0.0' not null, constraint PK_OPER_OLD_OPERATOR primary key ("OperId") ); 疑问一: 为什么每个表名和字段名都带引号? 疑问二: 为什么生成'to_date(''1899-1-1'',''yyyy-mm-dd hh24:mi:ss'')' 应该是 to_date('1899-1-1','yyyy-mm-dd hh24:mi:ss') 网友 oceanwu (oceanwu):请问 powerdesinger9.5 建立基于 oracle 的 PDM,为何表名列名 会自动加上双引号? PowerDesigner 9.5 版本,在建立基于 oracle 的物理数据模型时候,生成 表的 SQL 脚本为: ==================================================================================== create table "Table_1" ("Column_1" INT,"Column_2" INT) ==================================================================================== 为什么表名和列名会出现引号呢?建立表空间,用户等也存在同样问题,若选择 DBMS 为其他 则没有引号。我不想要引号如何去掉呀,有相应的设置吗? 讨论: 其实加引号是 PL/SQL 的规范,数据库会严格按照“”中的名称建表,如果没有“”,会按照 ORACLE 默认的设置建表(DBA STUDIO 里面),默认是全部大写,这样,在 ORACLE 数据库里的字段 就如“Column_1”,如果你把引号去掉,ORACLE 自动默认为全部大写,即“COLUMN_1”,所以不必 担心,这段 SQL 在 PL/SQL 中执行的时候是没有任何问题的,如果不加引号,在 PL/SQL 会自动识 别为大写。 这个问题是生成脚本格式的问题,因此,我们可以尝试在 DBMS 配置文件中修改相应的格式设 置来解决这个问题。 解决方案: 选择 Database->Edit current database , 选择 Sql->Format , 有 一 项 CaseSensitivityUsingQuote,它的 comment 为“Determines if the case sensitivity for identifiers is managed using double quotes”,表示是否适用双引号来规定标识符的大小写, 可以看到右边的 values 默认值为“YES”, 如图 7-10 所示。手指向的位置改为“No”, 点击【确定】 按钮。在弹出的确认对话框中点击【确认】。 作者:姜江 error 471 图 7-10 不使用双引号 再次生成脚本即发现双引号自动去掉,示例脚本如下: ==================================================================================== create table Table_1 ( Column_1 INT, Column_2 INT ) ==================================================================================== 7.5 问题五 网友 billok (bill):在 SQL 的企业管理器的编辑关系图中,有一项叫“对 INERT 和 UPDATE 强制关系”的,在 PowerDesigner 中如何设置,能使其与 SQL Server 2000 同步数据库后改变在 企业管理器中看到的这一项啊,我是想把它变为不选中。 讨论: 在 PowerDesigner 中没有相应的选项,所以,我们先创建一个关系图,右键关系的连线,在 弹出的菜单中选择属性,在属性窗口中将“对 INERT 和 UPDATE 强制关系”变为不选中,点击【关 闭】。然后在空白处点击鼠标右键,弹出的菜单中选择保存更改脚本。出现脚本窗口,可发现有类 似如下的代码: ==================================================================================== ALTER TABLE dbo.OrgStudent NOCHECK CONSTRAINT FK_ORGSTUDE_REFERENCE_STUDENTO GO ==================================================================================== 这说明这段代码可以使“对 INERT 和 UPDATE 强制关系”变为不选中,因此,可以通过 PowerDesigner 中的 DBMS 的生成脚本的 resource 源文件中规定:创建 reference 时,也自动生成 这样的脚本。 作者:姜江 error 472 解决方案: 选择【DBMS】→【Edit Current DBMS】,找到【Scripts】→【Reference】→【Create】。通 过观察可以得知 values 编辑框中的代码模板为创建 reference 的模板,因此,可以在创建 reference 之后对外键的 reference 进行修改,通过上面那段代码分析,可以将各个对象的实例 映射为 PowerDesigner 中的变量:dbo.OrgStudent 为表名称,映射为[%QUALIFIER%] %TABLE%; FK_ORGSTUDE_REFERENCE_STUDENTO 为外键约束的名称,映射为%CONSTNAME%“对 INERT 和 UPDATE 强制关系”。如果读者对变量不熟悉,可以参考:3.16.1 PowerDesigner 变量列表,在 Resource Editor 中点击对象的 Category 的图标 ,可在右边 Comment 编辑窗口中查看相关变量,如图 7-11 所示。 图 7-11 在“DBMS Properties”窗口查看 Reference 的变量及其含义 根据上面对变量的分析,可以在【Scripts】→【Reference】→【Create】右边的编辑框中 代码下面添加以下代码: ==================================================================================== go ALTER TABLE [%QUALIFIER%] %TABLE% NOCHECK CONSTRAINT %CONSTNAME% GO ==================================================================================== 如图 7-12 所示。 作者:姜江 error 473 图 7-12 为 Reference 添加新的代码 点击【确定】,在弹出的确认窗口中点击【确认】。进入这个 reference 的属性窗口,点击 Preview 属性页,发现在以前脚本的基础上多了一段脚本,而这段脚本和我们在 SQL Server 2000 中修改 关系后产生的脚本是完全一致的,所以说明该解决方法是可行的。 虽然笔者认为这不是最好的办法,但是主要的目的是提供一种解决该类问题的思路。用逆向 推断方法,通过在 SQL Server 2000 中修改数据库,观察改变后的脚本变化,然后对脚本进行分析, 映射出相应的变量,修改 PowerDesigner 的 resource 文件,即可解决一些通常情况下比较棘手的问 题。 7.6 问题六 网友 tjan (安安):如何在 PowerDesigner 中设置种子值?PowerDesigner 支持的 Sybase 也可 以,为什么 SQL Server 2000 就没有呢?有一个 Identity 的属性标注该字段是自增型的, 网友 wonder01(一可)的回答:我不知道你用的 PowerDesigner 是哪个版本的,但估计差不多: 1. 如果你想把某一个设置成为 Identity 类型的,它的数据类型必须是数字型的,如 integer, numeric; 2. 选定列,打开它的属性,在 general 页上有 identify 属性,选中 3. 在 Extended Attributes 页上,可以看到 ExtIdentityIncrement 和 ExtIdentitySeed,这就是你需要 的,你可以改变它们的值,改变后 redefined 属性被选中 这就完成了,你再看生成的脚本,就可以看到类似 identity(1,2)的东东了 讨论: 首先我们要知道,并不是所有的 DBMS 都支持序列(Sequences)或者标识(Identity),如果 DBMS 不支持 Sequence,那么 Model 菜单中的 Sequence 菜单是灰化不可选取的。网友 tjan (安安)的问题 是如果是使用 SQL Server 2000 作为 DBMS 的情况下,可以规定某列为 Identity,表示自动增长, 作者:姜江 error 474 但是 PowerDesigner 中却没有相应的设置自动增长的“初始值”和“增长步长”的地方。 而网友 wonder01(一可)的回答从理论上来说是正确的,也为我们提供了一种解决问题的思路。 因为在 DBMS 的定义文件中,根据需要可以产生很多扩展属性类型以及扩展属性,这些扩展属性 在脚本生成期间成为变量,用来控制模型的生成。但是实际上如果选择 SQL Server 2000 作为 DBMS,在列的属性窗口中看不到 Extended Attributes 属性页。因为 PDM 的 DBMS Resource 文件 如果没有为某个特定的 Metaclasses(通常是一些模型对象,包括 table,view,columns 等等)定 义扩展属性(Extended Attributes),则该对象的属性窗口中就不显示 Extended Attributes 属性页。 假设前面定义的一个表 testTable,定义 testTableID 为主键,并且为 Identity,如图 7-13 所示。 图 7-13 实例模型 当 DBMS 为 Oracle version 9i 时,创建序列 在 DBMS 为 Oracle version 9i 时,要为列使用序列就必须先创建序列(Sequences),然后将 之应用到列上。 将 DBMS 切换为 Oracle version 9i,选择【Model】→【 Sequences】(oracle 中和 SQL Server 2000 中与 Identity 等同的概念是 Sequences),弹出的窗口中显示当前模型的 sequence 列表,弹吉列表 中的空白行或者点击【Add a Row】工具 ,分别输入 Name 和 Code,点击【Apply】按钮应用。 双击该行行首的箭头,或者选择该行后点击属性工具 ,在打开的序列的属性窗口中选择 Options 属性页,可以在左侧的 Syntax 页中选择某选项,点击【Add a selected item】工具 ,添加到右 边的 Items 页中,选择其中的某个参数在下方的编辑框中为该参数赋值。 双击在 DBMS 为 SQL Server 2000 时创建 Sequences(由 Identity 转化而来):S_TestTable,在 弹出的属性窗口中点击 Options 属性页,将左边的值点击【Add selected item】添加到右侧,然后 在右侧的下方的编辑窗口中输入适当的值,如图 7-14 所示,规定 sequence 的初始值为 1,步长为 2 作者:姜江 error 475 图 7-14 设置 Sequence 的初始值和布长 生成的 sequence 代码如下: ========================================== create sequence S_TestTable increment by 2 start with 1 / ========================================== ========================================== 将序列应用到列上的操作步骤如下: 1. 双击图形模型中的表,进入 Columns 属性页,或者选择【Model】→【Columns】 2. 选择需要定制序列的列,进入属性窗口 3. 在 General 属性页下方的 Sequence 下拉列表中选择一个定义好的序列,点击【确定】按钮, 关闭所有窗口。 4. 由于要其用序列必须重建触发器,请参考 3.5.1 创建触发器,在重建触发器时,选择包含需要 添加 Sequence 的列的表。这样,即可激活序列 数据库是 Interbase 也是一样的,如果换成 SQL Server 2000 则无法规定相应的种子和步长, 如果 PowerDesigner 自带的 SQL Server 2000 的 Resource 文件中包含网友 wonder01(一可)提到的扩 展属性,我们应该可以在列的属性窗口中看到相应的 Extended Attributes 属性页,这说明 Resource 文件中没有包含这样的扩展属性,我们可以尝试来创建这样的扩展属性来解决这个问题。 请参考:3.15.5 使用扩展属性,相信读者能够获得一定的启发 解决方案: 再把 DBMS 切换回 SQL Server 2000,选择【Database】→【Edit Current DBMS】,弹出 Resource Editor,右键 Profile,在弹出的菜单中选择 Add Metaclasses,表示创建一个元类。因为要定义列的 扩展属性,所以,在弹出的 Metaclasses Selection 窗口中选择 Column。如图 7-15 所示。 作者:姜江 error 476 紧接着,为 Column 创建扩展属性,在 Columns 上点击鼠标右键,选择新建 Extended Attribute, 如图 7-16 所示。 图 7-15 增加 Metaclasses 图 7-16 为元类 Column 增加扩展属性 右键 Extended Attributes 点击【新建】,创建两个 item,分别命名为 ExtIncrementInit 和 ExtIncrementStep,分别表示 Identity 的初始值(标识种子)和自动增长的步长(标识增长量),数 据类型均选择为 Integer,ExtIncrementInit 默认值为 1,ExtIncrementStep 默认值为 2,如图 7-17 所示。 作者:姜江 error 477 图 7-17 设置两个扩展属性的默认值 创建好扩展属性,我们就要使用它了。我们分析要加入 Identity 就是要在列创建的模板中加入 创建好的扩展属性才可以生成相应的脚本,所以,在 Resource Editor 窗口中选择【Script】→ 【Objects】→【Add】,在右边的 values 编辑框中包含创建列的脚本模板: ========================================== %20:COLUMN%[%COMPUTE%?AS(%COMPUTE%):%20:DATATYPE%%IDENTITY%?%IDENTI TY%:[%NULL%][%NOTNULL%]][ default %DEFAULT%] [[constraint %CONSTNAME%] check (%CONSTRAINT%)]] ========================================== %IDENTITY%?%IDENTITY%:表示如果该列是 Identity,则置为 Identity 关键字,因此我们可 以尝试在这里加入我们定义的扩展属性,将代码修改如下: ========================================== %20:COLUMN%[%COMPUTE%?AS(%COMPUTE%):%20:DATATYPE%%IDENTITY%?%IDENTI TY%(%ExtIncrementInit%,%ExtIncrementStep%):[%NULL%][%NOTNULL%]][default DEFAULT%] [[constraint %CONSTNAME%] check (%CONSTRAINT%)]] ========================================== 实际上是将%IDENTITY%? %IDENTITY% 修改成为%IDENTITY% (%ExtIncrementInit%, %ExtIncrementStep%),含义为如果该列是 Identity,则加入 Identity 关键字, 并且在括号中表明该标识的种子和增量,中间用逗号隔开。而使用 %ExtIncrementInit% 和 %ExtIncrementStep%则符合使用扩展属性的规则,扩展属性作为变量使用时要用“% %”括起 来。 做好修改之后,点击【确定】按钮,在弹出的确认窗口中点击【是(Y)】 表示确认保存 Resource 文件。 这时我们在图形模型中能够双击表 testTable,打开表的属性窗口,进入 Preview 属性页,观察 作者:姜江 error 478 代码预览,发现代码发生了如下改变: ========================================== create table TestTable ( testTableID numeric(6) identity(1,2), constraint PK_TESTTABLE primary key (testTableID) ) ========================================== 这表明使用了定义好的扩展属性在生成代码时起到了我们期望的作用,并且使用了定义的默 认值。 进入列 testTableID 的属性窗口,可以发现出现了属性页“Extended Attributes”,在扩展属性列 表中包含定义好的两个扩展属性,同时还可以对这两个扩展属性的值进行相应的修改,最终这些 修改都将反应在生成的脚本中。如图 7-18 所示。 图 7-18 列的属性窗口中出现刚刚定义的扩展属性 如果我们将该例设置为不是 Identity,那么即使我们规定了这两个值,在最终产生的脚本中也 不会出现,这和我们修改代码的设计思路是相吻合的,脚本如下: ========================================== create table TestTable ( testTableID numeric(6) not null, constraint PK_TESTTABLE primary key (testTableID) ) ========================================== 7.7 问题七 网友 ue (似敌是友):在 PowerDesigner 9 中如何为字段设置默认值为 Getdate()以及其他的 MSSql 函数 ?我 发现 如 果把 Getdate()作为默认值后,在生成的数据库中的默认值却是 "Getdate()",不知这个问题如何解决? 讨论: 作者:姜江 error 479 在 DBMS 属性窗口中,可以看到 Resource Editor 中选择【Script】→【Sql】→【Keywords】, 这个 category 主要定义了 DBMS 的各种保留字和关键字,这些关键字和保留字在生成脚本的时候 不会加上双引号。而通常情况下,如果列或者域的数据类型被认为可能时字符串类型或者时间类 型时,PowerDesigner 会自动加上引号(单引号和双引号随着 DBMS 的不同而不同,并且可以自 定义)。 Getdate()被加引号说明作为默认值该函数没有被识别为关键字或者保留字,因此我们可以在 Keywords 中定义 Getdate()为保留字,而 Keywords 中恰恰包含一项 ReservedDefault,是作为默认 值的保留字,因此我们可以根据这种思路来解决问题。 解决方案: 选择 Database>Edit Current DBMS,在 DBMS 属性窗口,即 Resource Editor 中选择【Script】 →【Sql】→【Keywords】→【ReservedDefault】,在右边 Value 编辑框中添加一行,如图 7-19 所 示。 图 7-19 添加保留关键字“getdate()” 此时再次进入列的属性窗口,在 Standard Checks 属性页中输入 Default 的值:getdate(),观察 生成的代码或者预览脚本,和以下脚本相似: ========================================== create table Table_1 ( Column_1 datetime null default getdate() ) ========================================== 问题得到了解决。同样我们还可以在【Script】→【Sql】→【Keywords】中定义其他的保留 子和关键字,如图 7-20 所示。 作者:姜江 error 480 图 7-20 其他的保留字以及关键字 这里不再赘述,读者可以根据自己的需要定制修改。 7.8 问题八 网友枫少(28113411):我在 PowerDesigner 创建了用户 user,并且设置了访问表和权限,但 运行后 SQL Server 2000 没有产生这个用户,怎么做?生成的脚本在 SQL Server 中总是不能正确 执行? 参考:3.10.5 生成权限控制(privilege)脚本,该节中生成的脚本的样本如下: ====================================================================== /*==============================================================*/ /* Database name: test1 */ /* DBMS name: Microsoft SQL Server 2000 */ /* Created on: 2003-11-21 23:57:32 */ /*==============================================================*/ sp_revokedbaccess jiangj go sp_droprole Designer go /*==============================================================*/ /* User: jiangj */ /*==============================================================*/ sp_grantdbaccess jiangj go /*==============================================================*/ /* Role: Designer */ /*==============================================================*/ sp_addrole Designer go sp_addrolemember Designer, jiangj 作者:姜江 error 481 go ========================================================================== 将这段代码在调用 SQL Analyzer 执行,提示以下错误信息: ========================================================================== 服务器: 消息 15008,级别 16,状态 1,过程 sp_revokedbaccess,行 36 当前数据库中不存在用户 'jiangj'。 服务器: 消息 15014,级别 16,状态 1,过程 sp_droprole,行 39 当前数据库中不存在角色 'Designer'。 服务器: 消息 15007,级别 16,状态 1,过程 sp_grantdbaccess,行 97 登录 'jiangj' 不存在。 新角色已添加。 服务器: 消息 15410,级别 11,状态 1,过程 sp_addrolemember,行 66 此数据库中不存在用户或角色 'jiangj'。 ========================================================================== 讨论: 仔细分析就会发现,错误的原因还是在于我们在生成窗口中选择了 Drop user 和 Drop role 复选框,所以才导致 sp_droprole Designer 和 sp_revokedbaccess jiangj 两条语句的执行都报 错。即使去掉这两条语句,我们同样会发现后面的 sp_grantdbaccess jiangj 和 sp_addrolemember Designer, jiangj 这两条语句仍然不能顺利运行,细心的读者会发现,脚本中似乎没有创建用 户“jiangj”这个登陆的语句,所以,无论我们执行多少次脚本(关于脚本执行的次数,请参考: 3.6.1 生成数据库)都不会产生正确的结果。 另外,有些读者可能遇到过这样的问题,安装好应用系统之后,采用 SQL Server 2000 的用 户分配方案,直接在 SQL Server 2000 的 GUI 中创建用户和登录,假设我们创建了 10 个登陆和用 户供用户使用。突然,有一天,系统奔溃了,如果平时备份比较勤快的话,我们都知道可以恢复 数据库,但是这些用户和登录的信息却往往不能够自动备份下来。 于是,在重新安装系统时就不得不再次手动在 GUI 中添加。即使不是这样,也不得不事先写 好 SQL 语句,在万不得已的时候重建数据库,如果我们先前是通过 GUI 创建的,那么写语句必须 是另外单独进行的一项工作,因为 SQL Server 2000 没有提供用户的脚本导出功能。 前面我们已经学习过可以通过 ODBC 对数据库做反向工程,细心的读者会发现反向工程也可以 将 user、role 等信息反向工程到模型中来,这样就可以确保模型中也保持和数据库同步,在万不 得已的时候通过模型重建数据库,但是通过刚才的例子我们又发现生成的语句不能在 SQL Server 2000 中顺利正确执行。 接下来,学习如何解决这个问题。上面的错误告诉我们,PowerDesigner 自动创建的脚本忽 略了创建用户(登录)的语句,因此,可以推断出,PowerDesigner 自带的生成创建用户的脚本 模板有问题。 作者:姜江 error 482 解决方案: 选择【Database】→【Edit Current DBMS】,在弹出的窗口中的 General 属性页中选择【Script】 →【 Objects】→【 User】→【 Create】,发现右侧的编辑框中的脚本模板为 sp_grantdbaccess %USER%, 在当前数据库中添加一个安全帐户,并使其能够被授予在数据库中执行活动的权限,但是没有创 建登录的脚本,使用户得以连接使用 SQL Server 2000 身份验证的 SQL Server 2000 实例,熟 悉 SQL Server 的读者知道(不知道的也可以通过查询 SQL Server 2000 自带的联机丛书获得帮助) 创建新的登录的存储过程为 sp_addlogin,因此,我们在这了添加一条语句 EXEC sp_addlogin '%USER%', '%USER%', '%DATABASE%',表示对当前数据库,创建一个以%USER%名称为登录名和初 始化密码(第 2 个%USER%代表密码)的用户,如图 7-21 所示中手指向的语句。 图 7-21 在用户创建的脚本模板中增加脚本 修改完毕后,点击【确定】按钮,在弹出的确认保存对话框中点击【确定】按钮。在执行一 次生成权限控制脚本语句,发现在 sp_grantdbaccess jiangj 之 前 多 了 一 行脚本:EXEC sp_addlogin 'jiangj', 'jiangj', 'test',这表明我们的修改产生了作用。这样,我们就可以 正确的执行脚本,同时,还可以通过反向工程,将数据库中的用户、登录信息有效的备份,在必 要的时候进行重建。 至此,我们已经可以自己定制如何生成脚本了,关于数据库的进一步定制修改,请参考:3.15 对 DBMS 进行定制。 7.9 问题九 网友 JasonKing(122002139)和 ymhmax (Max is my faith):我使用 PowerDesigner 9.5 创建了 一个 PDM,如何生成 Microsoft Access 2000 数据库?为什么使用 PowerDesigner 生成数据库时生 成的是 DAT 的文件,即使规定后缀名的为 sql,生成的脚本也不能在 Access 中执行,如果用文本 编辑器打开该生成的文件,发现不是正确的 SQL 语句,这个问题如何解决?而反向工程似乎没有 这个问题。 作者:姜江 error 483 讨论: PowerDesigner 在生成 Microsoft Access 类型的数据库时,采用后缀名为 DAT 的文件来交换信 息,即使我们选择生成的后缀名为 sql,生成的脚本都不是通常的 SQL 语法,也不能在 Access 的 查询工具中正确执行。 新创建一个 Microsoft Access 类型的 PDM,然后创建一个表“公司”,同时为该表创建几个索 引如图 7-22 和图 7-23 所示。 图 7-22 实例模型 图 7-23 为表创建索引 双击该表,进入表的属性窗口,点击 Preview 属性页查看得到如下脚本: ========================================== RemoveIndx C=CompanyName T=公司; RemoveIndx C=PrimaryKey T=公司; RemoveTble C=公司; #============================================================== # Table: 公司 #============================================================== CreateTble C=公司 N="公司" ( C=公司编号 T=COUNTER P=No M=Yes N="公司编号", C=公司名称 T=Text(255) P=No M=No N="公司名称", C=地址 T=Text(255) P=No M=No N="地址", C=城市 T=Text(255) P=No M=No N="城市", C=省区市 T=Text(255) P=No M=No N="省区市", C=邮政编码 T=Text(255) P=No M=No N="邮政编码", C=地区 T=Text(255) P=No M=No N="地区", C=国家 T=Text(255) P=No M=No N="国家", C=网站 T=Memo P=No M=No N="网站" 作者:姜江 error 484 ); #============================================================== # Index: CompanyName #============================================================== CreateIndx C=CompanyName T=公司 U=unique ( C=公司名称 A=ASC ); #============================================================== # Index: PrimaryKey #============================================================== CreateIndx C=PrimaryKey T=公司 U=unique ( C=公司编号 A=ASC ); ========================================== PowerDesigner 要生成的 DAT 文件中内容就是这样风格的一些内容,显然,这不是符合 SQL 语法的 SQL 脚本,因此也就不可能在 Access 中正确地执行。 解决方案: PowerDesigner 在\tools 目露下面提供了 Access.mdb 和 Acces2k.mdb 两个实用程序解决这个问 题,具体的操作办法如下: 1. 将刚才创建的模型生成数据库脚本,后缀名可以是 DAT 也可以是 SQL,这两种格式的文件实 际上都可以用文本编辑器打开,因此没有关系 2. 双击 PowerDesigner 的\tools 目录下的 Access.mbd,弹出如图 7-24 所示窗口。 图 7-24 双击 Access.mbd 弹出的窗口 3. 选择单选框“Generate Access database from script file” 4. 点击 Select database 右端的工具 ,选择保存要创建的数据库的路径,输入文件名称 5. 在 Script file 出选择用 PowerDesigner 生成的 DAT 文件(后缀名也可以是 SQL) 6. 点击【Create】按钮,弹出窗口提示创建成功,如图 7-25 所示。 作者:姜江 error 485 图 7-25 创建成功提示对话框 7. 可以点击 Open MDB 打开创建好的 Access 文件。 这样,PowerDesigner 创建 Microsoft Access 的问题就得到了解决。 PowerDesigner 9.5 的官方文档提示,如果使用 Access97/95/2000 格式的文件,反向工程时 也必须使用 DAT 文件交换信息,笔者使用的是 Access2003,所以,无论是否使用 DAT 文件(如 果使用 DAT 文件,也必须使用生成数据库时所用的 Access.mbd 工具)都可以正确的完成反向工 程。经过进一步的测试,笔者发现反向工程 Access97/95/2000 创建的数据库同样不需要使用 DAT 文件交换信息就可以成功完成反向工程。其中,PowerDesigner 的版本是 9.5.2.908 EBF4。 7.10 问题十 网友 zy8133 (风间苍月):PowerDesigner 9.5 疑问,生成的数据无长度: 我用 domain 设定了几个数据类型,比如 varchar 长度设置为 50,然后在 entity 里面把各个 字段该设置为 int 的设为 int 该为 varchar 的为 varchar,用概念模型生成了物理模型,然后就 直接在物理模型中使用 generate database 功能生成数据库脚本,但是生成的脚本中,int 型很 简单的保存成了 int,应为他的长度不需要设定,但 varchar 就没有长度了,在最后生成的数据 库中都是默认长度为 1,为什么会出现这种情况?另外,我看了那个中间生成的 SQL 脚本,创建 表的语句里面的 varchar 的确也没有写长度,但是前面写了: ========================================== execute sp_addtype varchar, 'varchar(50)' go ========================================== 那么为什么最终生成的数据库中 varchar 类型的数据没有长度而是采取默认长度 1 呢? 讨论: 错误一: 参考:3.3.2 域(Domains),这部分内容中提到过:域的概念实际上可以理解为自定义数据类 型,execute sp_addtype varchar, 'varchar(50)'这段代码也充分的说明了这一点,所以添加这 样的一个域本身就会出错,varchar 这样的数据类型在一般的 DBMS 中都已经存在,从这段添加域 的代码中可以得知该网友使用的 DBMS 是 SQL Server,如果在 SQL Server Query Analyzer 中执行 execute sp_addtype varchar, 'varchar(50)' 就会出现以下错误: ========================================== 作者:姜江 error 486 服务器: 消息 15029,级别 16,状态 1,过程 sp_addtype,行 89 当前数据库中已存在数据类型 'varchar'。 ========================================== 这是因为试图定义的数据类型已经存在,所以可以推断出该网友执行建库脚本是一定会有错 误。在 SQL Server 中,如果没有指定 varchar 数据类型的长度,会默认使用 1。例如以下代码: ========================================== create table hehe ( haha varchar null ) ========================================== 错误二: CDM 中定义域选择数据类型时,如果要定一变长字符串,应该选择“VA%n”,所以数据类 型应该是“VA50”而不是 varchar(50), CDM 生成 PDM 时会自动将该数据类型“VA%n”转化 为“Varchar(n)。 关于模型之间的转化中涉及的数据类型转化,请通过以下内容了解: 1. 选择【Database】→【Edit Current DBMS】(前提是当前 workspace 有 PDM 处于打开状态) 2. 选择 Script\DataType,如图 7-26 所示(Sybase AS Anywhere)。 图 7-26 内部数据类型和物理模型数据类型映射表 3. Script\DataType 下各个条目的含义分别为(如果 DBMS 是 SQL Server 2000,则只有前四个条 目,因为 SQL Sever 2000 不支持抽象数据类型):  AmcdDataType:从内部数据类型到目标数据库类型的转化(“VA%n”转 化为“varchar(%n)) 其中:  %n 是数据类型的长度 作者:姜江 error 487  %s 是数据类型的整数部分的大小  %p 是数据类型小数点后位数  OdbcPhysDataType:从 ODBC 的数据类型转化为目标数据库的数据类型的映射表  PhysDataType:从目标数据库数据类型到内部数据类型的转化表  PhysDttpSize:目标数据库数据类型的存储占用空间大小  LogPhysADTType:从内部 ADT 到目标数据库 ADT 的转化  PhysLogADTType:抽象数据类型转化表(从目标数据库的 ADT 到模型内部 ADT)  AllowedADT:是否允许列或者域使用列表中定一的抽象数据类型作为数据类型。 而该网友在 CDM 中使用了 varchar 作为数据类型,所以 PowerDesigner 就不能识别真正的数 据类型,所以自然就丢失了 50 这个长度了。 下面通过实例来进一步了解学习: 1. 创建一个 CDM,在 CDM 中创建一个域,如图 7-27 所示。 图 7-27 域的属性窗口 2. 创建好之后点击【确定】按钮,PowerDesigner 会弹出一个警告窗口,提示用户在 CDM 中, varchar(50)是不合法的数据类型,如图 7-28 所示。 图 7-28 数据类型错误提示对话框 3. 点击【是(Y)】,表示忽略该警告(点击“是”的目的向读者展示错误是如何造成的,如果不 希望在自己的模型中出现类似的错误就不要点击【确定】按钮,选择合法的数据类型),之后 又弹出如图 7-29 所示的窗口: 作者:姜江 error 488 图 7-29 用域更新数据项 4. 点击【Yes】,表明使用该域修改使用该域的列的数据类型。 5. 在模型中创建一个实体,这个实体中创建一个属性,属性的域选择刚刚创建的“varchar”,如 图 7-30 和图 7-31 所示。 图 7-30 创建实体 图 7-31 为实体的属性选择域 选择【Tools】→【Generate Physical Data Model】,将 CDM 转化为 PDM,可以发现,生成的物 理数据模型中,域“varchar”已经丢失了数据长度的信息,如图 7-32 所示。 作者:姜江 error 489 图 7-32 域的属性窗口 6. 同时,实体转化为表格后,也就自然不包括数据长度的信息,如图 7-33 和图 7-34 所示。 图 7-33 转化生成的表 图 7-34 生成的表的属性窗口 生成代码截取如下一部分: ========================================== /*==============================================================*/ /* Domain: varchar */ /*==============================================================*/ execute sp_addtype varchar, 'varchar' go /*==============================================================*/ 作者:姜江 error 490 /* Table: Entity_1 */ /*==============================================================*/ create table Entity_1 ( Attribute_1 varchar null ) ========================================== 显然,通过我们的分析,这段代码在执行的时侯会产生错误,并且会出现网友 zy8133 (风间 苍月)所提到的问题。 解决方案: 首先解决第一个问题,将域的名称修改为其他的名称,原则是不与 DBMS 中数据类型重复(如: testType),在域的数据类型中选择“VA%n”,改为“VA50”,重新将 CDM 转化为 PDM,即可发现问 题解决,产生的 varchar 类型包含了长度,如图 7-35 所示。 Entity_1 Attribute_1 varchar(50) 图 7-35 包含了长度的 varchar 类型 生成代码截取如下一部分: ========================================== /*==============================================================*/ /* Domain: testType */ /*==============================================================*/ execute sp_addtype testType, 'varchar(50)' go /*==============================================================*/ /* Table: Entity_1 */ /*==============================================================*/ create table Entity_1 ( Attribute_1 varchar(50) null ) ========================================== 这样,这段代码就可以顺利执行,生成正确的结果。 7.11 问题十一 网友 wljcan(www.smiling.com.cn):PowerDesigner 正向生成数据库与逆向生成模型的问 作者:姜江 error 491 题。 在使用 PowerDesigner 建模时,将表的 name 取为中文名字,code 为字段名,在生成 Sql 代码时,表的字段名是英文,备注为中文。 但是,当我逆向生成模型时,name 与 code 都是字 段名,备注是中文。这样与我的正向模型有区别了,并且使用也不方便。 水月听香(121142830):PowerDesigner 有个很大的弱点,就是不能导数据库对象注释,不 论正向还是反向都不可以。 网友 jerrys 的回答:如果想改变这种状况,必须利用 PowerDesigner 生成 PowerBuilder 的 扩展属性。将表的名称与字段等信息保存到扩展属性表中,逆向时先逆向表然后再进行扩展属性 的逆向这样就不会出现你提到的情况了。 ========================================== byfq (不愿放弃)(CSDN) :能否通过 PowerDesigner 的 extended attributes 实现把数据库字 段中文名称(header or comment)作为反转模型中的字段名称(name)?如何实现?可否在生成 脚本的时候将 Name 生成到 DBMS 的 Comment 中? prain2003(好雨知时节) :增加一个外部属性。从数据库中导入。 讨论: 如果 DBMS 是 Microsoft SQL Server 2000,尽管 SQL Server 2000 最终开始支持描述 (Comments),但是在默认情况下 PowerDesigner 9.5 不支持直接将模型中表和列的描述 (Comments)与 SQL Server 2000 之间相互转化。也就是说 PowerDesigner 9.5 中表和列的描 述(备注)不能生成到数据库中,SQL Server 2000 中表和列的描述也不能反向工程到 PowerDesigner 9.5 的模型中。 为了方便讲解,新创建一个 PDM,模型中创建一个员工表,如图 7-36 所示。 图 7-36 创建“员工”表 如果读者在该窗口中看不到 Comment 列,点击【Customize Columns and Filter】工具 ,在 弹出的窗口中选择 Comment 前面的复选框,如图 7-37 所示。点击确定后即可在列的列表窗口中 作者:姜江 error 492 看到 Comment 列。 SQL Server 2000 中可以使用自带的存储过程定义扩展属性,存在四个存储过程对扩展属性 进行操作,它们分别是: 图 7-37 设置显示“Comment”列  sp_addextendedproperty:将新扩展属性添加到数据库对象中。如果属性已经存在, 则过程失败;  sp_updateextendedproperty:更新现有扩展属性的值;  sp_dropextendedproperty:除去现有的扩展属性;  fn_listextendedproperty:返回数据库对象的扩展属性值; 下面举例简单说明这几个存储过程的用法,此示例列出数据库的所有扩展属性: ========================================== SELECT *FROM ::fn_listextendedproperty(NULL, NULL, NULL, NULL, NULL, NULL, NULL) ========================================== 此示例列出表"T1"中所有列的所有扩展属性: ========================================== CREATE table T1 (id int , name char (20)) EXEC sp_addextendedproperty 'caption', 'Employee ID', 'user', dbo, 'table', 'T1', 'column', id EXEC sp_addextendedproperty 'caption', 'Employee Name', 'user', dbo, 'table', 'T1', 'column', name SELECT * FROM ::fn_listextendedproperty (NULL, 'user', 'dbo', 'table', 'T1', 'column', default) ========================================== 图 7-38 查询结果 作者:姜江 error 493 关于这几个存储函数的准确用法和参数,请参考 Microsoft SQL Server 2000 的联机丛书,这 里不再赘述。 在 SQL Server 2000 中创建表 Employee 后,如图 7-38 所示。可以通过如下方式指定字段 的说明: ========================================== exec sp_addextendedproperty N'MS_Description', N'按阳历算', N'user', N'dbo', N'table', N'Employee', N'column', N'Birthday' GO exec sp_addextendedproperty N'MS_Description', N'中文名字', N'user', N'dbo', N'table', N'Employee', N'column', N'Name' ========================================== 当然,也可以在企业管理器中设计表字段时通过指定字段的描述(Comments)达到同样效果。 如图 7-39 所示。 图 7-39 企业管理器中查看生成的描述 在 SQL Analyzer 中执行以下脚本: ========================================== SELECT * FROM ::fn_listextendedproperty (NULL, 'user', 'dbo', 'table', 'Employee', 'column', default) ========================================== 执行结果如图 7-40 所示。 图 7-40 查询结果 反之,如果要将描述信息从 SQL Server 2000 中取出,则可以通过系统表 sysproperties 获得描述信 作者:姜江 error 494 息,可以使用以下脚本获得所有用户表的非空的描述备注信息: ========================================== select object_name(a.id) as 表名,a.name as 字段名,b.value as 说明 from syscolumns a left join sysproperties b on a.id=b.id and a.colid=b.smallid where objectproperty(a.id,N'IsUserTable')=1 and b.value is not null ========================================== 或者: ========================================== select o.name as oname, c.name as cname,convert(varchar(30),p.value) as value from syscolumns c join systypes t on c.xtype = t.xtype join sysobjects o on o.id=c.id left join sysproperties p on p.smallid=c.colid and p.id=o.id where o.xtype='U' and P.value is not null ========================================== 由于两段脚本本质上没有区别,因此返回结果一致,如图 7-41 所示。 图 7-41 查询结果 解决方案: 我们可以推断,既然描述(Comments)可以用固定格式的脚本生成,那么就有可能可以通 过修改 PowerDesigner 的 DBMS 源文件,即修改脚本生成的模板,使得这种过程自动化。同时, 还可以修改反向工程的模板文件,使得描述(Comments)能够转化为模型中的变量的值。比如 说:可以在生成数据库时,将 Name 作为描述备注(Comment)(如果没有单独为表和列定义备 注)生成到 SQL Server 2000 中,反向工程时,也可以将描述备注反向工程为表或者列的 Name, 用户可以根据自己的需要定制这些脚本。 选择 DBMS->Edit Current DBMS,定位到【Scripts】→【Objects】→【Table】→【 TableComment】 项目上,如果不存在该项,则在 Table 项上点击鼠标右键,在弹出的菜单中选择 Add Items,弹 出 Item 选择窗口,选择 TableComment 项,点击【OK】按钮。如图 7-42 所示。 作者:姜江 error 495 图 7-42 选择添加“TableComment” 图 7-43 增加“TableComment”项 如图 7-43 所示,默认情况下或者刚刚创建 TableComment 项时,窗口右边的 Value 编辑框中 为空,如果读者希望模型中表的描述(Comments)转化为 DBMS 中对表的描述,根据在讨论部 分的分析,可以在 Value 编辑框中插入以下脚本模板(%中包含的是 PowerDesigner 中的变量,和 描述对应的变量是%COMMENT%),如果希望将表的 Name 转化为数据库中表的描述,也可以将 “N%.q:COMMENT%”替换为:“ N%.q:TNAME%”: ========================================== [execute ]sp_addextendedproperty N'MS_Description', N%.q:COMMENT%, N'user', N%.q:OWNER%, N'table', N%.q:TABLE% ========================================== 作者:姜江 error 496 同样,选择 DBMS->Edit Current DBMS,定位到【Scripts】→【Objects】→【Column】→ 【ColumnComment】项目上,如果不存在该项,则在 Table 项上点击鼠标右键,在弹出的菜单中选 择 Add Items,弹出 Item 选择窗口,选择 ColumnComment 项,如图 7-42 所示,点击【确定】 按钮,在 Value 编辑框输入以下脚本: ========================================== [execute ]sp_addextendedproperty N'MS_Description', N%.q:COMMENT%, N'user', N%.q:OWNER%, N'table', N%.q:TABLE%, N'column', N%.q:COLUMN% ========================================== 修改之后点击【确定】按钮,在弹出的确认窗口中点击【确定】按钮,表示确认对 DBMS 源 文件的修改,双击图形模型中的表“员工”,在 General 页中表输入表的 Comment:“这是表 的注释--我在测试”,鼠标点击 Preview 属性页,由于默认情况不生成描述(Comment),点击 Preview 属性页中的【Show Generation Options】工具 ,弹出如图 7-44 所示窗口: 图 7-44 在“Database Generation”窗口中选择 Comment 复选框 在手指向的地方选择,选中 Table 和 Column 的 Comment 复选框,表示为表和列生成描述, 点击【确定】按钮,Preview 脚本如下所示。 ========================================== if exists (select 1 from sysobjects where id = object_id('dbo.Employee') and type = 'U') drop table dbo.Employee go /*==============================================================*/ /* Table: Employee */ /*==============================================================*/ 作者:姜江 error 497 create table dbo.Employee ( name varchar(50) null, birthday datetime null ) go execute sp_addextendedproperty N'MS_Description', N'这是表的注释--我在测试', N'user', N'dbo', N'table', N'Employee' go execute sp_addextendedproperty N'MS_Description', N' 中文名字', N'user', N'dbo', N'table', N'Employee', N'column', N'name' go execute sp_addextendedproperty N'MS_Description', N' 按阳历算', N'user', N'dbo', N'table', N'Employee', N'column', N'birthday' go ========================================== 在 SQL Analyzer 中执行该脚本,可顺利运行,与讨论中的脚本功能相同,至此,描述有模型 到 DBMS 的生成已经实现,接下来,进一步研究如何将数据库中的描述反向工程到模型中 将注释反向工程到 PowerDesigner 中 选择 DBMS->Edit Current DBMS, 定 位 到【 Scripts 】 →【 Objects 】→ 【 Column 】→ 【SqlAttriQuery】项目,该项目为 PowerDesigner 反向工程的脚本,如图 7-45 所示。 图 7-45 查看“SqlAttrQuery”项 作者:姜江 error 498 如图 7-45 所示,第一行用大括号括起来的都是变量,而下方的 select 语句返回的值将付给这 些变量,关于反向工程脚本的具体含义,请参考:第 7 章 高级应用&网友常见疑难解答(FAQ) 7.12 问题十二。将脚本修改如下(注意:有字符底纹的脚本为新增加的脚本): ========================================== {OWNER, TABLE, S, COLUMN, COMPUTE, NOTNULL, IDENTITY, DOMAIN,COMMENT} select u.name, o.name, c.colid, c.name, z.text, case (c.status & 8) when 8 then 'NULL' else 'NOTNULL' end, case (c.status & 128) when 128 then 'identity' else '' end, case when (s.usertype < 100) then '' else s.name end, CONVERT(varchar(20),b.value) from dbo.sysusers u join dbo.sysobjects o on (o.uid = u.uid) join dbo.syscolumns c on (c.id = o.id) join dbo.systypes s on ((c.usertype = 0 and s.xtype = c.xtype) or (c.usertype > 0 and s.usertype = c.usertype)) left outer join dbo.systypes x on (x.type = s.type and s.usertype >=100 and x.usertype = (select min(w.usertype) from dbo.systypes w where w.type=x.type)) left outer join dbo.syscomments z on (z.id = o.id and z.number = c.colid) left outer join dbo.sysproperties b on (c.id=b.id and c.colid=b.smallid) where c.usertype >= 0 and objectproperty(c.id,N'IsUserTable')=1 and c.name is not NULL [ and u.name = %.q:SCHEMA%] [ and o.name=%.q:TABLE%] order by 1, 2, 3 ========================================== 接下来对这段脚本进行分析: 在上面的 DBMS Properties 窗口中点击【确定】按钮,在弹出的确认窗口中确认保存修改, 作者:姜江 error 499 对前面创建的数据库进行反向工程一个新的模型(关于如何反向工程生成一个新的模型,请参考: 3.8.2 反向工程产生模型),可以得到以下结果,如图 7-46 所示。 图 7-46 将数据库中列的描述反向工程为列的 Comment 产生的表 可以发现,“{}”中的变量 Comment 能够通过 CONVERT(varchar(128),b.value)的从数据库中 的系统表 systemproperties 中获得正确的 Comment 值。起初,笔者在研究该问题时,直接使用了 b.value,但是得到的 Comment 为空,经过尝试之后才发现系统表 systemproperties 中的 value 为 binary 类型,而 PowerDesigner 中 Comment 至少应该是字符串类型,如果直接使用 b.value,则不 能得到正确的结果,所以使用了 convert 对数据类型进行转化,才得到了正确的结果。 在上图中,还可以看出,列的 Name 和 Code 完全相同,都为英文,这也是许多读者困惑的问 题:如何在数据库和模型之间保持 Name 的同步。 这个问题和“如何把 PowerDesigner 中的 Name 作为注释导入到 SQL Server 2000 的数据库 中”是有很大的关系的,因为,只有把 Name 导入到 SQL Server 2000 中,才有可能在反向工程时 将 Name 导回来,才能保持 Name 之间的同步。 对 PowerDesigner 9.5 的 DBMS 脚本文件熟悉的朋友可能会想到:生成数据库的时候,可以将 模型中列的Name生成到数据库的Comment中而在反向工程的时候,在上段脚本中用COLNNAME (列的 Name 在 PowerDesigner 9.5 中的系统变量)代替 Comment,会不会能够得到中文的 Name (也可能是英文)呢? 下面先介绍如何将 Name 作为注释导入到 SQL Server 2000 中,根据前面的解决方案,只需要 将表的注释的变量换为表的 name 的变量,将列的注释的变量换为列的 name 的变量即可,具体做 法如下: 将 TableComment 的 Value 编辑为以下脚本: ========================================== [execute ]sp_addextendedproperty N'MS_Description', N%.q:TNAME%, N'user', N%.q:OWNER%, N'table', N%.q:TABLE% ========================================== 将 ColumnComment 的 Value 编辑为以下脚本: 作者:姜江 error 500 ========================================== [execute ]sp_addextendedproperty N'MS_Description', N%.q:COLNNAME%, N'user', N%.q:OWNER%, N'table', N%.q:TABLE%, N'column', N%.q:COLUMN% ========================================== 图 7-47 表实例 选择如图 7-47 所示的表生成脚本,生成的脚本如下所示(仅取出了和注释有关的部分,注意, 表名称前面还包括用户名 dbo,否则增加备注的语句可能不能正确执行): ========================================== /*==============================================================*/ /* DBMS name: Microsoft SQL Server 2000 */ /* Created on: 2004-5-9 17:08:40 */ /*==============================================================*/ /*==============================================================*/ /* Table: country */ /*==============================================================*/ create table dbo.country ( countryID numeric(6) identity, countryName varchar(20) not null, continent varchar(20) null, constraint PK_COUNTRY primary key (countryID) ) go execute sp_addextendedproperty N'MS_Description', N'国家', N'user', N'dbo', N'table', N'country' 作者:姜江 error 501 go execute sp_addextendedproperty N'MS_Description', N'国家ID', N'user', N'dbo', N'table', N'country', N'column', N'countryID' go execute sp_addextendedproperty N'MS_Description', N'国家名称', N'user', N'dbo', N'table', N'country', N'column', N'countryName' go execute sp_addextendedproperty N'MS_Description', N'所属洲', N'user', N'dbo', N'table', N'country', N'column', N'continent' go ========================================== 事实上PowerDesigner自身提供了一种更为简便的操作方法用于将name生成为备注,在 Database Generation窗口中,如图 7-48所示,可以在不修改TableComment和ColumnComment的情 况下选中手形状图标所指的位置(Generate name in empty comment)的复选框,表明如果不存 在注释,则用name代替。 图 7-48 选择“Generate name in empty comment”复选框 在这个例子中,使用该选项生成的建库脚本同前面方法生成的脚本完全相同,但是,这里有 两点需要注意:  只有当 DBMS的 Resource文件中存在相应的 TableComment 或者 ColumnComment 等 Item 时,各对象 comment 复选框和该复选框才可用(否则为灰化状态) 作者:姜江 error 502  由于该选项为“注释不存在的情况下才用 Name 代替”,如果选中该选项,则表明最终在 数据库中生成的注释有可能是“实际的注释”,也可能是“Name”,因此:  如果读者希望注释全部都采用“Name”,则采取前面的那种方法(替换 Resource 文 件中的 COMMENT 变量的方法)  如果读者希望注释全部是“真正的注释”,最好不要选中该复选框,并且采用如下设 置: 将 TableComment 的 Value 编辑为以下脚本: ========================================== [execute ]sp_addextendedproperty N'MS_Description', N%.q:COMMENT%, N'user', N%.q:OWNER%, N'table', N%.q:TABLE% ========================================== 将 ColumnComment 的 Value 编辑为以下脚本: ========================================== [execute ]sp_addextendedproperty N'MS_Description', N%.q:COMMENT%, N'user', N%.q:OWNER%, N'table', N%.q:TABLE%, N'column', N%.q:COLUMN% ========================================== 上述脚本可以保证表和列在存在注释时,正确将注释生成到数据库中(注意,这里以 SQL Server 2000 中表和列为例,读者可反复实验,认真体会,尽可能精通掌握这几种方法的区别)。 执行前面刚刚生成的建库脚本后,再执行下面脚本(获得所有用户表的非空的描述备注信息): ========================================== select object_name(a.id) as 表名,a.name as 字段名,b.value as 说明 from syscolumns a left join sysproperties b on a.id=b.id and a.colid=b.smallid where objectproperty(a.id,N'IsUserTable')=1 and b.value is not null ========================================== 返回结果如图 7-49 所示,可以发现 Name 已经被转化为 SQL Server 2000 中的注释(备注), 读者也可以通过 SQL Server 2000 的企业浏览器进行查看。 图 7-49 查询显示结果 接下来,就要实现反向工程,确保数据库中备注和也可以反向工程到模型中。 作者:姜江 error 503 我们不防尝试一下,使用:{OWNER, TABLE, S, COLUMN, COMPUTE, NOTNULL, IDENTITY, DOMAIN,COLNNAME},但结果却和直接使用 b.value 一样,完全不能将 comment 到 COLNNAME 中,列的 Name 仍然和 Code 完全一样。 为什么这种办法不可行呢? 根据网友 jerrys 的回答:如果想改变这种状况,必须利用 PowerDesigner 的扩展属性。将表 的名称与字段等信息保存到扩展属性表中,逆向时先逆向表然后再进行扩展属性的逆向。 根据这种思路,为列创建一个扩展属性,在 DBMS Properties 窗口中,选择【Profile】→ 【Column】,在 Column 上(如果这里没有 Column 项,则在 Profile 上点击鼠标右键,在弹出的菜 单中选择 Add Metaclasses,在弹出选择窗口中选择 Column,点击【确定】按钮。)点击鼠标右键, 在弹出的菜单中选择【New】→【Extended Attributes】,新建扩展属性 Name 为 NAME_extended, 选择数据类型为 String,如图 7-50 所示。 图 7-50 为列创建扩展属性 图 7-51 设置该扩展属性的值 定义扩展属性后,将:{OWNER, TABLE, S, COLUMN, COMPUTE, NOTNULL, IDENTITY, DOMAIN,COMMENT}中的 COMMENT 替换为 NAME_extended,反向工程生成的模型中,进入 作者:姜江 error 504 列的属性窗口,点击 Extended Attributes 属性页,发现可以将 Comment 正确反向工程到扩展属性 中,如图 7-51 所示。 此时,我们可以尝试在上述{OWNER, TABLE, S, COLUMN, COMPUTE, NOTNULL, IDENTITY, DOMAIN, NAME_extended}中加入 COLNNAME,在 select 语句中,复制一份 CONVERT(varchar(128),b.value),修改后的脚本如下所示。 ========================================== {OWNER, TABLE, S, COLUMN, COMPUTE, NOTNULL, IDENTITY, DOMAIN,COLNNAME,NAME_extended} select u.name, o.name, c.colid, c.name, z.text, case (c.status & 8) when 8 then 'NULL' else 'NOTNULL' end, case (c.status & 128) when 128 then 'identity' else '' end, case when (s.usertype < 100) then '' else s.name end, CONVERT(varchar(128),b.value), CONVERT(varchar(128),b.value) from dbo.sysusers u join dbo.sysobjects o on (o.uid = u.uid) join dbo.syscolumns c on (c.id = o.id) join dbo.systypes s on ((c.usertype = 0 and s.xtype = c.xtype) or (c.usertype > 0 and s.usertype = c.usertype)) left outer join dbo.systypes x on (x.type = s.type and s.usertype >=100 and x.usertype = (select min(w.usertype) from dbo.systypes w where w.type=x.type)) left outer join dbo.syscomments z on (z.id = o.id and z.number = c.colid) left outer join dbo.sysproperties b on (c.id=b.id and c.colid=b.smallid) where c.usertype >= 0 and objectproperty(c.id,N'IsUserTable')=1 and c.name is not NULL [ and u.name = %.q:SCHEMA%] [ and o.name=%.q:TABLE%] 作者:姜江 error 505 order by 1, 2, 3 ========================================== 如果将数据库反向工程到新的模型,反向工程后的图形模型如图 7-52 所示。 图 7-52 反向过程生成的表 可以发现,尽管我们没有使用扩展属性“NAME_extended”转化为 COLNNAME,但在加入 该扩展属性后,问题就得到了解决。笔者认为,之所以出现这种情况,是因为 PowerDesigner 在 生成数据库的时候不会将列或者表的 Name 生成到 DBMS 中,因此,在反向工程时,也就默认不 可以使用 COLNNAME 或者 TNAME 等和 Name 相关的变量,而定义同类型的扩展属性后,使得 反向工程使用的变量整体得到扩展,当然也就包括 COLNNAME 或者 TNAME 等和 Name 相关的 变量。 尽管这种定义扩展属性的方法使得问题得到了解决,笔者对此也仍有所不解,毕竟这种理解 思路没有在 Sybase 的官方文档上出现过,因此仅供参考。 如果是反向工程到现有的模型,则弹出模型合并窗口,如图 7-53 所示(读者的软件中可能会 因为使用的模型不同,弹出的窗口的显示内容也会有所不同): 图 7-53 模型比较窗口 观察上图,则可以通过以下模型合并窗口清晰的看到修改脚本后产生的作用,点击【确定】 按钮,生成正确的模型,可以将数据库中的 Comment 反向工程到 PowerDesigner 9.5 中 PDM 的 Name 上。现实的使用过程中,情况也许会不同,但这仅仅是希望提供一种解决问题的思路,读 者在看这部分内容的时候就是从问题着手一步步学会如何解决问题。当然,遇到特定的问题,可 作者:姜江 error 506 能还需要特定的解决方法,但是了解解决问题的方法却是需要提高的最根本的能力。 7.12 问题十二 问题: 我使用的是 PowerDesigner 9.5 和 10,我用 PDM 为数据库建模,在对象(表或者视图等)的 Preview 的注释的颜色是亮绿色,很难辨认,即 PowerDesigner 内部的文本编辑器的注释颜色不 方便使用,举例如下: /*==============================================================*/ /* Table: 学生编号 */ /*==============================================================*/ 讨论: 可以通过修改注册表解决这个问题:\HKEY_CURRENT_USER\Software\Sybase\PowerDesigner Trial 10\Controls\Editor,刚开始安装 PowerDesigner 的时候 Controls\Editor 下面为空,不 包含任何键,这些键是在使用 PowerDesigner 的语法编辑器(如 Preview 或者脚本编辑器等)的 时候动态创建。因此,我们可以手动建立键,并设定键值。 在注册表编辑器中查找:\HKEY_CURRENT_USER\Software\Sybase\PowerDesigner Trial 10\Controls\Editor 或者\HKEY_CURRENT_USER\Software\Sybase\PowerDesigner 9\Controls\Editor(视版本而定) 可以发现,Editor 条目下又包含 C# Files、SQL Files、Default、XML Files 等类型的文件, 每一种文件类型都包含以下几种对象的颜色分类:  Comment  Keyword  Number  Operator  String  Text  Text Selection 每种类型都可以修改前景色(Foreground color)和背景色(Background color),但一般情况 下最好不要修改背景色,可以在这些条目下创建相应的键,并且修改键值,即可满足用户的特定 要求。 解决方案: 在 Windows 下选择【开始】→【运行】,在弹出的对话框中输入“Regedit”打开注册表编辑 器,由于该例中我们这里需要修改的是 SQL 脚本的 Comment(注释)的颜色,所以选择 \HKEY_CURRENT_USER\Software\Sybase\PowerDesigner Trial 10\Controls\Editor\SQL Files\Color Groups\Comment,在该项右方新建一个 DWORD 类型的键,键的名称为“Foreground”, 作者:姜江 error 507 并且设定键值(16 进制)为“0000FF”(Red),也可以是 FF0000 (Blue), ec00c000 (Green), 这里读者根据需要自行设定。如图 7-54 所示。 图 7-54 修改注册表中“Foreground”的值 7.13 问题十三 问题: 为什么我打开别人发给我的 PowerDesigner 模型时,所有的表的图形都显示为空的图符,而 看不到信息,但表之间的连接可以看到。而且进入表的属性窗口却可以看到表的列以及其他属性, 好像仅仅是不行不能正确显示,其他信息都完好无损。如图 7-55 所示。 图 7-55 不能正确显示模型图形 作者:姜江 error 508 解答: 这是因为该用户使用了低版本的 PowerDesigner 打开较高版本的 PowerDesigner 的模型文件而 导致的,这种情况经常发生在用 PowerDesigner 9.0 打开 PowerDesigner 9.或者 PowerDesigner 10 中 创建的模型时,PowerDesigner Viewer 9.0 不能打开 PowerDesigner 9.5 或 10 的模型。而 PowerDesigner 9.5 和 PowerDesigner 10 之间则不存在这个问题。 因此,遇到该问题的读者只需要尽可能选择相同版本,即可解决这个问题。 批注 [e36]: 最后一张附录删除
还剩507页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 3 人已下载

下载pdf

pdf贡献者

pc6c

贡献于2013-09-04

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf