从 2 个 REF 列中获取两个日期之间的差异
Posted
技术标签:
【中文标题】从 2 个 REF 列中获取两个日期之间的差异【英文标题】:Getting difference between two dates from 2 REF'd columns 【发布时间】:2017-10-06 07:59:36 【问题描述】:我是 SQL 新手,我正在尝试获取两个 REF 列值之间的两个值之间的日期。 我目前的表格设置如下:
CREATE OR REPLACE TYPE Person_Type AS OBJECT
(PersonId NUMBER,
DateBorn DATE)
CREATE OR REPLACE TYPE Movie_Type AS OBJECT
(MovieId NUMBER,
ReleaseDate DATE)
CREATE OR REPLACE TYPE Role_Type AS OBJECT
(PersonId REF Person_Type,
MovieId REF Movie_Type,
Name VARCHAR2(40),
MAP MEMBER FUNCTION Actor_Age RETURN NUMBER)
数据是这样插入的:
INSERT INTO Person_Table
VALUES (10000, '11-NOV-1974')
INSERT INTO Movie_Table
VALUES(1000000, '19-DEC-1997')
INSERT INTO Role_Table
VALUES((SELECT REF(a) FROM Person_Table a WHERE a.PersonId = 10000),
(SELECT REF(b) FROM Movie_Table b WHERE b.MovieId = 1000000),
'Some Person')
我试图让 Actor_Age 方法返回某人出生日期与电影上映日期之间的差异。我已经尝试了以下,但它不会编译..
CREATE OR REPLACE TYPE BODY Role_Type
AS
MAP MEMBER FUNCTION Actor_Age
RETURN NUMBER
IS
BEGIN
RETURN (MONTHS_BETWEEN((SELECT g.PersonId.DateBorn FROM Role_Table g),
(SELECT f.MovieId.Releasedate FROM Role_Table f)/12));
END;
END;
【问题讨论】:
也为 3 个表发布 DDL。 已更新。你的意思是表格插入对吗? 没有。我需要表Movie_Table
、Person_Table
和Role_Table
的表DDL(结构脚本)
@XING - 从类型中不言自明 - CREATE TABLE Person_table OF Person_Type;
@lesovren '11-NOV-1974'
不是 DATE
它是一个字符串文字 - Oracle 将尝试使用 TO_DATE
和 NLS_DATE_FORMAT
会话参数作为格式模型将其隐式转换为日期;但是,该会话参数可以由用户随时更改,并且会在不同的国家和语言之间改变其默认值(导致有趣且难以调试的问题)。更好的做法是使用日期文字 DATE '1974-11-11'
或明确声明格式模型(和语言)TO_DATE( '11-NOV-1974', 'DD-MON-YYYY', 'NLS_DATE_LANGUAGE=''ENGLISH''' )
【参考方案1】:
SQL Fiddle
Oracle 11g R2 架构设置:
CREATE OR REPLACE TYPE Person_Type AS OBJECT
(PersonId NUMBER,
DateBorn DATE)
/
CREATE OR REPLACE TYPE Movie_Type AS OBJECT
(MovieId NUMBER,
ReleaseDate DATE)
/
CREATE OR REPLACE TYPE Role_Type AS OBJECT
(PersonId REF Person_Type,
MovieId REF Movie_Type,
Name VARCHAR2(40),
MAP MEMBER FUNCTION Actor_Age RETURN NUMBER)
/
CREATE OR REPLACE TYPE BODY Role_Type
AS
MAP MEMBER FUNCTION Actor_Age
RETURN NUMBER
IS
p_age NUMBER;
BEGIN
SELECT MONTHS_BETWEEN(
DEREF( MovieID ).ReleaseDate,
DEREF( PersonID ).DateBorn
) / 12
INTO p_age
FROM DUAL;
RETURN p_age;
END;
END;
/
CREATE TABLE Person_Table OF Person_Type
/
CREATE TABLE Movie_Table OF Movie_Type
/
CREATE TABLE Role_Table OF Role_Type
/
INSERT INTO Person_Table VALUES ( 10000, DATE '1970-01-01' )
/
INSERT INTO Movie_Table VALUES ( 1000000, DATE '2000-01-01' )
/
INSERT INTO Role_Table VALUES(
(SELECT REF(a) FROM Person_Table a WHERE a.PersonId = 10000),
(SELECT REF(b) FROM Movie_Table b WHERE b.MovieId = 1000000),
'Some Person'
)
/
查询 1:
SELECT Name,
r.Actor_Age()
FROM Role_table r
Results:
| NAME | R.ACTOR_AGE() |
|-------------|---------------|
| Some Person | 30 |
【讨论】:
【参考方案2】:在pl sql中你必须使用构造select into
CREATE OR REPLACE TYPE BODY Role_Type
AS
MAP MEMBER FUNCTION Actor_Age
RETURN NUMBER
IS
v_date_born date ;
v_realse_date date ;
BEGIN
SELECT deref(self.PersonId).DateBorn into v_date_born FROM dual;
SELECT deref(self.MovieId).Releasedate into v_realse_date FROM dual;
RETURN (MONTHS_BETWEEN(v_date_born,v_realse_date)/12);
END;
END;
【讨论】:
这不起作用 -Role_Table
可以有多行并且您没有将它们过滤到当前行(除了您不需要从整个表中选择对象是表行,你可以只使用对象的属性),当PersonID
是REF
时,你不能使用PersonId.DateBorn
- 你需要使用DEREF( PersonId ).DateBorn
。以上是关于从 2 个 REF 列中获取两个日期之间的差异的主要内容,如果未能解决你的问题,请参考以下文章