2010-04-09 61 views
3

我一直在玩pluto-test-framework今天,我想用它來獲得一些現有的功能。在兩個Oracle類型的每一列中比較值

我有這種類型的規範很多功能。

FUNCTION DO_SOME_STUFF (pOldSchedule  IN  SCHEDULE_OBJ, 
          pNewSchedule   OUT SCHEDULE_OBJ, 
          pLoggerContext  IN OUT LOGGER_CONTEXT_OBJ) 
    RETURN NUMBER; 

它需要pOldSchedule,做一些東西,然後返回pNewSchedule。 logger_context只是記錄。

作爲測試的一部分,我希望能夠比較每個類型的列中的值,而不必編寫單獨的IF語句。

它需要返回布爾值來表示pOldSchedule和pNewSchedule是否匹配。

任何想法?

回答

6

直白平等的測試與嵌套表格的工作:

SQL> declare 
    2  type nt is table of number; 
    3  nt1 nt; 
    4  nt2 nt; 
    5  nt3 nt; 
    6 begin 
    7  nt1 := nt(1,2,3); 
    8  nt2 := nt(1,2,3); 
    9  if nt1 = nt2 then 
10   dbms_output.put_line('NT2 is the same nested table as NT1'); 
11  else 
12   dbms_output.put_line('NT2 is a different nested table from NT1'); 
13  end if; 
14  nt2 := nt(1,2,3,4); 
15  if nt1 = nt3 then 
16   dbms_output.put_line('NT3 is the same nested table as NT1'); 
17  else 
18   dbms_output.put_line('E3 is a different nested table from NT1'); 
19  end if; 
20 end; 
21/
NT2 is the same nested table as NT1 
E3 is a different nested table from NT1 

PL/SQL procedure successfully completed. 

SQL> 

然而同樣是不完整的對象的真實:

SQL> create or replace type new_emp as object (
    2  ename varchar2(10) 
    3  , sal number 
    4  , deptno number 
    5  , job varchar2(10)) 
    6/

Type created. 

SQL> declare 
    2  e1 new_emp; 
    3  e2 new_emp; 
    4 begin 
    5  e1 := new_emp('KESTELYN', 3700, 30, 'MARKETING'); 
    6  e2 := new_emp('KESTELYN', 3700, 30, 'MARKETING'); 
    7  if e1 = e2 then 
    8   dbms_output.put_line('E2 is the same as E1'); 
    9  else 
10   dbms_output.put_line('E2 is different from E1'); 
11  end if; 
12 end; 
13/
    if e1 = e2 then 
      * 
ERROR at line 7: 
ORA-06550: line 7, column 11: 
PLS-00526: A MAP or ORDER function is required for comparing objects in PL/SQL. 


SQL> 

我們需要明確地定義一個成員函數用於執行比較。所以這裏是與MAP函數相同的對象。該示例實現會生成一個散列字符串,如果我們想要存儲該值以供以後比較,它會很有用,但它可能只是返回串聯字符串(特別是因爲DBMS_CRYPTO上的EXECUTE未默認授予)。 NVL()函數有必要避免(null,value)和(value,null)被評估爲相等。使用魔法值時總會有風險,所以我們需要仔細選擇它們。

SQL> create or replace type new_emp as object (
    2  ename varchar2(10) 
    3  , sal number 
    4  , deptno number 
    5  , job varchar2(10) 
    6  , map member function equals return raw) 
    7/

Type created. 

SQL> create or replace type body new_emp as 
    2  map member function equals return raw 
    3  is 
    4  begin 
    5   return dbms_crypto.hash(
    6      utl_raw.cast_to_raw(nvl(self.ename,'***')|| 
    7           nvl(self.sal,-99)|| 
    8           nvl(self.deptno,-99)|| 
    9           nvl(self.job,'***') 
10          ) 
11         , 1); 
12  end equals; 
13 end; 
14/

Type body created. 

SQL> 

現在我們有我們的比較對象的實例的基礎:

SQL> declare 
    2  e1 new_emp; 
    3  e2 new_emp; 
    4 begin 
    5  e1 := new_emp('KESTELYN', 3700, 30, 'MARKETING'); 
    6  e2 := new_emp('KESTELYN', 3700, 30, 'MARKETING'); 
    7  if e1 = e2 then 
    8   dbms_output.put_line('E2 is the same as E1'); 
    9  else 
10   dbms_output.put_line('E2 is different from E1'); 
11  end if; 
12 end; 
13/
E2 is the same as E1 

PL/SQL procedure successfully completed. 

SQL>  

你可能會奇怪,爲什麼Oracle不默認情況下做到這一點。那麼,TYPE實現只允許一個比較方法(如果我們有一個MAP函數,我們不能有一個ORDER函數),所以我們需要有能力選擇我們自己的相等定義。例如,稱爲rectangle的類型可能具有稱爲area()的MAP函數,該函數返回self.width * self.length