0

我在使用 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 查询必须是别名。添加别名后,我的问题就解决了。不过感谢您的帮助-我发布了解决方案和几个示例。

4

4 回答 4

2

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;
/
于 2013-05-04T07:53:51.713 回答
1

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.

于 2013-05-04T07:56:40.893 回答
1

标题和正文中有不同的函数名称:

getHighestOrder

对比

getHighest
于 2013-05-04T07:24:29.813 回答
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;
    /

可以将函数体内的行切换为正确的别名版本。 SELECT Max(e.ord.quantity) INTO v_maxval FROM OrderOV e WHERE e.ord.customer.custID = self.custID;

您可以粘贴整个脚本进行测试,当您使用我列出的正确行切换有问题的行时,它会编译。

于 2013-05-04T19:42:59.220 回答