我在高级数据库类中有一个有趣的问题,给我带来了一些麻烦。
第一步是创建一个我已经完成的对象,如下所示:
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.
答案 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
,因为呼叫者不会启用该功能,但这似乎是分配的一部分。