Frage

I'm running into a bit of an issue with using oracle object types. My member function is compiling with errors.

Here's the type:

 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;

My SELECT INTO is not working. It's telling me I have invalid identifiers. If I want to write a member function to return the highest quantity order for a customer, do I query the table of Order, or can I use the object reference? I also tried creating views to no avail.

This is the easiest I could simplify it, I also am going to need to write some other methods, but none of the ones where I need to SELECT INTO work as of now.

Errors are SELF.custid INVALID IDENTIFIER and Component 'custid' must be declared. Thanks

EDIT: SELECT INTO pl/sql queries to access object types and their views must be aliased. After adding aliases, my problems were solved. Thanks for the help though - I posted the solution and a couple of examples.

War es hilfreich?

Lösung 4

You must use an alias to access Object fields in Oracle. (11g)

Examples:

Wrong SELECT Order.quantity FROM Customers

Wrong SELECT Customers.Order.quantity FROM Customers

Right SELECT cc.Order.quantity FROM Customers cc

I assumed that the second option in the list would work, but it doesnt. You have to use an alias.

Working example as per request:

       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;
    /

The line inside the function body can be switched out for the correct aliased version. SELECT Max(e.ord.quantity) INTO v_maxval FROM OrderOV e WHERE e.ord.customer.custID = self.custID;

You can paste this whole script to test, it compiles when you switch the line in question with the correct line I listed.

Andere Tipps

First thing is that you shouldn't name a table 'Order' - it's an Oracle reserved word.

Secondly, your member function is named getHighestOrder in the type spec and getHighest in the type body.

Thirdly, you're missing an 'end;' at the end of the t_Customer type body.

Fourthly, in your sql you are joining on custID, which is inconsistently typed. What you should do is use DEREF, then compare the result to self.

The code below shows these fixes.

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;

This should be close to what you need. Use the code below to test.

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;
/

You have different function names in header and body:

getHighestOrder

vs

getHighest

ORDER is a reserved word, so

CREATE TABLE Order of t_Order; 

... gets:

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

You could double-quote it but better just to avoid the issue and use different names. If I change the tables to orders and customers (and make the method name consistent) I get this:

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

I don't see how you're getting the error you're posting, so I can only assume you've mixed up different versions of code and errors somehow. Anyway...

You need to DEREF the t_customer object, and to make that a bit clearer I suggest you don't use CustID to mean inconsistent things:

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.

You could also do this:

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

... but that would only make sense if you had different customers with the same ID, and you wanted to include all of them in the count.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top