Oracle
具有非標量類型的嵌套表上的多重集運算符
我有一個函式,它對兩個嵌套表執行多重操作並返回結果:
function odejmijEgz(tab typ_NT) return typ_NT is tab1 typ_NT := typ_NT(); cursor c_osr_egz is select distinct o.id_osrodek oid, o.nazwa_o nazwa_o from egzaminy e right join osrodki o on e.id_osrodek = o.id_osrodek where e.id_osrodek is null; i number; begin for v_osr in c_osr_egz loop i := c_osr_egz%rowcount; tab1.extend; tab1(i) := v_osr; end loop; return tab multiset except tab1; end odejmijEgz;
其中類型在 pl/sql 塊中聲明:
type typ_Rec is record(Id osrodki.id_osrodek%type, Nazwa osrodki.nazwa_o%type); type typ_NT is table of typ_Rec;
該函式的參數是嵌套表,填充有記錄。
當我
multiset except
在函式中使用時出現錯誤:Error: PLS-00306: wrong number or types of arguments in call to 'MULTISET_EXCEPT_ALL'
但是,如果我將其更改為
multiset union
有效。這些表屬於同一類型。那有什麼問題?
嵌套表的元素類型必須是可比較的。
如果兩個非標量類型的對象具有相同的命名類型並且它們的元素之間存在一一對應關係,則它們是可比較的。此外,使用者定義對像類型的嵌套表,即使它們的元素是可比較的,也必須在其上定義 MAP 方法,以便在相等或 IN 條件下使用。
問題是,以上不能用
record
類型來完成。record
類型只有欄位,不能有成員函式。此外:無法在本地測試記錄的無效性、平等性或不平等性。
這些 BOOLEAN 表達式是非法的:
- My_Record 為空
- 我的記錄_1 = 我的記錄_2
- 我的_記錄_1 > 我的_記錄_2
這失敗了:
create or replace package p1 as type typ_Rec is record(id customers.customer_id%type, name customers.cust_first_name%type); type typ_NT is table of typ_Rec; function f1 (tab typ_NT) return typ_NT; end; / Package created. create or replace package body p1 as function f1 (tab typ_NT) return typ_NT as tab1 typ_NT := typ_NT(); begin return tab multiset except tab1; end; end; / Warning: Package Body created with compilation errors. SQL> show errors Errors for PACKAGE BODY P1: LINE/COL ERROR -------- ----------------------------------------------------------------- 5/5 PL/SQL: Statement ignored 5/12 PLS-00306: wrong number or types of arguments in call to 'MULTISET_EXCEPT_ALL'
UNION
有效,因為您沒有指定ALL
orDISTINCT
,在這種情況下,UNION ALL
是預設值。UNION ALL
不需要進行比較。但是,如果您嘗試UNION DISTINCT
(刪除重複項),那也將失敗:create or replace package body p1 as function f1 (tab typ_NT) return typ_NT as tab1 typ_NT := typ_NT(); begin return tab multiset union distinct tab1; end; end; / Warning: Package Body created with compilation errors. SQL> show errors Errors for PACKAGE BODY P1: LINE/COL ERROR -------- ----------------------------------------------------------------- 5/5 PL/SQL: Statement ignored 5/12 PLS-00306: wrong number or types of arguments in call to 'MULTISET_UNION_DISTINCT'
你需要一個
object
類型。create or replace type typ_Obj as object ( id number(6), name varchar2(20) ); / Type created. create or replace package p1 as type typ_NT is table of typ_Obj; function f1 (tab typ_NT) return typ_NT; end; / Package created. create or replace package body p1 as function f1 (tab typ_NT) return typ_NT as tab1 typ_NT := typ_NT(); begin return tab multiset except tab1; end; end; / Warning: Package Body created with compilation errors. SQL> show errors Errors for PACKAGE BODY P1: LINE/COL ERROR -------- ----------------------------------------------------------------- 5/5 PL/SQL: Statement ignored 5/12 PLS-00306: wrong number or types of arguments in call to 'MULTISET_EXCEPT_ALL'
注意它仍然失敗,因為我沒有定義
MAP
函式,我沒有告訴數據庫它如何比較兩個使用者定義的對象。現在再試一次,這次定義MAP
(這裡我假設對像有唯一的標識符,如果它們的標識符相等,則兩個對象相等):create or replace type typ_Obj as object ( id number(6), name varchar2(20), MAP MEMBER FUNCTION get_idno RETURN NUMBER ); / Type created. CREATE or replace TYPE BODY typ_Obj AS MAP MEMBER FUNCTION get_idno RETURN NUMBER IS BEGIN RETURN id; END; END; / Type body created. create or replace package body p1 as function f1 (tab typ_NT) return typ_NT as tab1 typ_NT := typ_NT(); begin return tab multiset except tab1; end; end; / Package body created.
最後它起作用了,沒有警告。