Apex初学者在这里。我在Oracle数据库中有一个表单:
create or replace view vw_awkward_view as
select unique tab1.some_column1,
tab2.some_column1,
tab2.some_column2,
tab2.some_column3
from table_1 tab1,
table_2 tab2
WHERE ....
我需要'tab1.some_column1'上的'unique'子句,因为它的基础表中有很多条目。我还需要在我的视图中包含'tab1.some_column1',因为如果没有它,其余的数据就没有多大意义。
在Apex中,我想创建一个关于此视图的报告,其中包含一个用于编辑它的表单(仅限更新)。我不需要编辑tab1.some_column1。只有视图中的其他列需要可编辑。我通常可以使用'替代'触发器来实现这一点,但是当视图包含'distinct','unique'或'group by'子句时,这看起来不可能。
如果我尝试更新此视图中的行,则会收到以下错误:
ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc.
如何避免此错误?我希望我的'替代'触发器启动并执行更新,我不需要编辑具有'unique'子句的列,所以我认为应该可以这样做。
答案 0 :(得分:2)
我认为你应该能够删除“独特”
如果tab2.some_column1,tab2.some_column2,tab2.some_column3 不是唯一的,那么你想如何更新它们?
如果它们是唯一的那么整个结果:tab1.some_column1,tab2.some_column1,tab2.some_column2,tab2.some_column3是唯一的。
当您在sql查询中声明“unique”或“distinct”时,它不仅适用于所有列'tab1.some_column1'
答案 1 :(得分:2)
希望我在这里找到你问题的正确方向;)
您的查询可以通过执行以下操作来实现:
select a.some_column1, tab2.some_column1, tab2.some_column2, tab2.some_column3
from table_2 tab2
join (select distinct some_column1 from table_1) a
on tab2.column_in_tab1 = a.some_column1
您收到ORA-02014
错误的原因是由于自动生成的ApplyMRU
进程。此过程将尝试锁定(已更改的行):
begin
for r in (select ...
from vw_awkward_view
where <your first defined PK column>= 'value for PK1'
for update nowait)
loop
null;
end loop;
end;
这是一个无赖,意味着你将无法使用生成的进程。 您必须编写自己的进程来进行更新。
为此,您必须使用apex_application中的F ##数组。 如果这听起来完全不熟悉,请看一下: Custom submit process和on using the apex_application arrays。
此外,来自Oracle本身的here is a how-to for apex from 2004。它仍然使用了大量的htmldb引用,但它的要点就在那里。
(使用apex_item
接口构建表单可能是一个好主意,并且可以控制生成的内容和所需的数组。)
它归结为:遍历包含项目的数组,并使用提交的值在视图上执行UPDATE
。
当然,您没有这种方式锁定,也没有办法防止不必要的更新。
锁定您可以自己做,例如使用select for update
方法。在更新之前,您必须在要更改的表中锁定正确的行。如果锁定失败,那么您的进程将失败。
至于“丢失的更新”故事:在这里你需要检查MD5校验和。校验和是从表单中的可编辑列生成的,并放在html代码中。在提交时,然后将此校验和与来自这些相同列的新生成的校验和进行比较,但是在提交时使用来自数据库的值。如果校验和不同,则表示记录在页面加载和页面提交之间发生了变化。您的进程应该失败,因为记录已被更改,并且您不希望将这些记录覆盖。 (如果你采用apex_item
方式,那么不要忘记包含MD5_CHECKSUM call(或MD5_HIDDEN)。
重要说明:使用apex_item生成的校验和或仅使用标准表单功能构建要散列的字符串。正如您在apex_item.md5_hidden中看到的,校验和是使用DBMS_OBFUSCATION_TOOLKIT.MD5
生成的。
您可以通过两种方式获取数据库中值的校验和:wwv_flow_item.md5或使用dbms_obfuscation
。
但是,文档没有提到的是:OTN Apex discussion on MD5 checksums。管道被添加到生成的校验和中!不要忘记这一点,否则它会在你的脸上爆炸,你会在几天之内想知道它到底出了什么问题。
示例:
select utl_raw.cast_to_raw(dbms_obfuscation_toolkit.md5(input_string=>
"COLUMN1" ||'|'||
"COLUMN2" ||'|'||
"COLUMN5" ||'|'||
"COLUMN7" ||'|'||
"COLUMN10" ||'|'||
"COLUMN12" ||'|'||
"COLUMN14" ||
'|||||||||||||||||||||||||||||||||||||||||||'
)) md5
from some_table
获取some_table
表格行的校验和,其中第1,2,5,7,10,12,1列是可编辑的!
最后,这应该是如何构建的:
不要在中间提交。这是全部或全部。
我几乎觉得自己过火了,可能觉得它有点多了,但是当你知道陷阱时,实际上并不是很难将这个自定义过程拉下来!对我来说,这是非常了解的:p
答案 2 :(得分:0)
汤姆的答案是处理问题的正确方法,但如果我理解正确的话,我认为你的要求有些过分。
最简单的方法可能是在要编辑的表格上创建表单。然后让报告编辑链接将用户带到此表单,该表单只会更新一个表中所需的列。如果您需要显示其他表中列的值,则在创建链接以将此值传递给可以包含仅显示项目的表单时,这很简单。