2012-02-09 36 views
1

Apex初學者在這裏。我在窗體的我Oracle數據庫的視圖:Oracle Apex - 使用替代觸發器更新視圖

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」的「唯一」條款,因爲它在它的底層表中的許多條目。我還需要在我的視圖中包含'tab1.some_column1',因爲如果沒有它,其餘數據沒有多大意義。

在Apex中,我想創建一個關於此視圖的報告,並使用表單進行編輯(僅更新)。我不需要編輯tab1.some_column1。只有視圖中的其他列需要可編輯。我通常可以使用'instead of'觸發器來實現這一點,但當視圖包含'distinct','unique'或'group by'子句時,這看起來不可能。

如果我嘗試在這個觀點我碰到下面的錯誤更新行:

ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc. 

我怎樣才能避免這個錯誤?我希望我的「替代」觸發器能夠啓動並執行更新,而且我不需要編輯具有「唯一」子句的列,因此我認爲應該可以執行此操作。

+1

唯一的是所有字段 - tab1.some_column1,tab2.some_column1,tab2.some_column2,tab2.some_column3。如果tab2.some_column1,tab2.some_column2,tab2.some_column3已經是唯一的,那麼爲什麼你需要獨特的?或者我錯過了什麼? – 2012-02-09 15:54:07

+0

啊..想你已經暴露了我可憐的SQL在這裏。我認爲'唯一'只適用於我宣佈它旁邊的專欄。這可能是我的問題。我會進一步調查,謝謝... – JMc 2012-02-09 16:18:09

回答

2

我認爲你應該能夠刪除「獨特」。
if tab2.some_column1,tab2.some_column2,tab2.some_column3 不是唯一的,那麼你想如何更新它們?
如果它們是唯一的那麼整個結果:tab1.some_column1,tab2.some_column1,tab2.some_column2,tab2.some_column3是唯一的。

當你在SQL查詢中註明「獨特的」或「不同」這對所有列不僅「tab1.some_column1」

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過程的原因。這個過程將試圖鎖定(下)更改的行(S):

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 processon 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生成校驗 你可以在數據庫中值的校驗和2種方式: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,14可編輯的行校驗!

最後,這是它應如何構造:

  1. 遍歷陣列
  2. 生成校驗和可修改的列 從數據庫
  3. 比較這電流值校驗和與所提交的校驗 (apex_application.g_fcs如果產生),如果校驗和匹配, 繼續進行更新。如果沒有,則在這裏失敗。
  4. 鎖定更新的正確記錄。指定NOWAIT,並 鎖定失敗,失敗的過程
  5. 更新與提交的值你的看法。您替代觸發器 將會觸發。請確保您的更新語句使用正確的值,以便只更新這一條記錄

不要提交inbetween。它可以是全部或全部。

我幾乎覺得我過了一會兒,它可能覺得它有點多,但是當你知道陷阱時,實際上並沒有很難將這個自定義過程關閉!這是非常有見地,我與它玩:對

0

由湯姆答案是處理的部份問題的正確途徑,但我認爲矯枉過正滿足您的要求,如果我理解正確。

最簡單的方法可能是在要編輯的表上創建表單。然後讓報告編輯鏈接將用戶轉到此表單,該表單將只更新一個表中所需的列。如果您需要顯示另一個表格中的列的值,那麼在創建鏈接以將此值傳遞到可包含僅顯示項目的表單時,這很簡單。