我正在开发一个应用程序,用于跟踪Apex学校的学生上课情况.我想创建一个包含三级级联选择列表的页面,因此教师可以先选择学期,然后选择主题,然后选择该主题的特定类,以便应用程序返回已注册该类的学生.
我的问题是这三个表之间有多对多的关系,所以我使用额外的表和它们的键.每个学期都有许多科目,并且可以在许多学期教授科目.每个学期每个学科都有很多课程.学生必须每学期注册一个科目,然后教师可以将他们分配到一个班级.
表格看起来像这样:
create table semester( id number not null, name varchar2(20) not null, primary key(id) ); create table subject( id number not null, subject_name varchar2(50) not null, primary key(id) ); create table student( id number not null, name varchar2(20), primary key(id) ); create table semester_subject( id number not null, semester_id number not null, subject_id number not null, primary key(id), foreign key(semester_id) references semester(id), foreign key(subject_id) references subject(id), constraint unique sem_sub_uq unique(semester_id, subject_id) ); create table class( id number not null, name number not null, semester_subject_id number not null, primary key(id), foreign key(semester_subject_id) references semester_subject(id) ); create table class_enrollment( id number not null, student_id number not null, semester_subject_id number not null, class_id number, primary_key(id), foreign key(student_id) references student(id), foreign key(semester_subject_id) references semester_subject(id), foreign key(class_id) references class(id) );
学期选择列表的值列表如下所示:
select name, id from semester order by 1;
主题选择列表应包括上面选择的学期中可用的所有主题的名称,但我无法确定查询,即使它是可能的.我现在拥有的:
select s.name, s.id from subject s, semester_subject ss where ss.semester_id = :PX_SEMESTER //value from above select list and ss.subject_id = s.id;
但是你不能在一个LoV中有两个表,而且查询可能是错的......我甚至没有开始考虑类的查询会是什么样子.
我感谢任何帮助,或者如果你能指出我正确的方向,那么我可以自己弄清楚.
您的初始架构设计看起来不错.一个建议,一旦您开发并测试了较小规模的解决方案,在ID
(主键)列附加一个触发器,可以通过序列自动填充其值.您也可以跳过触发器,并在sql insert DML命令中引用序列.它只会让事情变得简单.使用内置向导在APEX环境中创建表可以创建"自动递增"键列.
还有一个额外的列添加到SEMESTER
表中称为SORT_KEY
.当您存储字符串类型的值时,这会有所帮助,这些值的逻辑排序顺序本质上不完全是字母数字.
以下是我生成的测试数据,用于演示与示例一起使用的级联值设计列表.
下一步是制作前三个相互依赖的值列表定义.正如您所发现的,您可以在LOV中引用可能来自各种来源的页面参数.在这种情况下,我们的LOV中的选择将被分配给Apex页面项目.
我还认为在单个LOV查询中只能引用一个表. 这是不正确的. 页面文档表明,SQL查询语法是限制因素.以下LOV查询引用了多个表,它们可以工作:
-- SEMESTER LOV Query -- name: CHOOSE_SEMESTER select a.name d, a.id r from semester a where a.id in ( select b.semester_id from semester_subject b where b.subject_id = nvl(:P5_SUBJECT, b.subject_id)) order by a.sort_id -- SUBJECT LOV Query -- name: CHOOSE_SUBJECT select a.subject_name d, a.id r from subject a where a.id in ( select b.subject_id from semester_subject b where b.semester_id = nvl(:P5_SEMESTER, b.semester_id)) order by 1 -- CLASS LOV Query -- name: CHOOSE_CLASS select a.name d, a.id r from class a, semester_subject b where a.semester_subject_id = b.id and b.subject_id = :P5_SUBJECT and b.semester_id = :P5_SEMESTER order by 1
一些需要考虑的设计说明:
不要介意P5_ITEM
符号.我的示例应用程序中的页面恰好位于"第5页",因此约定如此.
我选择为每个LOV查询指定一个名称作为提示.不要只是将查询嵌入到项目中.通过使LOV成为可移植对象(如果需要可在其他地方引用)为开发人员添加一些喘息空间.
通过应用程序设计器的SHARED OBJECTS菜单选项为每个查询命名LOV.
额外的操作涉及NVL
命令,如nvl(:P5_SUBJECT, b.subject_id)
用于CHOOSE_SEMESTER
LOV是镜像对的表达式CHOOSE_SUBJECT
的查询,以及.如果在进入页面时默认值为P5_SUBJECT
和P5_SEMESTER
null,那么它如何帮助处理级联关系?
该表SEMESTER_SUBJECT
代表了一种关键关系. 为什么不需要这张桌子的LOV?
设置用于测试架构设计和LOV查询的页面需要创建三个页面项:
每个页面项目应定义为SELECT LIST
最初保留所有默认值,直到您了解基本设计的工作方式.每个选择列表项应与其对应的LOV相关联,例如:
关键设计扭曲是为LOV 制作的选择列表CHOOSE_CLASS
,它表示对多个数据源的级联依赖.
我们将使用"分级父"选项,这样,这个项目将等待两个CHOOSE_SEMESTER
和CHOOSE_SUBJECT
选择.如果两者中的任何一个发生变化,它也会刷新.
是!级联父项可以包含多个页面项/元素.它们只需要以逗号分隔的列表声明.
从在线帮助信息,这是如何在APEX设计中使用级联LOV的一般介绍:
来自Oracle Apex帮助文档: 级联LOV意味着如果此页面上另一项的值发生更改,则应刷新当前项的值列表.
指定用于触发刷新的以逗号分隔的页面项列表.然后,您可以在"值列表"SQL语句的where子句中使用这些页面项.
这些示例基于此解决方案开头给出的示例数据.所选示例案例的路径是:
SEMESTER:2014年春季 + 主题:物理ED + 验证有效课程选项:
Fitness for Life General Flexibility Presidential Fitness Challenge Running for Fun Volleyball Basics
上面的选择将分配给页面项目P5_CLASS
.
选择选择P5_SEMESTER
:
选择选择P5_SUBJECT
:
选择选择P5_CLASS
:
在使用此设计项目时,我发现了一些结束的想法:
关于主键:主键 的通用ID
命名列的概念是一个很好的设计选择.虽然APEX可以处理复合业务密钥,但它变得笨拙且难以解决.
使架构设计难以理解的一件事是"id"的概念在引用它的其他表中转换.(例如表格中的ID
列SEMESTER
变成SEMESTER_ID
了SEMESTER_SUBJECT
表格.只要用更大的查询来关注这些名称的变化.有时我实际上完全失去了ID
我正在使用的轨道.
Word for Sanity: 在您可能决定ID
通过数据库序列对象分配值的情况下,默认值通常从1开始.如果模式中有多个不同的表具有相同的列名:ID
并且某些关联表(例如CLASS_ENROLLMENT
连接一个主键ID
和三个附加外键的值)ID's
,则可能难以辨别数据值的来源.
考虑抵消序列或任意选择不同的增量和起始值.如果您主要在查询中推送ID,如果两个不同的ID集分开两个或三个数量级,那么很容易知道您是否已经提取了正确的数据值.
是否有更多级联关系? 如果"父"项关系指示使页面项LOV根据另一个的值等待或更改的依赖关系,是否可以定义另一个级联关系?在的情况下,CHOOSE_SEMESTER
和CHOOSE_SUBJECT
这可能吗?有必要吗?
我能够弄清楚如何使这两个项目具有可选的级联依赖关系,但它需要设置另一个外部页面项目引用.(如果它不是可选的,只要两个值中的一个发生变化,就会陷入闭环状态.)很奇怪,但并不是真的有必要解决手头的问题.
还剩下什么? 我遗漏了一些额外的任务供您继续使用,例如ENROLLMENT
在选择有效后将DML管理到表中STUDENT
.
总的来说,你有一个可行的架构设计.有一种方法可以通过APEX应用程序设计模式表示数据关系.编码愉快,看起来像一个具有挑战性的项目!