【问题标题】:Cascading List of Values with many to many relationship具有多对多关系的级联值列表
【发布时间】:2014-05-11 07:08:16
【问题描述】:

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

感谢您的帮助,或者您能否指出正确的方向,以便我自己解决。

【问题讨论】:

  • 你做得很好,这就是你应该做的,继续!

标签: plsql oracle-apex


【解决方案1】:

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

您的初始架构设计看起来不错。一个建议是,一旦您在较小的规模上开发和测试了您的解决方案,请在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_SUBJECTP5_SEMESTER的默认值为null,这对级联关系的处理有什么帮助?
  • SEMESTER_SUBJECT 表示键关系。 为什么不需要此表的 LOV?

使用级联 LOV 的 APEX 应用程序表单设计

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

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

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

我们将使用“Cascading Parent”选项,这样该项目将等到CHOOSE_SEMESTERCHOOSE_SUBJECT 都被选中。如果两者中的任何一个发生更改,它也会刷新。

是的! 级联父项可以由多个页面项/元素组成。它们只需要在逗号分隔的列表中声明即可。

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

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

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

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

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

学期:2014 年春季 + 主题:PHYS 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”的概念在引用它的其他表中发生了转换。 (例如SEMESTER 表中的ID 列在SEMESTER_SUBJECT 表中变为SEMESTER_ID。只需通过更大的查询密切关注这些名称更改。有时我实际上完全忘记了ID 我是什么合作。

  • 明智的说法:如果您决定通过数据库序列对象分配ID 值,则默认值通常从一个开始。如果您的架构中有多个具有相同列名的不同表:ID 和一些关联表,例如 CLASS_ENROLLMENT,它们连接一个主键 ID 和三个附加外键 ID's 的值,它可能会得到很难辨别数据值的来源。

    考虑偏移您的序列或任意选择不同的增量和起始值。如果您主要在查询中推送 ID,如果两个不同的 ID 集相隔两个或三个数量级,则很容易知道您是否提取了正确的数据值。

  • 是否有更多的级联关系?如果“父”项关系表示依赖项使页面项 LOV 等待或根据另一个项的值发生变化,是否存在要定义的另一个级联关系?在CHOOSE_SEMESTERCHOOSE_SUBJECT 的情况下可以吗?有必要吗?

    我能够弄清楚如何使这两个项目保持 可选 级联依赖项,但它需要设置另一个外部页面项目引用。 (如果它不是可选的,一旦两个值之一发生变化,您就会陷入闭环。)花哨,但对于解决手头的问题并不是真正必要的。

  • 还有什么事情要做?我留下了一些额外的任务让您继续,例如在选择有效的STUDENT 后将 DML 管理到ENROLLMENT 表中。

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

【讨论】:

  • 哦,哇,感谢您抽出宝贵的时间来写这一切。您的帮助是无价的!我找不到任何包含多个表的 LoV 示例,我无法让 apex 接受我的查询。你的榜样让我走上了正确的道路。
  • 我很高兴它有帮助,@odysseas!您帖子中的示例提供了一个很好的机会,可以与您和我们的 StackOverflow Oracle 社区分享一些关于 APEX 开发人员常见的设计难题的见解。
  • 对于未来的读者,通过“优化刷新 = 否”应用可选的级联依赖
猜你喜欢
  • 1970-01-01
  • 2021-09-07
  • 2018-06-28
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
  • 2011-09-02
  • 1970-01-01
  • 2016-01-28
相关资源
最近更新 更多