2013-08-28 79 views
1

我有2個表具有相同的列名稱(52 +庫侖)。我需要編寫一個Oracle函數來比較這些列之間是否有任何記錄發生了變化。 EMP_ID是主鍵Oracle函數硬編碼列名稱作爲參數

我嘗試使用下面的功能,但它給我的不正確的結果, 我打電話這樣的funcaiton:

get_data_change (emp_id, 'DEPT_NAME'); 
get_data_change (emp_id, 'PHONE_NUMBER'); 

功能我已經創建了:

CREATE OR REPLACE function get_data_change (
    in_emp_id varchar2, in_Column_Name varchar2) 
return char is 

    v_data_changed char; 
begin 
    select eid, in_Column_Name 
    into v_table1_eid, v_table1_Column_Value 
    from table 1 
    where eid=in_emp_id; 

    Select eid, in_Column_Name 
    into v_table2_eid, v_table2_Column_Value 
    from table 2 
    where eid = in_emp_id; 


    if (v_table2_Column_Value != v_table1_Column_Value) 
    then 
    v_data_changed := 'Y' 
    else 
    v_data_changed :='N' 
    endif 
    return v_data_changed 
end 
end get_data_change; 
+2

正如@JeffreyKemp已經指出的那樣,您需要動態SQL來實現這一點。此外,如果其中一個值爲NULL,則檢查兩個值是否不同(v_table2_column_value!= v_table1_column_value)將無法按預期工作 - 您需要對NULL值進行特殊處理。 –

回答

2

in_Column_Name是一個字符串變量,您可以爲其指定文字字符串值,如'DEPT_NAME'

因此,您的查詢將其解釋爲字符串值並將相同的內容返回到v_table1_Column_Value

要做到你所期望的,你需要使用動態SQL,是這樣的:

EXECUTE IMMEDIATE 'select eid, ' || in_Column_Name 
       || ' from table1 where eid=:P_emp_id' 
into v_table1_eid, v_table1_Column_Value 
using in_emp_id; 

你需要知道的SQL注入的可能性在這裏 - 即in_Column_Name的價值不能被最終提供用戶。

+0

你好傑夫,謝謝你的迴應。有效 :)。 – Ragav

+0

我有2個問題。 1.)這是什麼:P_emp_id?這是什麼影響? 2.)我沒有得到當你的意思in_Column_Name不能由最終用戶提供?即時通訊使用get_data_change(emp_id,'DEPT_NAME');調用它..它工作正常。在哪個上下文中提到這個..欣賞你對此的意見..再次感謝解決方案。 – Ragav

+1

@balaji - ':P_emp_id'是一個綁定變量標記;運行時,'using'子句將'in_emp_id'的值放入該變量中。這是更高效,更重要的是防止惡意值被提供。但是,這隻適用於值,列名不能綁定,因此必須連接。 'in_Column_Name'的令人討厭的值可能會讓你做一些你不期望的事情。 (搜索'小鮑比表')。您可以使用['dbms_assert.simple_sql_name'](http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_assert.htm#BABHIEBA)來降低風險,但仍然要小心。 –