2017-02-24 25 views
1

我有一个查询,它调用一个包中的函数来创建一个约30列的总和的百分比值。根据嵌套选择更新Oracle表。包函数

我想要做的是根据“计算列的总和”作为百分比更新每一行。

的选择查询是:

SELECT 
checklist_id, 
row_status, 
eba_cm_checklist_std.get_row_percent_complete(pc.id,pc.checklist_id,pc.max_col_num) AS percent_complete 
FROM 
(
    SELECT 
     (
      SELECT 
       COUNT(id) 
      FROM 
       eba_cm_checklist_columns 
      WHERE 
       checklist_id = r.checklist_id 
     ) AS max_col_num, 
     r.* 
    FROM 
     eba_cm_checklist_rows r 
    ORDER BY 
     r.row_order, 
     r.name 
) pc 

,并创建百分比package.function是 “eba_cm_checklist_std.get_row_percent_complete”。

查询输出如下:

checklist_id       row_status percent_complete 
97176759931088640236098007249022291412 Red   0 
97176759931071715274623402440576404948 Red   0 
97176759931071715274623402440576404948 Red   0 
97176759931071715274623402440576404948 Red   0 
97176759931088640236098007249022291412 Red   0 
97176759931088640236098007249022291412 Red   0 
97176759931081386681180319473974054356 Grey  100 
97176759931051163535689953744606399956 Grey  100 

我遇到的困难是,该表达式使用基于函数的输出嵌套select语句,我不能让我围绕如何头根据查询的输出更新物理“eba_cm_checklist_rows”表。

基本上,我要做到以下几点:

update set row_status = 'Green' where percent_complete = 100 
+0

'COUNT(*)'计数的所有行,但'计数(COL)'只能算作行,其中山坳不为空。 – jarlh

+0

好吧,我已经用'count(id)'替代了count(*)'(id是每行唯一/ pk) – Huskie69

回答

1

另一种选择是使用批量选择/更新:

declare 
    type t_rid_arr is table of rowid index by pls_integer; 
    type t_row_status_arr is table of eba_cm_checklist_rows.row_status%type index by pls_integer; 
    type t_percent_complete_arr is table of number index by pls_integer; 

    l_rid_arr t_rid_arr; 
    l_row_status_arr t_row_status_arr; 
    l_percent_complete_arr t_percent_complete_arr; 
begin 
    SELECT 
    rid, 
    row_status, 
    eba_cm_checklist_std.get_row_percent_complete(pc.id,pc.checklist_id,pc.max_col_num) AS percent_complete 
    bulk collect into 
    l_rid_arr, 
    l_row_status_arr, 
    l_percent_complete_arr 
    FROM (
    SELECT r.rowid as rid, 
      r.*, 
      count(*) over(partition by checklist_id) AS max_col_num 
     FROM eba_cm_checklist_rows r 
    ) pc; 

    forall i in 1..l_rid_arr.count 
    update eba_cm_checklist_rows 
     set row_status = case when l_percent_complete_arr(i) = 100 then 'Green' else row_status end 
     where rowid = l_rid_arr(i); 
end; 
/
+0

谢谢生锈。 'PL/SQL过程已成功完成'。但是,当我检查行时,row_status没有改变。我看不出为什么会这样! – Huskie69

+1

尝试用您的主键替换rowid。检查percent_complete的类型。是数字吗? – Rusty

+0

我用'id'(表格的pk)替换了'rowid'的所有实例,并且还使用了'to_number(l_percent_complete_arr(i))= 100' - 仍然相同,但执行成功,但似乎不成功更新什么。修改PL/SQL在这里:http://pastebin.com/RnY8d77F万一我做了明显错误的事情! – Huskie69

1

,你可以尝试使用CTE和SUM()OVER()函数,希望你觉得它有用。

+0

CTE看起来像要走的路,谢谢! (之前没有听说过这个功能)。试图弄清楚语法。 – Huskie69

1

尝试这样:

merge into eba_cm_checklist_rows trg 
using (
SELECT 
rid, 
checklist_id, 
row_status, 
eba_cm_checklist_std.get_row_percent_complete(pc.id,pc.checklist_id,pc.max_col_num) AS percent_complete 
FROM 
(
    SELECT r.rowid as rid, 
      r.*, 
      count(*) over(partition by checklist_id) AS max_col_num 
     FROM eba_cm_checklist_rows r 
) pc 
) src 
on (trg.rowid = src.rid) 
when matched then update set row_status = 'Green' where percent_complete = 100; 

我不喜欢这个主意,用在SQL中的功能 - 它可能会与正常的SQL来代替。

+0

嗯,我越来越'ORA-04091:表CHECKLIST.EBA_CM_CHECKLIST_ROWS是变异,触发器/函数可能看不到它 ORA-06512:在“CHECKLIST.EBA_CM_CHECKLIST_STD”,行44' – Huskie69

+0

这个表上触发器调用一个函数(CHECKLIST.EBA_CM_CHECKLIST_STD.create_checklist_history)更新一个'历史'表记录任何修改... – Huskie69

+0

好吧,我不知道这个函数在做什么。你可以发布源代码吗? – Rusty