数据库编程作业(“实验室PM”)

查尔默斯/GU TDA357/DIT621
LP32019年



上次修改时间:2019-03-13 12:33。由Thomas Hallgren、Jonas Duregárd和Aarne Ranta根据Chalmers和GU许多其他教师早年的规范修改

目的

本作业的目的是让你亲身体验为现实世界中类似的领域设计、构建和使用数据库。你会的了解数据库创建的各个方面,从了解域到使用来自外部应用程序的最终数据库。

作业提交和截止日期

要通过编程作业,您必须通过上描述的所有五项任务本页。你将以两人一组的形式完成作业。您需要组建小组,在Fire中注册,并在课程的第一周申请PostgreSQL帐户。

您必须通过消防报告系统提交解决方案,在该系统中您还可以看到每个任务的截止日期(链接主页).

您必须按照给定的最后期限。提交后,你的作业将被评分(“通过”或“拒绝”),你将收到关于您的解决方案的评论(针对任务1、2和3)。如果您的提交被拒绝,您可以修改解决方案并重新提交它。

要通过作业的最后一部分,您必须演示您的系统其中一位老师。任务4的文件必须上传到消防系统之后您已经演示了您的系统,并且之前任务4最后期限。

介绍

在本作业中,你将设计和构建一个数据库,以及一个前端应用程序,用于处理大学生和课程。你会的分四个不同的任务执行此操作:

  1. 构建:创建数据库(原型)并通过查询进行探索
  2. 设计:后退一步,使用更系统的方法重新设计数据库
  3. 用法:定义更多约束和触发器以维护数据库
  4. 接口:编写包装程序以允许在不显式使用SQL的情况下访问数据库

所有任务都相互关联。它们处理相同的数据库域,后续任务在不同程度上建立在早期任务的基础上。

对于每一项任务,你都会提交并获得对结果的反馈。一项任务中的错误可能会传播到下一项任务,明智的做法是交出尽早解决问题,以获得更多反馈机会。如果助手不忙,你也可以让他们在实验课上快速查看你的解决方案(不能保证你提交的解决方案被接受!)。

确保在阅读作业的完整描述之前因为我们对系统的要求必须影响您的初始设计也是如此。

域描述

你将在本作业中建模的领域是课程和一所大学的学生。以免任务过大未指定,您将在此处获得该域的描述在一定程度上限制了这个问题。请注意,所描述的域不是与Chalmers或GU相同。

您正在为其构建此系统的大学被组织为员工部门,如计算科学部(CS),以及为学生开设的学习课程,如计算机科学和工程计划(CSEP)。课程由各部门主办,但几个部门可能会在一个项目上合作,事实就是这样与CSEP合作,CSEP由CS部门和计算机工程(CE)。部门名称和缩写如下独特,节目名称也一样,但不一定是缩写。

每个学习项目都被进一步划分为分支,例如CSEP拥有计算机语言、算法、软件工程等分支。请注意,分支名称在给定程序中是唯一的,但不是必须跨越几个项目。例如,CSEP和自动化技术课程可以有一个名为交互设计。每个学习计划都有强制性的课程。对于每个分支,都有额外的必修课程拿那个树枝的学生必须阅读。分支还命名一组所有该分支的学生都必须阅读的推荐课程满足毕业要求的一定数额,见下文。

学生总是属于一个项目。学生必须选择一个在该课程中分支,并满足其毕业要求,为了毕业。通常学生会选择哪个分支他们的第四年,这意味着处于早期阶段的学生他们的研究可能还不属于任何分支。

课程由部门提供(例如CS提供数据库课程)。每个课程都有一个独特的六字符课程代码。任何学习课程的学生都可以阅读所有课程。一些课程可能对某些项目是强制性的,但对其他项目则不是。学生获得通过课程的学分,具体数字可能在课程(但所有学生获得相同数量的学分课程)。一些(但不是全部)课程对可能同时参加课程的学生。课程可以是分类为数学课程、研究课程或研讨会课程。并非所有课程都需要分类,有些课程可能有多个分类。大学偶尔会引入新的分类。有些课程有先决条件,即。允许学生注册之前必须阅读的其他课程到它。

学生需要注册课程才能阅读。成为如果允许注册,学生必须先满足所有先决条件为课程准备。学生不应该注册到课程,除非先修课程已经通过。它不应该学生可以注册他们所学的课程已经通过了。

如果课程已满,随后注册的学生将被放在等待列表。如果之前注册的学生之一决定退学,如果球场上有一个空位,那么这个空位就是送给等待时间最长的学生。当课程完成后,所有学生按照“U”、“3”、“4”、“5”的等级进行评分。获得“U”表示学生没有通过课程,而其他等级表示不同程度的成功。

研究管理员可以覆盖这两个课程先决条件要求和大小限制,并将注册的学生直接添加到当然。(注意:您不会为实现任何前端应用程序学习管理员,仅供学生使用。数据库必须仍然能够来处理这种情况。)

对于学生来说,要想毕业,他们必须满足一些要求首先完成。他们必须全部通过(至少三年级)他们所属学习计划的必修课程,以及他们必须选择的特定分支的必修课程。此外,他们还必须在为分支机构推荐的课程。此外,他们需要阅读并通过(至少)20学分的课程分类数学课程,10学分的研究类课程课程和一个研讨会课程。必修课程和推荐课程也像其他课程一样以某种方式进行分类,因此,如果课程的必修课之一也是研讨会课程,该课程的学生不需要阅读还有更多的研讨会课程。

系统规范

您将为上述域设计并实现一个数据库面向大学学生的前端应用程序。通过他们应该能够看到自己的信息的应用程序,注册课程和注销课程。

从形式上讲,您的应用程序应该具有以下模式:

任务1:构建数据库

您的任务是通过在数据库引擎中实现数据库模式来构建数据库的第一个版本(PostgreSQL)。本文件中给出了该零件的模式:数据库任务1的抽象架构

请注意,模式有点不完整,但这将在赋值的第二部分中修复。您应该使用实现模式创建表格声明

因此,您应该创建所有表,并在过程,您还应该插入基本检查,以确保只有有效的数据可以插入数据库中。无效数据的示例为等级“6”或一门学生人数为负数的课程。

创建表格后,应该用示例填充表格数据。通常,这是一个耗时但重要的部分数据库的开发。数据库中的数据顺序至关重要以正确验证其行为是否符合预期。表中应填充足够的数据,以便可以测试应用程序可以处理上面指定的各种操作。只是如果数据仍然不能测试所有部分,那么插入大量数据是没有用的数据库的。

然而,在本课程中,我们决定只为您提供一组应该有效的插件(可能需要稍作调整):插入.sql.请注意测试涵盖的各种拐角情况:

按照系统规范创建以下视图:

提示1:对每个列的数据进行查询,当它们都有效时,将它们放在WITH子句中,并使用(左)外部联接链将它们组合起来。

提示2:使用COALESCE公司将空值替换为0(例如。COALESCE(totalCredits,0)作为totalCredits。此外,请记住,将空值与任何东西进行比较都会得到UNKNOWN!

提示3:包含学生/分类/学分的查询可能会有用,其中每个学生通过的每个课程的每个分类都有一行。

确保视图使用正确的列名称!使用AS公司命名列。

测试文件运行测试.sql自动运行此分配的文件。文件输出.txt包含执行此操作的预期输出。运行文件(使用\我运行tests.sql在psql中),并确保输出与示例匹配(假设您使用提供的insert.sql文件),并且没有错误(行的顺序可能不同)。这并不能完美地保证您的代码能够正常工作,但它确实发现了一些常见的错误。

可交付成果:对于任务1,您应通过Fire提交以下文件:

注意,SQL代码应该是纯文本格式。确保PostgreSQL可以在提交文件之前在空数据库中执行文件。在提交的任何文件中都不要使用“删除所有内容”语句。

任务2:数据库设计

这个实验室的任务是回顾数据库在实验室1中实施,并检查我们应该如何完成。更准确地说,我们将

这项研究可能会产生许多有趣的结果:

E-R模型

首先创建一个E-R图,该图正确地建模了域描述以上。

你可以使用任何你喜欢的工具对于此任务,只要您将解决方案作为其中一个格式.png码,.jpg格式,.gif文件.pdf格式并作为纯文本文件中的模式(格式类似于task1.txt(任务1.txt)).我们建议您使用迪亚.

在这两种情况下,你都必须使用讲座中指定的翻译,并正确标记键和参考。

提示:如果您的图表不包含至少一个弱实体,至少一个ISA关系,以及至少一个多对多关系关系,你可能做错了什么。

功能依赖性

第二个任务是制定域中的所有函数依赖关系,并从中派生出有效的模式。这应该主要独立于E-R设计和task1.txt(任务1.txt).

提示:只要您自己确定了功能依赖项,Query Converter(主页上的链接)就可以自动执行大部分分析。当模式非常大时,速度可能会变慢,但您可以重新加载页面以终止进程。

提示:与任务1中的模式相比,最终模式应至少包含四个附加关系,以及至少三个UNIQUE约束(只有出于技术原因才需要一个约束,以启用一个约束来防止学生在错误的程序中选择分支)。

可交付成果:对于任务2,您应该通过Fire提交以下文件

验收标准:

任务3:触发器

当您的表和视图在任务2中实现时,下一个任务是创建两个触发器来处理注册和注销。下面是一段代码,让您开始第一次触发:

Postgresql触发器示例

但首先,您应该定义另一个视图可以由触发器和任务4中的应用程序使用:

当学生尝试注册课程时,该课程可能已经满了,在这种情况下,学生应该被列入候补名单为了那门课。当学生注销时,可能是因为现在有空间了对于等待名单中的一些学生,然后应该注册而不是课程。这类事情通常通过触发器处理。应编写两个触发器:

  1. 当学生试图注册已满的课程时,该学生是已添加到课程的等待列表中。确保检查学生如果可能的话,可以在添加到任一列表之前实际注册该课程不应该引发错误(使用提高例外情况).提示:域中规定了几个注册要求描述,以及一些类似的隐含描述,学生不可能两者兼而有之同时等待并注册同一课程。
  2. 如果学生没有注册课程已注册且不仅在等待名单上应该为该课程注册等待列表。注释:此只有在球场(球场)上确实有空位时才应该这样做可能由于管理员覆盖限制而导致过满并直接添加学生)。

您需要在视图上编写触发器注册而不是在表本身(视图是在上面的任务1中构建的)。(其中一个原因是我们“假装”您只有任务4中列出的权限表示无法在基础表中插入数据或从中删除数据直接。但即使我们解除了这一限制,还有另一个理由不这样做在底层表上定义这些触发器-您能找出原因吗?)

提示1:以增量方式编写触发器,首先创建一个注册触发器,它总是会给出错误并测试它是否有效,然后仅在学生已经注册(或等待)时才给出错误,否则进行注册,如果学生缺少先决条件,则使其给出不同的错误,然后,如果课程已满,则将学生放入等待列表,依此类推。

提示2:检查课程是否已满的一种方法是:计算使用该代码的课程数量以及超过其座位容量的学生人数。计数将为1或0(0表示没有限制或未超出限制)。

测试制作一个文件测试.sql使用插入和删除来测试触发器的所有情况。在每个插入/删除上写一个简短的注释(以--开头的行),说明测试的内容和预期结果(更改/错误)。

提示1:您的测试需要测试注册失败的各种方式,以及成功注册/注销的结果。后者包括:

提示2:查看任务4末尾的列表,了解测试内容的一些想法。

可交付成果。对于任务3,您应提交以下文件:

确保PostgreSQL可以在您提交文件之前执行这些文件。

任务4:前端应用程序

这个作业的最后一部分是写一个学生可以用于与数据库通信。此应用程序应连接到PostgreSQL数据库以请求并插入适当的数据,并且可以是

Java和JDBC

为了帮助您编写应用程序,我们为您提供了一个存根文件包含用于在本地系统上连接到PostgreSQL的代码。它还可以包含应用程序三种操作模式的挂钩,这是应该插入代码的位置。这个想法是你不需要重点放在应用程序的纯Java部分上,而不是直接开始使用数据库接口代码。

存根文件位于此处:学生门户网站.java.

程序的预期行为是从命令行使用它,给出一些学生识别号作为参数(这到底是什么取决于您的设计)。这对应于学生“登录”到门户。登录后,学生可以选择三种模式之一“信息”、“注册”或“注销”。如果选择第一个,则所有那个学生的信息应该打印出来。确切的信息必须按上述系统要求打印。如果选择后一种模式时,将提示学生注册课程到或从注销,应用程序应执行请求的操作并打印结果(成功、失败)。

存根文件可以按原样编译和运行,但不会发生任何事情在任何模式下。因此,您的任务是填写这些内容的实际逻辑三项任务。

运行应用程序可能如下所示:

$>java学生门户1234567890欢迎!请选择操作模式:? > 学生信息1234567890-------------------------------------姓名:Emilia Emilsson学生编号:emem行:信息技术(IT)分支:系统开发阅读课程(名称(代码),学分:年级):集合论(MAT050),5p:5函数编程(TDA450),10p:5面向对象系统开发(TDA590),10p:4注册课程(名称(代码):状态):数据库(TDA356):已注册算法(TIN090):作为nr 3等待参加的研讨会课程:0取得的数学学分:5取得的研究学分:0总学分:25符合毕业要求:否-------------------------------------请选择操作模式:? > r TDA350您现在已成功注册TDA350加密课程!请选择操作模式:? > r TDA381型课程TDA381并发编程已满,您将进入等待列表。请选择操作模式:? > 退出再见!$>

请注意,精确的格式只是一个建议:您可以选择格式化只要您将适当的信息返回给用户。

要从应用程序访问PostgreSQL jdbc驱动程序,您应该从以下位置下载https://jdbc.postgresql.org网站并将其导入到java中类路径。

或者,如果使用日食。

如果您正在Java中插入学生门户,可以跳过关于Haskell的下一节,继续要求和可交付成果如下所示。

哈斯克尔和HDBC

我们提供如下所述的Haskell模块作为您的起点工作。您可以一次从下载所有内容任务4haskell.zip.

学生门户.hs
这是学生门户应用程序的主要模块。它包含三个不完整的函数定义,您应该在其中添加自己的代码来访问数据库。当然,您也可以根据需要添加其他辅助功能。

我们还提供以下模块,您可以不加更改地使用这些模块:

学生门户通用.hs
常见类型定义。
SQL行.hs
将SQL行(查询结果)转换为元组的便利函数,与中定义的类型类似学生门户通用。使用此模块是可选,但它可以在一定程度上简化代码。
学生门户CLI.hs
用户界面模块,选项1。此模块实现相同类型的中用Java实现的命令行界面学生门户.java.
学生门户网站3p.hs
用户界面模块,选项2。该模块实现了一个简单的web界面,使用三便士gui,需要安装,例如通过运行cabal安装三便士gui.

这两个用户界面模块都导出一个名为学生门户,从中调用主要的函数,所以只需更改用户即可在两个用户界面之间切换导入的接口模块。不需要对代码进行其他更改。

HDBC公司

HDBC简介可在本书中找到真实世界的Haskell,第21章。使用数据库。在这里,我们只简要总结一下您需要了解的内容。

正如您在主模块中看到的那样学生门户.hs,要使用HDBC从Haskell访问PostgreSQL数据库,您需要导入来自两个软件包的两个模块:

您可以同时安装两个软件包,例如通过运行电缆安装HDBC-postgresql.

SQL值和行

使用HDBC,从数据库检索或发送到数据库的所有值都具有哈斯克尔类型SqlValue(平方值)例如,函数快速查询'向数据库发送SQL查询并检索结果类型为:

快速查询'::连接->字符串->[SqlValue]->IO[[Sql Value]]

HDBC提供过载功能到Sql来自Sql转换之间SqlValue(平方值)和正常的Haskell类型,比如字符串国际.您还可以从SqlValue(平方值)到例如。也许是字符串,如果你正在检索可能是无效的.

模块SQL行上面提到的提供了转换函数一次编写整行SQL值,这允许您编写如下函数以下内容:

getContinent::连接->字符串->IO[(String,Int)]获取大陆连接大陆=fromRowsM=<<quickQuery'查询[toSql大陆]哪里query=“选择姓名,人口来自国家WHERE大陆=?”

这里,返回的行快速查询'转换自[[SqlValue]]到类型[(字符串,Int)].用于正确构造查询转换应该成功,但通常可能失败,例如,如果查询结果中的行不包含预期的值(本例中为两个)或如果行中的单个值无法转换为预期的Haskell类型(字符串国际在本例中)。

功能来自行M来自M行是单子的并在中引发错误IO(输入输出)如果转换失败,则返回monad。中的错误IO(输入输出)可以使用库中的函数捕获monad模块系统。IO.错误也有纯变体来自行来自行那个电话错误转换失败时。

fromRowM::(FromRow a,Monad m)=>行->m afromRowsM::(FromRow a,Monad m)=>行->m[a]fromRow::fromRow a=>行->fromRows::FromRow a=>行->[a]

要求和可交付成果

您的学生门户应用程序应表现为只有以下权限:

我们将检查您提交的代码,以确保您遵守这些特权,即使我们无法让系统自动执行它们。

可交付成果:

您必须参加其中一个监督会议并展示您的运行应用程序,我们将当场接受或拒绝它(等待检查提交的授权代码违规)。提交时,您应该在评论中写下您向其演示的老师的姓名以及您被接受的时间。

每组演示大约需要10分钟。在演示之前,请至少对以下列表进行一次测试。还有一个用于在数据库上运行查询的接口,它可以显示CourseQueuePositions和Registrations的内容。

作为你可能意识到,如果你们都等到最后一次会议,我们会很简单,不是每个人都有时间,所以早点来!

以下是我们将测试应用程序的内容列表(演示时请准备运行这些内容):

  1. 列出学生的信息。
  2. 为学生注册无限制课程,并显示其结束向上注册(再次显示信息)。
  3. 再次为同一课程注册同一学生,并显示程序不会崩溃,学生会收到一条错误消息。
  4. 从课程中注销学生,然后从中再次注销同样的课程。表明该学生未注册。
  5. 为学生注册一门他们不具备先决条件的课程for,并显示注册未通过。
  6. 从已注册的限制课程中注销学生到,并且队列中至少有两名学生。再次注册到同样的课程,并表明学生得到了正确的答案(最后)在等待列表中的位置。
  7. 注销并重新注册同一名学生相同的限制课程,并表明学生首先被删除然后在相同的位置结束(最后)。
  8. 最后,从过满课程,即带有注册的学生超过了课程中的名额(您需要直接在数据库中设置此情况)。显示没有学生因此从队列中移动到正在注册。

你必须在最后一次实验课之前或之前演示你的工作项目。