我正在开发一个应用程序,用于跟踪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中拥有两个表,而且查询可能无论如何...... 我甚至没有开始考虑类的查询会是什么样的。
我感谢任何帮助,或者如果你能指出我正确的方向,那么我可以自己解决。
答案 0 :(得分:5)
您的初始架构设计看起来不错。一个建议,一旦您开发并测试了较小规模的解决方案,在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页"惯例就是这样。NVL
命令的额外运算符,如nvl(:P5_SUBJECT, b.subject_id)
LOV中的CHOOSE_SEMESTER
,也是CHOOSE_SUBJECT
查询上镜像的表达式。如果在进入页面时默认值P5_SUBJECT
和P5_SEMESTER
为空,那么它如何帮助处理级联关系?SEMESTER_SUBJECT
代表关键关系。 为什么不需要此表的LOV? 设置用于测试架构设计和LOV查询的页面需要创建三个页面项:
每个页面项应定义为SELECT LIST
,最初保留所有默认值,直到您了解基本设计的工作原理。每个选择列表项应与其对应的LOV相关联,例如:
关键设计扭曲是为CHOOSE_CLASS
LOV制作的选择列表,它表示对多个数据源的级联依赖关系。
我们将使用" Cascading Parent"选项,以便此项目等到CHOOSE_SEMESTER
和CHOOSE_SUBJECT
都被选中。如果两者中的任何一个发生变化,它也会刷新。
是!级联父项可以包含多个页面项/元素。它们只需要以逗号分隔的列表声明。
在线帮助信息中,这是关于如何在APEX设计中使用级联LOV的一般性介绍:
来自Oracle Apex帮助文档:级联LOV意味着如果此页面上其他项目的值发生更改,则应刷新当前项目的值列表。
指定用于触发刷新的以逗号分隔的页面项列表。然后,您可以在"值列表"的where子句中使用这些页面项。 SQL语句。
这些示例基于此解决方案开头给出的示例数据。所选示例案例的路径为:
SEMESTER:SPRING 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
的值和另外三个外键{ {1}},可能难以辨别数据值的来源。
考虑抵消序列或任意选择不同的增量和起始值。如果你主要在你的查询中推送ID,如果两个不同的ID集分开两个或三个数量级,那么很容易知道你是否已经提取了正确的数据值
是否有更多级联关系?如果"父母" item relationship表示一个依赖项,它使页面项LOV等待或改变,具体取决于另一个的值,是否可以有另一个级联关系来定义?如果ID's
和CHOOSE_SEMESTER
有可能吗?有必要吗?
我能够弄清楚如何使这两个项目保持可选级联依赖关系,但它需要设置另一个外部页面项目引用。 (如果它不是可选的,只要两个值中的一个发生变化,就会陷入闭环状态。)很有意思,但不是真的有必要解决手头的问题。
剩下要做什么?我遗漏了一些额外的任务供您继续使用,例如在选择一个DML后将DML管理到CHOOSE_SUBJECT
表中有效ENROLLMENT
。
总的来说,您已经有了可行的架构设计。有一种方法可以通过APEX应用程序设计模式表示数据关系。编码愉快,看起来像是一个具有挑战性的项目!