2013-05-03 96 views
0

我遇到了一些使用oracle對象類型的問題。我的成員函數正在編譯時出錯。在SELECT對象中遇到問題在Oracle對象類型成員函數

這裏的類型:

CREATE OR REPLACE TYPE t_Customer as OBJECT 
(custID NUMBER 
    ,fname varchar2(50) 
    ,lname varchar2(50) 
    ,MEMBER FUNCTION getHighest RETURN INTEGER 
); 

CREATE OR REPLACE TYPE t_Order AS OBJECT 
(OrderID NUMBER, custID REF t_Customer, quantity INTEGER); 

CREATE TABLE Order_Tbl of t_Order; 
CREATE TABLE Customer_Tbl of t_Customer; 

CREATE OR REPLACE TYPE BODY t_Customer AS 
    MEMBER FUNCTION getHighest RETURN INTEGER IS 
    v_max integer; 
    BEGIN 
     SELECT Max(Order.quantity) INTO v_max FROM Order WHERE Order.CustID = self.custID; 
     return v_max; 
    end; 

我的SELECT INTO不工作。它告訴我我有無效的標識符。如果我想寫一個成員函數來爲客戶返回最高數量的訂單,我可以查詢Order的表嗎,還是可以使用對象引用?我也嘗試創建視圖無濟於事。

這是最簡單的,我可以簡化它,我也需要寫一些其他方法,但沒有一個我需要SELECT INTO現在的工作。

錯誤是SELF.custid INVALID IDENTIFIERComponent 'custid' must be declared. 感謝

編輯:SELECT INTO PL/SQL查詢來訪問對象類型和他們的觀點必須別名。添加別名後,我的問題解決了。感謝您的幫助 - 我發佈瞭解決方案和幾個例子。

+0

狂猜:ORDER是SQL子句「order by」的一部分,也許這就是錯誤的原因 - 嘗試使用模式名稱的前綴順序。 – 2013-05-04 07:22:13

+0

@FrankSchmitt對不起,我的例子中有一些不一致(這是其中之一)。他們不會給我我抱怨的錯誤,但我糾正了我的例子,以避免混淆。 – Scotch 2013-05-04 19:45:02

回答

1

您必須使用別名來訪問Oracle中的對象字段。 (11克)

實例:

錯誤 SELECT Order.quantity FROM Customers

錯誤 SELECT Customers.Order.quantity FROM Customers

SELECT cc.Order.quantity FROM Customers cc

我認爲列表中的第二個選項可以工作,但它沒有。你使用別名。

工作實施例爲每個請求:

 DROP Table tblCustomer; 
DROP Table tblOrders; 
CREATE OR REPLACE TYPE t_Customer as OBJECT 
    (custID varchar2(20) 
    ,lastname varchar2(50) 
    ,firstname varchar2(50) 
    ,member function getHighest RETURN NUMBER 
); 
/
CREATE OR REPLACE TYPE t_Orders AS OBJECT 
    (OrderID Number 
    ,Customer REF t_Customer 
    ,quantity NUMBER 
); 
/
CREATE TABLE tblOrders of t_orders; 
CREATE TABLE tblCustomer of t_Customer; 

CREATE OR REPLACE VIEW OrderOV(ord) AS 
    SELECT t_orders(OrderID, Customer, quantity) FROM tblOrders; 
/
    CREATE OR REPLACE VIEW CustomerOV(cust) AS 
    SELECT t_customer(custID, lastname, firstname) FROM tblCustomer; 
/

    CREATE OR REPLACE TYPE BODY t_Customer AS 
     MEMBER Function getHighest RETURN NUMBER IS 
     v_maxval NUMBER; 

     BEGIN 

    SELECT max(orderOV.ord.quantity) INTO v_maxval FROM OrderOV WHERE OrderOV.ord.custID = self.CustID; 
     END; 
    end; 
    /

函數體內部的線可爲正確的版本別名來切換的。

您可以粘貼這整個腳本進行測試,它會在您使用我列出的正確線切換問題行時編譯。

+0

你可以展示一個完整的工作示例,其中前兩個失敗,但第三個作品? – 2013-05-04 23:30:53

+0

@AlexPoole如果你堅持。用一個例子更新我的答案。 – Scotch 2013-05-05 21:31:25

1

你在標題和正文不同的函數名稱:

​​3210

VS

getHighest 
2

的第一件事是,你不應該命名錶「訂單」 - 這是一個Oracle的保留字。其次,你的成員函數在類型規範中被命名爲getHighestOrder,在類型主體中被命名爲getHighest。

第三,你錯過了'結束';在t_Customer類型主體的末尾。

第四,在你的SQL你加入custID,這是不一致的類型。你應該做的是使用DEREF,然後將結果與自己進行比較。

下面的代碼顯示了這些修復程序。

CREATE OR REPLACE TYPE t_Customer as OBJECT 
(custID NUMBER 
,fname varchar2(50) 
,lname varchar2(50) 
,MEMBER FUNCTION getHighest RETURN INTEGER 
); 

CREATE OR REPLACE TYPE t_Order AS OBJECT 
(OrderID NUMBER, cust REF t_Customer, quantity INTEGER); 

CREATE TABLE OrderA of t_Order; 
CREATE TABLE Customer of t_Customer; 

CREATE OR REPLACE TYPE BODY t_Customer AS 

MEMBER FUNCTION getHighest RETURN INTEGER IS 
v_max integer; 
BEGIN 
    SELECT Max(OrderA.quantity) 
    INTO v_max 
    FROM OrderA 
    WHERE DEREF(OrderA.cust) = self; 

    return v_max; 

end; 
end; 

這應該是接近你所需要的。使用下面的代碼來測試。

declare 

    cust t_customer := t_customer (1, 'John','Smith'); 

begin 

    insert into customer values (cust); 

    insert into orderA (OrderID, cust, quantity) 
    select 10, ref(c) , 7 
    from customer c 
    where custID = 1; 

    insert into orderA (OrderID, cust, quantity) 
    select 11, ref(c) , 15 
    from customer c 
    where custID = 1; 

    dbms_output.put_line(cust.getHighest); 

end; 
/
+0

除非您更改't_order'對象中的'REF'名稱,並且您仍在混合Order,Order1和OrderA,否則應該是'DEREF(OrderA.custID)'。但我只是挑剔,因爲你打我 2013-05-04 08:01:46

+0

這會教我沒有足夠的測試!我什麼時候才能學會... – TonyB 2013-05-04 08:04:53

+0

現在修正了錯別字... – TonyB 2013-05-04 08:39:27

1

ORDER是一個保留字,所以

CREATE TABLE Order of t_Order; 

...獲得:

CREATE TABLE Order of t_Order 
      * 
ERROR at line 1: 
ORA-00903: invalid table name 

你可以雙引號,但只是爲了更好地避免這個問題,並使用不同的名稱。如果我更改了表,orderscustomers(以及使該方法的名稱一致)我得到這樣的:

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
5/6  PL/SQL: SQL Statement ignored 
5/79  PL/SQL: ORA-00932: inconsistent datatypes: expected REF got 
     NUMBER 

我不知道你是如何讓您發佈的錯誤,所以我只能假設你已經混淆了不同版本的代碼和錯誤。無論如何...

您需要DEREF的t_customer對象,並做出更清楚一點,我建議你不要使用CustID意味着不一致的事情:

CREATE OR REPLACE TYPE t_Order AS OBJECT 
(OrderID NUMBER, custRef REF t_Customer, quantity INTEGER); 
/

CREATE TABLE Orders of t_Order; 
CREATE TABLE Customers of t_Customer; 

CREATE OR REPLACE TYPE BODY t_Customer AS 
    MEMBER FUNCTION getHighestOrder RETURN INTEGER IS 
    v_max INTEGER; 
    BEGIN 
    SELECT Max(Orders.quantity) 
    INTO v_max 
    FROM Orders 
    WHERE DEREF(Orders.custRef) = self; 
    RETURN v_max; 
    END getHighestOrder; 
END; 
/

Type body created. 

No errors. 

你也可以這樣做:

WHERE DEREF(Orders.custRef).custID = self.custID; 

......但這隻有在你有不同的客戶具有相同的ID時纔有意義,並且你想將他們全部納入計數。