且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Application Express:匿名PL/SQL块和绑定变量

更新时间:2022-12-03 11:04:02

Oracle APEX中的流程控制

(在其他编程学科和环境中考虑这实际上很有用.)

Process Flow Control in Oracle APEX

(This is actually useful to think about in other programming disciplines and environments.)

问题是在满足条件之前,页面项目(:P4550_REQUESTOR)不会填充值.看起来,PL/SQL阻止过程在页面加载后立即将变量绑定为空值,尽管该过程只有在单击特定按钮后才会触发.

The problem is that the page item (:P4550_REQUESTOR) is not populated with a value until a conditional is met. It appears that the PL/SQL block process is binding the variable to an empty value as soon as the page is loaded, despite the fact that the process does not fire until a specific button has been clicked.

问题陈述以Apex术语重新措词并以实际问题的形式呈现:

The problem statement reworded in Apex terminology and presented in the form of an actual question:

  1. 页面上有一个REPORT REGION,其中包含直接引用数据表/视图的结果.此报告由称为自动提取"的Apex流程管理,并由页面标题的加载自动启动.
  2. 页面上有一个FORM ITEM,它由用户选择的BUTTON ITEM有条件地填充. BUTTON ITEM是报告结果的一部分.
  3. 有多个按钮项.每个都与每个报告记录的值相关联.
  4. 如果用户未从REPORT REGION中选择BUTTON ITEM,则FORM ITEM保持未分配状态,并包含空"值.
  1. There is a REPORT REGION on the page which contains the result of a direct reference to a data table/view. This report is managed by an Apex process called "Automated Fetch" and is initiated automatically by the loading of the page headers.
  2. There is a FORM ITEM on a page which which is populated conditionally by a BUTTON ITEM selection made by the user. The BUTTON ITEM is part of the report results.
  3. There are multiple button items. Each is associated with a value for each report record.
  4. If the user does not select the BUTTON ITEM from the REPORT REGION, the FORM ITEM remains unassigned and contains a "null" value.

有一个已定义的PL/SQL代码块,可以将其设置为在按下SUBMIT BUTTON项目时执行(也在同一页面上).为什么我的代码块(定义的页面进程)在没有先从REPORT REGION首先按下BUTTON ITEM的情况下被触发时以空值运行?

There is a defined PL/SQL block of code which is set to execute when a SUBMIT BUTTON item is pressed (also on the same page). Why does my code block (defined page process) run with a null value when it is triggered without first pressing a BUTTON ITEM from the REPORT REGION first?

如果您以过程语言的范式思考,答案并不明显.在不进行有关该主题的演讲的情况下,这是我制作的OP的问题空间的直观布局,以说明如何使问题变得更加明显:

The answer is not obvious if you think under the paradigm of a procedural language. Without diving into a lecture on the topic, here's a visual layout of the problem space of the OP that I cooked up to illustrate how the problem can be made more obvious:

这是我正在实施的Apex页面设计.它足够通用,可以用作其他Apex设计的模板.此图上没有流程箭头,因为它是一个有状态的系统.一件事会导致另一件事发生,依此类推……但并非总是如此,并非同时发生.

This is my Apex page design in implementation. It's generic enough to use as a template for other Apex designs. There are no flow arrows on this diagram because it's a stateful system. One thing causes another thing to happen and so on... but not always and not all at the same time.

尝试遍历几个用例,以了解图中分解的元素如何一起运行.每个用户可以进行任意数量的点击组合和互动,但是有一个共同点:

Try walking through a few use cases to understand how the elements broken down in the diagram operate together. Each user may take any number of click combinations and interactions, but there is a commonality:

  1. 它们在页面加载时都输入了相同的初始化条件.
  2. 他们都通过以下方式离开页面:导航到其他地方或通过提交"按钮事件.

用例#1

  1. 用户从{MyPage:SQLReport}
  2. 中的一条记录中选择{MyPage:SQLReport:ThisButton}
  3. 根据{MyPage:SQLReport:ThisButton} #3,将报表记录和按钮项之间关联的值传递给:{MyPage:HTML-Region:ThisItem}
  4. 表单项状态已更新,并且已从初始null值更改.
  5. 用户选择{MyPage:HTML-Region:ThisSubmit}按钮通知系统继续运行.
  6. 提交"按钮执行定义的PL/SQL过程块:{MyPage:RunCodeBlock}
  1. User chooses {MyPage:SQLReport:ThisButton} from one of the records in {MyPage:SQLReport}
  2. According to {MyPage:SQLReport:ThisButton} #3, the value associated between the report record and the button item is passed to: {MyPage:HTML-Region:ThisItem}
  3. The form item state has been updated and changed from the initial null value.
  4. User selects {MyPage:HTML-Region:ThisSubmit} button to inform the system to continue on.
  5. The submit button executes the defined PL/SQL procedure block: {MyPage:RunCodeBlock}

用例2

  1. 用户进入页面并查看在{MyPage:SQLReport}区域中显示的结果.
  2. 用户认为不需要其他输入,然后选择{MyPage:HTML-Region:ThisSubmit}按钮通知系统继续运行.
  3. (注意:此时,表单项{MyPage:HTML-Region:ThisItem}的状态尚未从初始null值更改...选择了提交按钮之后)
  4. 提交"按钮执行定义的PL/SQL过程块:{MyPage:RunCodeBlock}
  1. User enters page and reviews results displayed in the {MyPage:SQLReport} region.
  2. User decides no additional input is necessary and then selects the {MyPage:HTML-Region:ThisSubmit} button to inform the system to continue on.
  3. (a note: the state of form item {MyPage:HTML-Region:ThisItem} has not been changed from the initial null value at this point... after the submit button has been selected)
  4. The submit button executes the defined PL/SQL procedure block: {MyPage:RunCodeBlock}

用例#3

  1. 用户从{MyPage:SQLReport}
  2. 中的一条记录中选择{MyPage:SQLReport:ThisButton}
  3. 根据{MyPage:SQLReport:ThisButton} #3,将报表记录和按钮项之间关联的值传递给:{MyPage:HTML-Region:ThisItem}
  4. 表单项状态已更新,并且已从初始null值更改.
  5. 用户从{MyPage:SQLReport}中的一条记录中的不同选择项中选择{MyPage:SQLReport:ThisButton}.
  6. 根据{MyPage:SQLReport:ThisButton} #3,将报表记录和按钮项之间关联的值传递给:{MyPage:HTML-Region:ThisItem}
  7. 表单项状态已从步骤(2)中存储的初始值进行了更新和更改.
  8. 用户选择{MyPage:HTML-Region:ThisSubmit}按钮通知系统继续运行.
  9. 提交"按钮执行定义的PL/SQL过程块:{MyPage:RunCodeBlock}
  1. User chooses {MyPage:SQLReport:ThisButton} from one of the records in {MyPage:SQLReport}
  2. According to {MyPage:SQLReport:ThisButton} #3, the value associated between the report record and the button item is passed to: {MyPage:HTML-Region:ThisItem}
  3. The form item state has been updated and changed from the initial null value.
  4. User chooses {MyPage:SQLReport:ThisButton} from a different selection from one of the records in {MyPage:SQLReport}.
  5. According to {MyPage:SQLReport:ThisButton} #3, the value associated between the report record and the button item is passed to: {MyPage:HTML-Region:ThisItem}
  6. The form item state has been updated and changed from the initial value stored in step (2).
  7. User selects {MyPage:HTML-Region:ThisSubmit} button to inform the system to continue on.
  8. The submit button executes the defined PL/SQL procedure block: {MyPage:RunCodeBlock}

每种情况之间的差异应说明为什么一个用例与另一个用例相比,依赖值(ThisItem,或更具体地说,页面项P4550_REQUESTOR)为空.

The difference between each case should illustrate why the dependent value (ThisItem, or more specifically, page item P4550_REQUESTOR) is null in one use case vs. the other.

我使用的表称为STAR_EMPS.它类似于EMP表,但只有三列:ename,deptno和salary.尽管它不是很重要,但这是我用来填充STAR_EMPS的数据集:

The table I used is called STAR_EMPS. It is similar to the EMP table but has only three columns: ename, deptno and salary. Although it is not super important, this is the data set I used to populate STAR_EMPS:

我使用了一个名为STAR_EMPS_LOG的简单两列表来捕获成功执行的过程调用的输出.您只用一列就可以完成相同的操作,但是我想要一个顺序ID来跟踪每个事件的记录顺序-用于运行多个测试用例.该过程是此页面上保留的几个已定义过程之一:

I used a simple two-column table named STAR_EMPS_LOG for capturing the output of a successfully executed procedure call. You could accomplish the same with just one column, but I wanted a sequential id for tracking the order each event was recorded- for running multiple test cases. The procedure is one of several defined processes kept on this page:

包含在:{MyPage:RunCodeBlock}中:

contained in: {MyPage:RunCodeBlock} is below:

    DECLARE
      -- output from this procedure will be recorded in the star_emps_log
      -- table.  {MyPage:RunCodeBlock}

      mycelebrity  star_emps.ename%TYPE:= :P17_CELEBRITY_NAME;
      mylogmessage star_emps_log.log_message%TYPE;

    BEGIN
      -- Conditional; changes message based on the value set for the
      -- page item.

         if mycelebrity is null then
         mylogmessage:= 'No button was pressed on the previous page.';
     else 
         mylogmessage:= 'The user selected: ' || mycelebrity ||
         ' from the report list.';
     end if;

     -- populate value from the page item.
        INSERT INTO star_emps_log (log_message)
           VALUES (mylogmessage);
        commit;

    END;

这是设置页面布局的方式:

This is how the page layout was set up:

>

  1. 在您的示例中,我创建了一个{MyPage:SQLReport}区域及其支持元素. SQL报表代表针对源数据表的查询.
  2. {MyPage:Form}已被 重命名 到{MyPage:HTML-Region}.
  3. {MyPage:SQLReport}由SQL查询定义,还有一个模拟列用作放置编辑"按钮的占位符.
  4. {MyPage:SQLReport:ThisButton}按钮详细说明如下:

两个页面"过程:过程"和分支"需要与引用按钮触发项的相同设置相链接.

The TWO Page processes: PROCESS and BRANCH need to be linked with the same settings referencing a BUTTON triggering Item.

运行三种建议的方案以开始使用.验证系统是否正确解释了请求.这是页面布局的样子:

Run through the three suggested scenarios to get started. Verify that the system is interpreting the requests correctly. This is what the page layout looks like:

系统上的两个进程的定义在前面的讨论中没有提到,可能会解决我们眼前的原始问题:

The two processes on the system have a definition that wasn't mentioned in previous discussions may solve our original problem at hand:

这是一件好事,一旦分解,这将是一件微不足道的案件.此处描述的图表绘制方法应可扩展到复杂程度不同的其他Apex应用程序.远离代码,限制术语并尝试在没有实际代码的情况下描述系统和过程具有相当大的实用性.如果这种方法有助于您应对自己的Oracle Apex设计挑战,请确保分享任何故事.

It is a good thing this turns out to be a trivial case once broken down. The diagramming method described here should scale to other Apex applications of varying complexity. There is considerable utility in stepping away from the code, locking down on terminology and trying to describe systems and processes without actual code. Please be sure to share any stories if this approach helps with your own Oracle Apex design challenges.

前进!