创建和添加对象成员过程和函数-ORACLE-

时间:2018-07-18 21:09:32

标签: database oracle plsql user-defined-types

我在高级数据库类中有一个有趣的问题,给我带来了一些麻烦。

第一步是创建一个我已经完成的对象,如下所示:

CREATE OR REPLACE TYPE EmployeeObj AS OBJECT
(
    EmployeeID      NUMBER,
    LastName        VARCHAR2(100),
    FirstName       VARCHAR2(100),
    AddressLine1    VARCHAR2(100),
    AddressLine2    VARCHAR2(100),
    City            VARCHAR2(100),
    State           VARCHAR2(100),
    Zip             VARCHAR2(10),
    StartDate       DATE,
    EndDate         DATE,
    JobTitle        VARCHAR2(100),
    MEMBER PROCEDURE Display, 
    MEMBER FUNCTION DaysOnJob RETURN NUMBER
);

接下来,它要求创建一个显示所有字段的成员过程。然后,它要求使用SYSDATE创建一个成员函数,以显示自作业开始以来的天数。我想我做得很好,如下所示:

CREATE TYPE BODY EmployeeObj AS

    MEMBER PROCEDURE Display IS
        BEGIN
            DBMS_OUTPUT.PUT_LINE('EmployeeID: ' || EmployeeID);
            DBMS_OUTPUT.PUT_LINE('Name: ' || FirstName ||', '|| LastName);
            DBMS_OUTPUT.PUT_LINE('Address: ' || AddressLine1 || ', ' ||  AddressLine2 || ' ' || City || ', '|| State || ' '|| Zip);
            DBMS_OUTPUT.PUT_LINE('Start Date: ' || StartDate);
            DBMS_OUTPUT.PUT_LINE('EndDate: ' || EndDate);
            DBMS_OUTPUT.PUT_LINE('Job Title: ' || JobTitle);
            DBMS_OUTPUT.PUT_LINE('Days On Job: ');
        END Display;

     MEMBER FUNCTION DaysOnJob RETURN NUMBER IS 
        BEGIN
            IF EndDate = 'NULL' THEN
                RETURN SYSDATE - StartDate;           
                    ELSE IF EndDate != 'NULL' THEN
                        RETURN EndDate - StartDate; 
                    END IF;
            END IF;
        END DaysOnJob;

END;
/

最后,它要求我创建一个我创建的对象的实例,并调用DISPLAY成员过程以将该实例输出到屏幕上。这是我遇到的麻烦。当我运行此代码时:

DECLARE 
    --This is null initially--
    myEmployee EmployeeObj;
BEGIN
    --building the object--
    myEmployee := EmployeeObj(1234, 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL', '1234', '01-JAN-98', '01-JUL-18', 'Software Engineer');
    myEmployee.Display;

END;
/

一切正常,但是如果我尝试从该过程中调用DaysOnJob函数,会遇到各种错误吗?

有人知道如何从过程中正确调用成员函数,以便我可以将工作天数作为对象的“显示”过程的一部分输出。

任何帮助将不胜感激。以下是我的实现和收到的错误消息。

CREATE TYPE BODY EmployeeObj AS

    MEMBER PROCEDURE Display IS
        BEGIN
            DBMS_OUTPUT.PUT_LINE('EmployeeID: ' || EmployeeID);
            DBMS_OUTPUT.PUT_LINE('Name: ' || FirstName ||', '|| LastName);
            DBMS_OUTPUT.PUT_LINE('Address: ' || AddressLine1 || ', ' ||  AddressLine2 || ' ' || City || ', '|| State || ' '|| Zip);
            DBMS_OUTPUT.PUT_LINE('Start Date: ' || StartDate);
            DBMS_OUTPUT.PUT_LINE('EndDate: ' || EndDate);
            DBMS_OUTPUT.PUT_LINE('Job Title: ' || JobTitle);
            DBMS_OUTPUT.PUT_LINE('Days On Job:' || DaysOnJob);
        END Display;

     MEMBER FUNCTION DaysOnJob RETURN NUMBER  IS
        BEGIN
            IF EndDate IS NULL THEN
                RETURN SYSDATE - StartDate;           
                    ELSE IF EndDate IS NOT NULL THEN
                        RETURN EndDate - StartDate; 
                    END IF;
            END IF;
        END DaysOnJob;

END;
/
 --4. Creating Instance of EmployeeObj--
DECLARE 
    --This is null initially--
    myEmployee EmployeeObj;

BEGIN
    --building the object--
    myEmployee := EmployeeObj(1234, NULL, NULL, NULL, NULL, NULL, NULL, NULL, date '2018-01-01', date '2018-07-01', 'Software Engineer');
    myEmployee.Display;


END;
/

错误在下面

DECLARE 
    --This is null initially--
    myEmployee EmployeeObj;

BEGIN
    --building the object--
    myEmployee := EmployeeObj(1234, NULL, NULL, NULL, NULL, NULL, NULL, NULL, date '2018-01-01', date '2018-07-01', 'Software Engineer');
    myEmployee.Display;


END;
Error report -
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at "MILLERJL6.EMPLOYEEOBJ", line 16
ORA-06512: at "MILLERJL6.EMPLOYEEOBJ", line 11
ORA-06512: at line 8
01858. 00000 -  "a non-numeric character was found where a numeric was expected"
*Cause:    The input data to be converted using a date format model was
           incorrect.  The input data did not contain a number where a number was
           required by the format model.
*Action:   Fix the input data or the date format model to make sure the
           elements match in number and type.  Then retry the operation.

2 个答案:

答案 0 :(得分:2)

您正在将日期与字符串进行比较以检查Matrix;如果要检查值是否为null,则null是正确的方法:

is [not] null

MEMBER FUNCTION DaysOnJob RETURN NUMBER IS 
BEGIN
    IF EndDate is null THEN
        RETURN SYSDATE - StartDate;           
            ELSE IF EndDate is not null THEN
                RETURN EndDate - StartDate; 
            END IF;
    END IF;
END DaysOnJob;

甚至

MEMBER FUNCTION DaysOnJob RETURN NUMBER IS 
BEGIN
    IF EndDate is null THEN
        RETURN SYSDATE - StartDate;           
    ELSE 
        RETURN EndDate - StartDate; 
    END IF;
END DaysOnJob;

此外,与依赖NLS设置相比,更好地使用ANSI日期格式:

MEMBER FUNCTION DaysOnJob RETURN NUMBER IS 
BEGIN
    RETURN nvl(EndDate, sysdate) - StartDate; 
END DaysOnJob;

答案 1 :(得分:2)

函数返回一个值,因此您需要将其赋值给变量:

DECLARE 
    myEmployee EmployeeObj;
    days number;
BEGIN
    myEmployee := EmployeeObj(1234, 'NULL', 'NULL', 'NULL', 'NULL',
        'NULL', 'NULL', '1234', date '1998-01-01', date '2018-07-01',
        'Software Engineer');
    myEmployee.Display;
    days := myEmployee.daysOnJob;
    dbms_output.putline(days):
END;
/

或可以直接使用它:

    dbms_output.put_line(myEmployee.daysOnJob);

或以文本开头-这大概是您在过程中所需要的:

DBMS_OUTPUT.PUT_LINE('Days On Job: ' || daysOnJob);

您应该将日期传递给构造函数,而不是字符串。可以使用我完成的日期文字,也可以使用to_date()。不要依赖隐式转换或NLS设置。

几乎可以肯定,您想传递null(不带引号),而不是传递其他参数的文字字符串'NULL',但这还不是很清楚。

您也不应该依赖dbms_output,因为呼叫者不会启用该功能,但这似乎是分配的一部分。