第三周翻译(《Database.System.Concepts》7.7 Entity-Relationship Design Issues)

本文探讨E-R模型设计中常见的问题,包括实体与属性的区别、联系集与实体集的应用、联系属性布局等,并提供实用的设计建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Tip:参考前人翻译

实体——联系设计问题

  针对实体集和联系集的概念并不明确的现象,并且定义一组实体和它们的相互联系可能会有许多不同的方式。本节我们讨论E-R数据库模式设计中的一些基本问题。设计过程将在7..10节更详细地讨论。

7.7.1 用实体集还是用属性

  考虑到具有新增属性phone_number的实体集instructor(如图7-17a)。很容易就会把电话作为一个单独的实体,具有属性phone_number和location;而地点可能是电话所处于的办公室或者家中,所以移动电话就可以用“移动”来备注。但如果我们采用这样的观点,那么我们就不给instructor增加属性phone_number,相反的,我们可以创建:

   实体集phone,具有属性phone_number和location。

   联系集inst_phone,表示老师和他们拥有的电话之间的关系。

   这种方法如图7-17b。

 

 

   那么,老师的两个定义之间又有什么主要差别?把电话看成一个属性,phone_number表示每个老师刚好有一个电话号码与他相关。而如果把电话当成一个实体phone,允许每个老师可以有若干个电话号码(包括零)和他相关联。同样的,也可以简便地将phone_number定义为有多个值的属性,从而允许每个老师有多个电话。

  而两种方法的主要区别在于,当一个人可能希望保存关于电话的其他信息时,如电话的位置,或者类型(移动电话、视频电话或者普通的老式电话),或者想共享该电话的所有成员时,把电话当成一个实体是一种比较好的建模方法。所以,把电话看成一个实体比把它当成一个属性的方式更具有通用性;而当通用的这种方法更为有效时,这种定义形式就更加合适了。


  相反的,把(一位老师的)name属性看做一个实体就不是很合适,把name作为一个实体,本身就不具有说服力(和电话的情况相反)。所以,合适的做法就是把name当成instructor实体集的一个属性。

  从上述的这个例子就提出两个问题:由什么构成了属性?而又是什么构成了实体集?令人遗憾的是,关于这两个问题并不是那么简单就能回答的。因为区别它们主要依靠于被建模的实际的企业的结构,和被商议的属性的相关定义。

  一个常见的错误就是错用一个实体集的主键作为另一个实体集的属性,而不是用联系。例如,虽然每位老师只能指导一名学生,但将student的ID当成instructor的属性也是不正确的,而用advisor联系代表学生和老师之间的关系才是正确的方法,因为这样可以更准确地表示出两者之间的联系而不是简单将这种关系隐藏在属性中。

  人们经常犯的与此相关的另外一个错误是把相关实体集的主键属性当成联系集的属性。例如,ID(student的主键属性)和ID(instructor的主键)不能在advisor联系中作为属性出现,因为在联系集中就已经包含了这些主键的属性,所以这样的做法是不对的。

7.7.2 用实体集还是用联系集

  一个对象最好被表示为实体集还是联系集并不总是显而易见的。如图7-15所示,我们用takes联系集对学生选择课程(某一次开课)建模。另一种方式是想象对于每一个学生选的每门课程有一个课程-注册记录。那么,我们用一个叫registration的实体集代表课程-注册记录。每个registration实体恰好与一个学生和一次开课相关联,所以,我们就会有两个联系集,一个将课程-注册记录和学生相关联,另一个把课程-注册记录和课程关联。如图7-18所示,我们将图7-15中section和student实体集之间的takes联系集用一个实体集和两个联系集替代:

  Registration,代表课程-注册记录的实体集。

  Section_reg,关联registration和course的联系集。

  Student_reg,关联registration和 student的联系集。

注意,我们使用双线表示registration实体全部参与。

 

图7-15和图7-18的方法都准确地表达了大学的信息,但是使用takes的方法更紧凑也更可取。然而,如果注册办公室通过课程—注册记录与其他信息相关联,那么最好还是让它本身作为一个实体。

  在决定用实体集还是联系集时可采用的一个原则就是,当描述发生在实体间的行为时采用联系集。这一方法在决定是否将某些属性表示为联系可能会更合适时,很有用。

  而我们以后会看到,当从E-R模式中创建关系模式时,这些属性可能会出现在从advisor联系集创建出的模式中,但是,它们并不应该出现在advisor联系集中。

7.7.3 二元还是n元联系集

  数据库中的联系通常都是二元的情况,但在一些看来非二元的联系实际上可以用多个二元联系更好地表示。例如,可以创建一个三元联系parent,将一个孩子和他/她的母亲和父亲相关联。然而,这一联系也可以用两个二元联系分别来表示,即mother和father,分别将孩子与他/她的母亲和父亲相关联。使用mother和father两个联系使我们可以记录孩子的母亲,即使我们不知道父亲是谁,而对于这种情况三元联系parent中必然会有一个空值。所以在这个例子中用二元联系更好。

  实际上,一个非二元的(n元,n>2)联系集总可以用一组不同的二元联系集来替代。简单起见,考虑一个抽象的三元(n=3)联系集R,它将实体集A、B和C联系起来。用实体集E替代联系集R,并创建三个联系集,如图7-19所示;

  Ra,关联E和A。

  Rb,关联E和B。

  Rc,关联 E和C。

  而如果联系集R有属性,那么将这些属性赋给实体集E:进一步,为E创建一个特殊的标识属性(因为它必须能够通过其属性值来区别实体集中的各个实体)。针对联系集R中的每个联系(ai,bi,ci),在实体集E中创建一个新的实体ei。然后,在三个新联系集中,分别插入新联系如下;

  在Ra中插入(ei,ai)。

  在Rb中插入(ei,bi)。

  在Rc中插入(ei,ci)。


  那么就可以将这一过程直接推广到n元联系集的情况。因此,在概念上可以限制E-R模型只包含二元联系集。然而,这种限制情况并不总是令人满意的。

  对于为表示联系集而间接创建的实体集,我们可能会为其创建一个标识属性。该标识属性和额外所需的那些联系集增加了设计的复杂程度以及对总的存储空间的需求(我们将在7.6节看到这一点)。

  N元联系集可以更清晰地表示几个实体集参与单个联系集。

  但有可能无法将三元联系上的约束转变为二元联系上的约束。例如,考虑一个约束,表明R是从A、B到C多对一的;也就是,来自A和B的每一对实体最多与一个C实体关联。这种约束就不能用联系集Ra,Rb和Rc上的基数约束来表示。

  考虑7.2.2节中的联系集proj_guide,它关联instructor、student和project。不能直接将proj_guide拆分为instructor和project之间的二元联系和student和project之间的二元联系。如果这么做,可以记录老师Kate同学生Shankar和Zhang一起参与项目A和B;但是无法记录Katz同Shankar一起参与项目A并且同Zhang一起参与项目B,而不是同Zhang一起参与项目A或者同Shangkar一起参与项目B。


  联系集proj_guide 可以通过创建一个如上所述的新实体集来拆分为二元联系。但是,这么做却不是很自然。

7.7.4 联系属性的布局

  一个联系的映射基数比率会影响联系属性的布局。因此,一对一或一对多联系集的属性可以放到一个参与该联系的实体集中,而不是放到联系集中。例如,我们指明advisor是一个一对多的联系集,也就是一个老师可以指导多个学生,但每个学生只能有一个导师。在这种情况下,表示老师何时成为学生导师的属性date可以与student实体集相关联,如图7-20所示。(为了保持图例简单,只显示了两个实体集的部分属性)。由于每个student实体最多和一个instructor实例相联系。因此将属性date放在student实体集中和将属性date放在advisor联系集中具有相同的含义。一对多联系集的属性只能重置到参与联系的“多”方的实体集中。而对于一对一的联系集,联系的属性可以放到任意一个参与联系的实体中。

  设计时把描述性属性作为联系集的属性还是实体集的属性这一决定,应该反映出被建模对象的特点。设计者可以选择保留date作为advisor的属性,以直观地表明指导关系的日期,而不是学生校内状态的其他一些方面(例如,被大学录取的日期)。

  属性位置的选择在多对多联系集中体现得更加清楚。回到刚才的例子,让我们指出可能更符合实际的情况,定义advisor为一个多对多联系集,表明一个老师可以指导一个或多个学生,而一个学生可以被一个或者多个教师辅导。而如果想要表示一个特定的老师成为一个特定学生的导师的日期,date则必须作为联系集advisor的属性,而不是任何一个参与的实体集的属性。例如,如果把date作为student的属性,则我们无法知道哪个教师在该特定日期成为他的导师。当一个属性是由参与的实体集联合确定而不是由单独的某个实体集确定时,该属性就必须放到多对多联系集中。图7-3给出了作为联系属性的date的位置。而为了图例的简单,只显示了两个实体集的部分属性。

目 录 译者序 第7版序言 第一部分 基础知识 第1章 数据库管理概述 1 1.1 引言 1 1.2 什么是数据库系统 3 1.3 什么是数据库 6 1.4 为什么用数据库 10 1.5 数据独立性 12 1.6 关系系统及其他 15 1.7 小结 17 练习 17 参考文献和简介 19 部分练习答案 19 第2章 数据库系统体系结构 22 2.1 引言 22 2.2 三级体系结构 22 2.3 外模式 24 2.4 概念模式 26 2.5 内模式 26 2.6 映象 27 2.7 数据库管理员 27 2.8 数据库管理系统 28 2.9 数据通信管理器 31 2.10 客户/服务器体系结构 31 2.11 工具 33 2.12 分布式处理 33 2.13 小结 35 练习 35 参考文献和简介 36 第3章 关系数据库介绍 38 3.1 引言 38 3.2 关系模型概述 38 3.3 关系和关系变量 41 3.4 关系的含义 42 3.5 优化 44 3.6 数据字典 45 3.7 基本关系变量和视图 46 3.8 事务 49 3.9 供应商和零件数据库 49 3.10 小结 51 练习 52 参考文献和简介 53 部分练习答案 54 第4章 SQL概述 55 4.1 引言 55 4.2 综述 56 4.3 目录 58 4.4 视图 59 4.5 事务 59 4.6 嵌入式SQL 59 4.7 SQL是不完美的 66 4.8 小结 66 练习 67 参考文献和简介 68 部分练习答案 73 第二部分 关系数据模型 第5章 域、关系和基本关系变量 77 5.1 引言 77 5.2 域 79 5.3 关系值 86 5.4 关系变量 90 5.5 SQL的支持 93 5.6 小结 96 练习 97 参考文献和简介 98 部分练习答案 101 第6章 关系代数 106 6.1 引言 106 6.2 关系封闭性 107 6.3 语法 109 6.4 语义 110 6.5 举例 117 6.6 关系代数的作用 119 6.7 附加的操作符 120 6.8 分组与分组还原 125 6.9 关系比较 127 6.10 小结 128 练习 129 参考文献和简介 131 部分练习答案 133 第7章 关系演算 140 7.1 引言 140 7.2 元组演算 141 7.3 举例 147 7.4 关系演算与关系代数的比较 149 7.5 计算能力 152 7.6 域演算 153 7.7 SQL语言 155 7.8 小结 162 练习 163 参考文献和简介 165 部分练习答案 167 第8章 完整性 179 8.1 引言 179 8.2 类型约束 180 8.3 属性约束 181 8.4 关系变量约束 182 8.5 数据库约束 182 8.6 黄金法则 183 8.7 静态约束和动态约束 184 8.8 码 185 8.9 SQL对完整性的支持 191 8.10 小结 194 练习 194 参考文献和简介 196 部分练习答案 201 第9章 视图 209 9.1 引言 209 9.2 视图的用途 211 9.3 视图检索 213 9.4 视图更新 214 9.5 快照 225 9.6 SQL对视图的支持 226 9.7 小结 227 练习 228 参考文献和简介 229 部分练习答案 232 第三部分 数据库设计 第10章 函数依赖 238 10.1 引言 238 10.2 基本概念 239 10.3 平凡的函数依赖和非平凡的函数 依赖 241 10.4 依赖集的闭包 241 10.5 属性集的闭包 242 10.6 最小函数依赖集 244 10.7 小结 245 练习 246 参考文献和简介 247 部分练习答案 249 第11章 进一步规范化Ⅰ:1NF、2NF、 3NF和BCNF 252 11.1 引言 252 11.2 无损分解和函数依赖 254 11.3 第一、第二和第三范式 257 11.4 保持函数依赖 262 11.5 BOYCE/CODD范式 264 11.6 具有关系值属性的关系变量 268 11.7 小结 270 练习 270 参考文献和简介 272 部分练习答案 274 第12章 进一步规范化Ⅱ:高级范式 282 12.1 引言 282 12.2 多值依赖与第四范式 282 12.3 连接依赖与第五范式 285 12.4 规范化过程小结 289 12.5 逆规范化 291 12.6 正交设计 292 12.7 其他的规范化形式 295 12.8 小结 296 练习 296 参考文献和简介 297 部分练习答案 302 第13章 语义建模 306 13.1 引言 306 13.2 总体方法 307 13.3 E/R模型 309 13.4 E/R图 312 13.5 基于E/R模型的数据库设计 313 13.6 简单分析 317 13.7 小结 319 练习 320 参考文献和简介 321 第四部分 事务管理 第14章 恢复 333 14.1 引言 333 14.2 事务 334 14.3 事务恢复 335 14.4 系统恢复 337 14.5 介质恢复 338 14.6 两阶段提交 338 14.7 SQL对事务的支持 339 14.8 小结 340 练习 341 参考文献和简介 341 部分练习答案 345 第15章 并发 347 15.1 引言 347 15.2 三个并发问题 347 15.3 锁 349 15.4 重提三个并发问题 350 15.5 死锁 352 15.6 可串行性 353 15.7 隔离级别 354 15.8 意向锁 355 15.9 SQL的支持 357 15.10 小结 358 练习 359 参考文献和简介 360 部分练习答案 365 第五部分 高级专题 第16章 安全性 369 16.1 引言 369 16.2 自主存取控制 371 16.3 强制存取控制 375 16.4 统计数据库 377 16.5 数据加密 381 16.6 SQL的支持 384 16.7 小结 386 练习 387 参考文献和简介 388 部分练习答案 390 第17章 优化 394 17.1 引言 394 17.2 一个启发性的例子 395 17.3 查询处理概述 396 17.4 表达式变换 399 17.5 数据库统计信息 403 17.6 分而治之的策略 404 17.7 关系操作的实现算法 406 17.8 小结 410 练习 411 参考文献和简介 413 部分练习答案 430 第18章 信息空缺 432 18.1 引言 432 18.2 3VL方法概述 433 18.3 上述方案所造成的某些结果 437 18.4 空值和码 440 18.5 外连接 442 18.6 特殊值 444 18.7 SQL的支持 444 18.8 小结 447 练习 448 参考文献和简介 449 部分练习答案 452 第19章 类型继承 454 19.1 引言 454 19.2 类型的层次结构 457 19.3 多态性和可置换性 459 19.4 变量与赋值 462 19.5 约束特化 465 19.6 比较 467 19.7 操作、版本和签名 470 19.8 一个圆是一个椭圆吗 473 19.9 约束特化—再次讨论 476 19.10 小结 478 练习 479 参考文献和简介 480 部分练习答案 481 第20章 分布式数据库 484 20.1 引言 484 20.2 一些预备知识 484 20.3 十二个目标 487 20.4 分布式系统面对的问题 493 20.5 客户/服务器系统 502 20.6 DBMS独立性 504 20.7 SQL的支持 508 20.8 小结 509 练习 509 参考文献和简介 510 第21章 决策支持 518 21.1 引言 518 21.2 决策支持的特征 519 21.3 决策支持的数据库设计 520 21.4 数据准备 525 21.5 数据仓库和数据集市 527 21.6 联机分析处理 530 21.7 数据挖掘 535 21.8 小结 536 练习 537 参考文献和简介 538 部分练习答案 540 第22章 时态数据库 541 22.1 引言 541 22.2 时态数据 542 22.3 问题是什么 544 22.4 时间间隔 548 22.5 间隔类型 549 22.6 间隔上的标量操作符 551 22.7 间隔上的聚集操作符 551 22.8 与间隔有关的关系操作符 552 22.9 间隔上的约束 557 22.10 间隔上的更新操作符 559 22.11 关于数据库设计 560 22.12 小结 562 练习 563 参考文献和简介 563 部分练习答案 565 第23章 基于逻辑的数据库 567 23.1 引言 567 23.2 综述 567 23.3 命题演算 569 23.4 谓词演算 572 23.5 数据库的证明理论观点 577 23.6 演绎数据库系统 580 23.7 递归查询过程 583 23.8 小结 588 练习 589 参考文献和简介 590 部分练习答案 596 第六部分 对象和对象/关系数据库 第24章 对象数据库 599 24.1 引言 599 24.2 对象、类、方法和消息 602 24.3 进一步的分析 605 24.4 一个详实的例子 611 24.5 混合性问题 618 24.6 小结 624 练习 626 参考文献和简介 627 部分练习答案 634 第25章 对象/关系数据库 637 25.1 引言 637 25.2 第一个根本性错误 639 25.3 第二个根本性错误 644 25.4 实现上的问题 645 25.5 真正融合的好处 647 25.6 小结 648 参考文献和简介 649 附 录 附录A SQL表达式 657 附录B SQL3概览 666 附录C 缩略语和符号 678
<think>我们正在解决的是在Webpack项目中引入pdfjs-dist时出现的模块解析错误,错误信息通常为“Moduleparse failed: Unexpectedtoken”。这通常是由于Webpack配置中缺少对ES6+语法的支持(如可选链操作符`?.`)导致的。pdfjs-dist从2.4版本开始使用ES6语法,而Webpack默认可能无法处理这些新语法。根据引用[2]和引用[4],我们可以通过配置Babel插件来支持这些新语法。引用[4]提到了使用三个Babel插件:`@babel/plugin-proposal-optional-chaining`(可选链)、`@babel/plugin-proposal-nullish-coalescing-operator`(空值合并)和`@babel/plugin-proposal-private-methods`(私有方法)。这些插件可以解决ES6+语法的问题。解决步骤:1.安装所需的Babel插件:```bashnpm install--save-dev @babel/plugin-proposal-optional-chaining@babel/plugin-proposal-nullish-coalescing-operator @babel/plugin-proposal-private-methods```2.在Webpack配置中,为pdfjs-dist的代码添加Babel加载器(通常是在`module.rules`中增加一条规则)。我们只针对pdfjs-dist进行转译,因为其他代码可能已经由之前的Babel配置处理了。3.配置Webpack的规则,排除node_modules中其他模块(除了pdfjs-dist),因为我们只需要转译pdfjs-dist。具体配置示例(在webpack.config.js中):```javascriptmodule:{rules:[// ...其他规则{test:/\.js$/,//只对pdfjs-dist进行转译include: /node_modules\/pdfjs-dist/,use: {loader: 'babel-loader',options: {presets:['@babel/preset-env'],plugins:['@babel/plugin-proposal-optional-chaining','@babel/plugin-proposal-nullish-coalescing-operator','@babel/plugin-proposal-private-methods']}}}] }```4.如果项目中还没有安装babel-loader和@babel/preset-env,需要安装:```bashnpminstall --save-devbabel-loader @babel/core@babel/preset-env```5.如果问题仍然存在,尝试删除node_modules并重新安装依赖(引用[3]提到):```bashrm -rf node_modulesnpminstall```另外,引用[1]和[2]的错误信息都指向了pdf.js文件中的特定语法(可选链操作符),所以上述配置应该能解决问题。注意:如果项目本身已经配置了Babel,并且已经排除了node_modules,那么我们需要特别将pdfjs-dist包含进来(如上述配置中的`include`属性)。如果使用Vue CLI或CreateReact App等脚手架工具,可能需要通过其他方式配置(例如在VueCLI中可以使用`transpileDependencies`选项)。对于Vue CLI项目,可以在vue.config.js中配置: ```javascriptmodule.exports= {transpileDependencies:['pdfjs-dist'] }```对于CreateReact App,通常不需要额外配置,因为默认情况下它会编译node_modules中的模块?但事实上,CreateReact App默认不编译node_modules。因此,如果遇到此问题,可能需要使用react-app-rewired来覆盖配置,或者将pdfjs-dist的ES5版本(pdfjs-dist/legacy/build/pdf)引入。另一种方案:使用pdfjs-dist的legacy版本(ES5语法)。在引入时使用: ```javascriptimport *as pdfjsLibfrom 'pdfjs-dist/legacy/build/pdf'; ```但这样可能会失去一些新特性,所以推荐使用Babel转译。总结:通过配置Webpack的Babel加载器专门针对pdfjs-dist进行转译,并添加必要的插件,即可解决该问题。</think>### 解决 PDF.js 在 Webpack 中的模块解析错误 #### 问题原因分析 当使用 `pdfjs-dist` 时出现的 `Module parse failed: Unexpected token` 错误,通常是由于: 1. **ES6+ 新语法支持问题**:PDF.js 2.5+ 使用了可选链操作符(`?.`)、空值合并运算符(`??`)等ES2020语法[^2] 2. **Webpack 配置缺失**:默认配置无法处理这些新语法 3. **Babel 插件缺失**:项目缺少必要的语法转换插件[^4] --- #### 完整解决方案 ##### 步骤1:安装必要依赖 ```bash npm install --save-dev @babel/plugin-proposal-optional-chaining npm install --save-dev @babel/plugin-proposal-nullish-coalescing-operator npm install --save-dev @babel/plugin-proposal-private-methods ``` ##### 步骤2:配置 Webpack (webpack.config.js) ```javascript module.exports = { // ...其他配置 module: { rules: [ { test: /\.m?js$/, include: /node_modules\/pdfjs-dist/, // 关键:只处理pdfjs-dist use: { loader: 'babel-loader', options: { plugins: [ '@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-nullish-coalescing-operator', '@babel/plugin-proposal-private-methods' ] } } } ] } }; ``` ##### 步骤3:配置 Babel (.babelrc 或 babel.config.js) ```json { "plugins": [ "@babel/plugin-proposal-optional-chaining", "@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-private-methods" ] } ``` ##### 备选方案:使用兼容版本 ```javascript // 在代码中引入 legacy 版本 import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf'; ``` --- #### 关键配置说明 1. **include 路径**: ```javascript include: /node_modules\/pdfjs-dist/ // 精确限定处理范围 ``` 避免全局处理 node_modules 影响性能[^3] 2. **插件作用**: - `@babel/plugin-proposal-optional-chaining`:转换 `obj?.property` 语法 - `@babel/plugin-proposal-nullish-coalescing-operator`:转换 `value ?? default` 语法 - `@babel/plugin-proposal-private-methods`:处理类私有方法 3. **版本兼容方案**: ```javascript // 在 package.json 中固定兼容版本 "pdfjs-dist": "2.4.456" // 最后支持 ES5 的版本 ``` --- #### 验证步骤 1. 删除现有依赖: ```bash rm -rf node_modules package-lock.json ``` 2. 重新安装: ```bash npm install ``` 3. 重启构建: ```bash npm run build ``` > **注意**:如果使用 Vue CLI/Create React App,需在项目根目录创建 `vue.config.js` 或修改 `react-scripts` 配置[^1] --- #### 常见错误排查 1. **版本冲突**: ```bash npm ls pdfjs-dist # 检查实际安装版本 ``` 2. **缓存问题**: ```bash npm cache clean --force ``` 3. **Loader 缺失**: 确保已安装 `babel-loader`: ```bash npm install --save-dev babel-loader @babel/core ``` [^1]: 删除 node_modules 重新安装可解决依赖不一致问题 [^2]: 可选链操作符(`?.`)是 Webpack 解析失败的主因 [^3]: 精确配置 include 路径避免全局处理 node_modules [^4]: 三个 Babel 插件组合可完整支持 PDF.js 的新语法 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值