具有多对多关系的级联值列表

时间:2014-03-31 19:11:01

标签: plsql oracle-apex

我正在开发一个应用程序,用于跟踪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中拥有两个表,而且查询可能无论如何...... 我甚至没有开始考虑类的查询会是什么样的。

我感谢任何帮助,或者如果你能指出我正确的方向,那么我可以自己解决。

1 个答案:

答案 0 :(得分:5)

使用项目参数化值列表(LOV)开发Apex输入表单

您的初始架构设计看起来不错。一个建议,一旦您开发并测试了较小规模的解决方案,在ID(主键)列附加一个可以通过序列自动填充其值的触发器。您也可以跳过触发器,并在sql insert DML命令中引用序列。它只会让事情变得简单。使用内置向导在APEX环境中创建表格可以实现"自动递增"关键栏目。

还在SEMESTER表中添加了一个名为SORT_KEY的附加列。当您存储字符串类型的值时,这会有所帮助,这些值的逻辑排序顺序本质上不完全是字母数字。

设置测试数据值

以下是我生成的测试数据,用于演示 级联值列表 设计,该示例将与示例一起使用。

APEX Class Enrollment Application Sample Data

制作动态价值查询清单

下一步是制作前三个相互依赖的值列表定义。正如您所发现的,您可以在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) LOV中的CHOOSE_SEMESTER,也是CHOOSE_SUBJECT查询上镜像的表达式。如果在进入页面时默认值P5_SUBJECTP5_SEMESTER为空,那么它如何帮助处理级联关系?
  • SEMESTER_SUBJECT代表关键关系。 为什么不需要此表的LOV?

使用级联LOV的APEX申请表格设计

设置用于测试架构设计和LOV查询的页面需要创建三个页面项:

APEX Page Design for Testing Cascading LOVs

每个页面项应定义为SELECT LIST,最初保留所有默认值,直到您了解基本设计的工作原理。每个选择列表项应与其对应的LOV相关联,例如:

APEX Page Item Design: Select List Type

关键设计扭曲是为CHOOSE_CLASS LOV制作的选择列表,它表示对多个数据源的级联依赖关系。

我们将使用" Cascading Parent"选项,以便此项目等到CHOOSE_SEMESTERCHOOSE_SUBJECT都被选中。如果两者中的任何一个发生变化,它也会刷新。

APEX Page Item Design: Using a Form Item Element for a Cascading LOV Relationship

  

是!级联父项可以包含多个页面项/元素。它们只需要以逗号分隔的列表声明。

在线帮助信息中,这是关于如何在APEX设计中使用级联LOV的一般性介绍:

  

来自Oracle Apex帮助文档:级联LOV意味着如果此页面上其他项目的值发生更改,则应刷新当前项目的值列表。

     

指定用于触发刷新的以逗号分隔的页面项列表。然后,您可以在"值列表"的where子句中使用这些页面项。 SQL语句。

使用级联LOV演示APEX应用程序项目

这些示例基于此解决方案开头给出的示例数据。所选示例案例的路径为:

  

SEMESTER:SPRING 2014 + 主题:物理ED + 验证有效课程选项:

 Fitness for Life
 General Flexibility
 Presidential Fitness Challenge
 Running for Fun
 Volleyball Basics

上面的选择将分配给页面项P5_CLASS

P5_SEMESTER的选择选项:

APEX Form Design: Semester Option Selection

P5_SUBJECT的选择选项:

APEX Form Design: Subject Option Selection

P5_CLASS的选择选项:

APEX Form Design: Class Option Selection

结束语和讨论

在使用此设计项目时,我发现了一些结束的想法:

  • 关于主键:主键的通用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'sCHOOSE_SEMESTER有可能吗?有必要吗?

    我能够弄清楚如何使这两个项目保持可选级联依赖关系,但它需要设置另一个外部页面项目引用。 (如果它不是可选的,只要两个值中的一个发生变化,就会陷入闭环状态。)很有意思,但不是真的有必要解决手头的问题。

  • 剩下要做什么?我遗漏了一些额外的任务供您继续使用,例如在选择一个DML后将DML管理到CHOOSE_SUBJECT表中有效ENROLLMENT

总的来说,您已经有了可行的架构设计。有一种方法可以通过APEX应用程序设计模式表示数据关系。编码愉快,看起来像是一个具有挑战性的项目!