ORACLE APEX:如何在没有循环的情况下更新 APEX_APPLICATION.G_F01 中的所有项目
ORACLE APEX: How to update all items in APEX_APPLICATION.G_F01 without a LOOP
我在 apex 应用程序的交互式报告中使用复选框。假设它呈现 table MY_TABLE
此 table 包含一个 FLAG
列,其值为 0 or 1
在报告中,如果 FLAG=1
,则勾选每一行的复选框
APEX_ITEM.CHECKBOX2(
p_idx => 1,
p_value => lrg_name,
p_attributes => DECODE(flag,1,'CHECKED', 'null'))
我想允许用户 select 或 deselect 任何行。之后我需要相应地更新数据库中的 FLAG
列。
例如如果用户:
- 将 2 行(A1、A2)从 选中更改为未选中
- 需要为这 2 行更新
FLAG=0
- 将 3 行(B1、B2、B3)从 未选中更改为选中
- 这 3 行需要更新
FLAG=1
我了解到 APEX_APPLICATION.G_F01
将仅包含选中复选框的行的值。这意味着我可以更新数组中存在的 B1,B2,B3 行,但不能更新 A1,A2.
所以,作为黑客,我所做的是:
- 为
MY_TABLE
中的所有行设置 FLAG=0
- 循环
APEX_APPLICATION.G_F01
并设置 FLAG=1
BEGIN
-- step 1
UPDATE MY_TABLE SET FLAG=0;
-- step 2
FOR I in 1..APEX_APPLICATION.G_F01.COUNT
LOOP
UPDATE MY_TABLE
SET FLAG=1
WHERE LRG_NAME=APEX_APPLICATION.G_F01(i);
END LOOP;
END;
如果列表很长,上面的 Step2 会花费很多时间。它 运行 每行一个更新查询。我怎样才能 运行 一次可以更新所有行的查询?
我尝试使用 APEX_UTIL.TABLE_TO_STRING
但它对我不起作用:
UPDATE MY_TABLE SET FLAG=1
WHERE LRG_NAME IN APEX_UTIL.TABLE_TO_STRING(APEX_APPLICATION.G_F01);
apex_item.checkbox 的问题在于它只有在选中时才有值,因此您没有足够的信息来了解哪些行已从选中变为未选中或相反。您可以通过添加额外的 apex_item.hidden 列并使用 pl/sql 过程中的列进行更新来解决这个问题。
这样您就可以优化 pl/sql 块以仅更新实际需要更改的行。在您的情况下,您总是更新 all 行。下面的代码只会更新更改的行。
示例:
基本 table 带有标志列。我使用的是 apex_item.checkbox(不是 checkbox2),但这不重要。
-- create tables
create table so_checkbox (
id number generated by default on null as identity
constraint so_checkbox_id_pk primary key,
name varchar2(100 char) not null,
favorite_flag varchar2(1 char) not null
)
;
-- load data
insert into so_checkbox (id, name, favorite_flag ) values (1, 'Zero Data Loss Implementation', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (2, 'DevOps Best Practices', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (3, 'New Hire Training', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (4, 'Corporate Network Upgrade', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (5, 'Continuous Build', 'N');
使用 sql 查询创建关于此 table 的交互式报告:
select ID,
NAME,
APEX_ITEM.CHECKBOX(1,id,CASE WHEN FAVORITE_FLAG = 'Y' THEN 'CHECKED' END)||
APEX_ITEM.HIDDEN(2,CASE WHEN FAVORITE_FLAG = 'Y' THEN id END) as favorite
from SO_CHECKBOX
在第一列中,连接了 2 apex_item 列。第一个是复选框(id 1),第二个(隐藏)是复选框的当前值(id 2)。在提交时运行的过程中,每个数组都放在类型为 apex_t_varchar2
的变量中,然后 pl/sql MULTISET
语句可用于识别更改的复选框。
DECLARE
l_old_checked apex_t_varchar2 := apex_t_varchar2();
l_new_checked apex_t_varchar2 := apex_t_varchar2();
l_added apex_t_varchar2 := apex_t_varchar2();
l_removed apex_t_varchar2 := apex_t_varchar2();
BEGIN
FOR i in 1..APEX_APPLICATION.G_F01.COUNT LOOP
apex_string.push(l_new_checked,APEX_APPLICATION.G_F01(i));
END LOOP;
FOR i in 1..APEX_APPLICATION.G_F02.COUNT LOOP
apex_string.push(l_old_checked,APEX_APPLICATION.G_F02(i));
END LOOP;
l_added := l_new_checked MULTISET EXCEPT l_old_checked;
l_removed := l_old_checked MULTISET EXCEPT l_new_checked;
UPDATE so_checkbox SET favorite_flag = 'Y' WHERE id IN (SELECT column_value FROM table(l_added));
UPDATE so_checkbox SET favorite_flag = 'N' WHERE id IN (SELECT column_value FROM table(l_removed));
END;
我在 apex 应用程序的交互式报告中使用复选框。假设它呈现 table MY_TABLE
此 table 包含一个 FLAG
列,其值为 0 or 1
在报告中,如果 FLAG=1
APEX_ITEM.CHECKBOX2(
p_idx => 1,
p_value => lrg_name,
p_attributes => DECODE(flag,1,'CHECKED', 'null'))
我想允许用户 select 或 deselect 任何行。之后我需要相应地更新数据库中的 FLAG
列。
例如如果用户:
- 将 2 行(A1、A2)从 选中更改为未选中
- 需要为这 2 行更新
FLAG=0
- 将 3 行(B1、B2、B3)从 未选中更改为选中
- 这 3 行需要更新
FLAG=1
我了解到 APEX_APPLICATION.G_F01
将仅包含选中复选框的行的值。这意味着我可以更新数组中存在的 B1,B2,B3 行,但不能更新 A1,A2.
所以,作为黑客,我所做的是:
- 为
MY_TABLE
中的所有行设置 - 循环
APEX_APPLICATION.G_F01
并设置FLAG=1
FLAG=0
BEGIN
-- step 1
UPDATE MY_TABLE SET FLAG=0;
-- step 2
FOR I in 1..APEX_APPLICATION.G_F01.COUNT
LOOP
UPDATE MY_TABLE
SET FLAG=1
WHERE LRG_NAME=APEX_APPLICATION.G_F01(i);
END LOOP;
END;
如果列表很长,上面的 Step2 会花费很多时间。它 运行 每行一个更新查询。我怎样才能 运行 一次可以更新所有行的查询?
我尝试使用 APEX_UTIL.TABLE_TO_STRING
但它对我不起作用:
UPDATE MY_TABLE SET FLAG=1
WHERE LRG_NAME IN APEX_UTIL.TABLE_TO_STRING(APEX_APPLICATION.G_F01);
apex_item.checkbox 的问题在于它只有在选中时才有值,因此您没有足够的信息来了解哪些行已从选中变为未选中或相反。您可以通过添加额外的 apex_item.hidden 列并使用 pl/sql 过程中的列进行更新来解决这个问题。
这样您就可以优化 pl/sql 块以仅更新实际需要更改的行。在您的情况下,您总是更新 all 行。下面的代码只会更新更改的行。
示例:
基本 table 带有标志列。我使用的是 apex_item.checkbox(不是 checkbox2),但这不重要。
-- create tables
create table so_checkbox (
id number generated by default on null as identity
constraint so_checkbox_id_pk primary key,
name varchar2(100 char) not null,
favorite_flag varchar2(1 char) not null
)
;
-- load data
insert into so_checkbox (id, name, favorite_flag ) values (1, 'Zero Data Loss Implementation', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (2, 'DevOps Best Practices', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (3, 'New Hire Training', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (4, 'Corporate Network Upgrade', 'N');
insert into so_checkbox (id, name, favorite_flag ) values (5, 'Continuous Build', 'N');
使用 sql 查询创建关于此 table 的交互式报告:
select ID,
NAME,
APEX_ITEM.CHECKBOX(1,id,CASE WHEN FAVORITE_FLAG = 'Y' THEN 'CHECKED' END)||
APEX_ITEM.HIDDEN(2,CASE WHEN FAVORITE_FLAG = 'Y' THEN id END) as favorite
from SO_CHECKBOX
在第一列中,连接了 2 apex_item 列。第一个是复选框(id 1),第二个(隐藏)是复选框的当前值(id 2)。在提交时运行的过程中,每个数组都放在类型为 apex_t_varchar2
的变量中,然后 pl/sql MULTISET
语句可用于识别更改的复选框。
DECLARE
l_old_checked apex_t_varchar2 := apex_t_varchar2();
l_new_checked apex_t_varchar2 := apex_t_varchar2();
l_added apex_t_varchar2 := apex_t_varchar2();
l_removed apex_t_varchar2 := apex_t_varchar2();
BEGIN
FOR i in 1..APEX_APPLICATION.G_F01.COUNT LOOP
apex_string.push(l_new_checked,APEX_APPLICATION.G_F01(i));
END LOOP;
FOR i in 1..APEX_APPLICATION.G_F02.COUNT LOOP
apex_string.push(l_old_checked,APEX_APPLICATION.G_F02(i));
END LOOP;
l_added := l_new_checked MULTISET EXCEPT l_old_checked;
l_removed := l_old_checked MULTISET EXCEPT l_new_checked;
UPDATE so_checkbox SET favorite_flag = 'Y' WHERE id IN (SELECT column_value FROM table(l_added));
UPDATE so_checkbox SET favorite_flag = 'N' WHERE id IN (SELECT column_value FROM table(l_removed));
END;