2016-03-18 102 views
0

我目前正在學習SQL,並且遇到了我的程序問題。該過程應計算名爲「INDICE_METABO_PAT」的列的平均值。我需要的信息是3-4個不同的表格。然後,當我確實計算了平均值時,我更新了一個表格以將此平均值設置爲相應的條目。這是程序。需要注意的是一切在我的.sql文件的工作原理:插入,更新,選擇,視圖等SQL Oracle - 程序語法(學校作業)

create or replace Procedure SP_UPDATE_INDICE_METABO_DV (P_NO_ETUDE in number) 

is 
    V_SOMME number := 0; 
    V_NBPATIENT number := 0; 
    V_NO_ETUDE number := P_NO_ETUDE; 

    cursor curseur is 
    select PATIENT.INDICE_EFFICACITE_METABO_PAT 
    from ETUDE, DROGUE_VARIANT, ETUDE_PATIENT, PATIENT 
    where ETUDE.NO_DROGUE = DROGUE_VARIANT.NO_DROGUE 
    and ETUDE.NO_VAR_GEN = DROGUE_VARIANT.NO_VAR_GEN 
    and V_NO_ETUDE = ETUDE_PATIENT.NO_ETUDE 
    and ETUDE_PATIENT.NO_PATIENT = PATIENT.NO_PATIENT; 

begin 
    open curseur; 
    fetch curseur into V_SOMME; 
    V_NBPATIENT := V_NBPATIENT + 1; 
    exit when curseur%NOTFOUND; 

    update DROGUE_VARIANT 
    set INDICE_EFFICACITE_METABO_DV = V_SOMME/V_NBPATIENT 
    where exists(select * from ETUDE, DROGUE_VARIANT, ETUDE_PATIENT, PATIENT 
    where ETUDE.NO_DROGUE = DROGUE_VARIANT.NO_DROGUE 
    and ETUDE.NO_VAR_GEN = DROGUE_VARIANT.NO_VAR_GEN 
    and V_NO_ETUDE = ETUDE_PATIENT.NO_ETUDE 
    and ETUDE_PATIENT.NO_PATIENT = PATIENT.NO_PATIENT); 

end SP_UPDATE_INDICE_METABO_DV; 
/

我得到一個錯誤:編譯程序,錯誤檢查編譯日誌。

但我無法打開編譯器日誌,當我的朋友打開它時,它指向奇怪的地方,比如我的創建表等。

這是學校的事情,所以如果您能夠提供洞察力而不是直接的解決方案,那將會很好。非常感謝。

非常感謝您的善意幫助!

+0

不應該有一個循環處理從遊標中獲取的行嗎? –

+0

你還沒有說過是什麼問題。你是否收到編譯錯誤,運行時錯誤,錯誤的結果?你爲什麼在程序中這樣做?爲什麼不直接在查詢中使用'avg()'聚合函數,或者直接在update語句中使用'avg()'聚合函數? –

+0

告訴我們*不*工作會有多大幫助。你得到一個編譯錯誤?不正確的結果? –

回答

2

要在程序創建語句後查看錯誤,您可以執行show errors,或者您可以查詢user_errorsall_errors views

,將顯示類似:

LINE/COL ERROR 
-------- ------------------------------------------------------------------------ 
20/4  PLS-00376: illegal EXIT/CONTINUE statement; it must appear inside a loop 
20/4  PL/SQL: Statement ignored 

你提到,當你檢查編譯日誌,其中顯示了相同的信息,「它指向奇怪的地方。」據推測,你正在腳本中查看第20行。但是這條消息指的是PL/SQL代碼塊的第20行,它是exit when curseur%NOTFOUND;,這對於錯誤消息是有意義的。

而且正如該消息所述,並且@ammoQ在評論中表示,這應該是一個循環。如果你想手動計算過程的平均值作爲一個練習,而不是使用內置的聚合功能,那麼你需要遍歷所有從你的光標行:

open curseur; 
loop 
    fetch curseur into V_SOMME; 
    exit when curseur%NOTFOUND; 
    V_NBPATIENT := V_NBPATIENT + 1; 
end loop; 
close curseur; 

但作爲你很快就會意識到,你將最終得到v_somme變量檢索到的最後一個值,而不是所有值的總和。您需要一個單獨的變量來跟蹤總和 - 將每個值提取到變量中,並將其添加到循環中的所有運行總數中。但是按照要求,沒有提供完整的解決方案。


在開始的時候,你應該真的使用ANSI連接語法,而不是現在使用的語法。這是一個恥辱,仍然被教導。所以,你的光標查詢應該是這樣的:

select PATIENT.INDICE_EFFICACITE_METABO_PAT 
from ETUDE_PATIENT 
join ETUDE 
-- missing on clause ! 
join DROGUE_VARIANT 
on DROGUE_VARIANT.NO_DROGUE = ETUDE.NO_DROGUE 
and DROGUE_VARIANT.NO_VAR_GEN = ETUDE.NO_VAR_GEN 
join PATIENT 
on PATIENT.NO_PATIENT = ETUDE_PATIENT.NO_PATIENT 
where ETUDE_PATIENT.NO_ETUDE = P_NO_ETUDE; 

...這表明你,你缺少ETUDE_PATIENT和ETUDE之間的連接狀態 - 這是不可能的,你想一個笛卡爾乘積,並發現失蹤它更容易加入使用這種語法比你有什麼。


您還需要仔細看看您的更新聲明,特別是exists條款。如果光標發現任何內容,基本上總是會返回true,所以它會更新DROGUE_VARIANT中的每一行,並計算出平均值,這可能不是您想要的。

您正在更新的表中的行與該子句中的子查詢之間沒有關聯 - 子查詢中的DROGUE_VARIANT獨立於您正在更新的DROGUE_VARIANT。我的意思是,這顯然是同一張桌子;但是更新和子查詢分別查看錶,並查看不同的行。它也具有與遊標查詢相同的缺失連接條件。

+0

好吧,非常感謝每個人,我現在正在上班的路上,我會在今晚稍後看這個。 另外@Alex Poole,我們正在接受幾種加入方法,但是我只能用from/where方法得到結果。我喜歡你給我的例子,我會盡力讓我的關節像現在這樣! (對不起Engrish) – CBinet