這可以使用普通SQL(無過程或函數等)完成,例如使用MERGE
語句。一個完整的會話,從設置表格開始,插入值,爲註釋添加一列,然後MERGE
聲明,結果「之前」和「之後」顯示如下。
我又添加了一行數據,其中沒有NULL
值。你總是需要類似這樣的東西來測試解決方案:當連續有否NULL
值時,它是否正常工作?
真正的工作是在下面的解決方案中標記爲x
的子查詢中完成的。首先我從原始表中獲取數據(加入ROWID
,以便稍後可以識別每行)。 UNPIVOT
需要Oracle 11.1或更高版本;我也使用LISTAGG
,它需要Oracle 11.2或更高版本。你用oracle11g
和oracle10g
標記你的帖子,所以我不知道你有什麼,在任何情況下11g
等都是營銷名稱;正確的版本是11.1或11.2(或者確實是11.2.0.4.0和類似的)。你可以通過select * from v$version
找到你的版本。
如果您沒有Oracle 11.2,則可以使用其他工具(層次查詢或XMLAGG
等)來完成字符串聚合 - Stack Overflow中有很多關於如何完成的問題。同樣,如果您沒有Oracle 11.1,則可以使用交叉連接完成未透明處理;我沒有檢查,但我認爲關於堆棧溢出也有很多問題。這兩項行動都是標準的,與您的問題無關;如果您需要幫助,請先搜索此網站,如果遇到困難,請回復。
所以,回到我的方法。我反轉數據,跟蹤rowid
。在unpivot
操作中,我包含了空值(這不是默認值,因此需要include nulls
)。然後從結果中,我只保留值爲NULL
的行。然後我按01分組,並與LISTAGG
聚合。這爲MERGE
操作準備子查詢x
,該操作在此之外是標準操作。
關於效率的注意事項我問OP中的評論是否應該首選快速執行或解決方案的簡單性(維護更簡單)。 OP表示,易於維護更重要。下面的解決方案更加清晰,但由於以下原因效率不高。在原始表格中,五列中的值已經由它們出現在同一行中的事實「分組」了。不支持丟失這些信息;那麼我們必須再次按ROWID
進行分組,以創建LISTAGG
字符串併爲MERGE
做好準備。GROUP BY
操作很昂貴,如果我們編寫的代碼沒有打破輸入行,就不需要了。但是編寫一個不會中斷輸入行的解決方案,雖然可能,但更加複雜,特別是在列數增加的情況下。
SETUP
create table tbl(cola number, colb number, colc number, cold number,cole number);
insert into tbl(cola, colb, colc, cold, cole) values (1, 7, 3, 4, NULL);
insert into tbl(cola, colb, colc, cold, cole) values (2, 9, NULL, 12, NULL);
insert into tbl(cola, colb, colc, cold, cole) values (3, NULL, NULL, NULL, 10);
insert into tbl(cola, colb, colc, cold, cole) values (0, 1, 2, 3, 5);
commit;
alter table tbl add (comment_about_nulls varchar2(1000));
select * from tbl;
COLA COLB COLC COLD COLE COMMENT_ABOUT_NULLS
---- ---- ---- ---- ---- ----------------------------------------
1 7 3 4
2 9 12
3 10
0 1 2 3 4
SOLUTION
merge into tbl
using (
select rid, listagg(colname, ', ') within group (order by colname) str
from (select rowid as rid, cola, colb, colc, cold, cole from tbl)
unpivot include nulls (val for colname in
(cola as 'ColA', colb as 'ColB', colc as 'ColC',
cold as 'ColD', cole as 'ColE'))
where val is null
group by rid
) x
on (tbl.rowid = x.rid)
when matched then update
set tbl.comment_about_nulls = 'NULL VALUE IN ' || x.str
;
select * from tbl;
COLA COLB COLC COLD COLE COMMENT_ABOUT_NULLS
---- ---- ---- ---- ---- ----------------------------------------
1 7 3 4 NULL VALUE IN ColE
2 9 12 NULL VALUE IN ColC, ColE
3 10 NULL VALUE IN ColB, ColC, ColD
0 1 2 3 5
什麼是更重要的是你:代碼簡單(便於維修),或效率(執行速度)?不要說**都**!有很多方法可以解決這個問題,但代碼更加麻煩。 – mathguy
請澄清:**現有**欄的意思是什麼,稱爲評論?你的表格(保存在磁盤上)是否有這樣的列?或者你只需要在SELECT'查詢的輸出中使用該列? (而不是:列確實存在,你需要'更新'它並將結果保存到磁盤上。) – mathguy
我創建了一個名爲Comments的列 - 如果任何行中有空,並且該列名應該在註釋中更新列爲 - NULL ColE的值....如果更多的列那麼它應該所有那些列 – Puttu