在 Select ORACLE SQL 中使用函数
Using a Function inside a Select ORACLE SQL
我有这个功能:
CREATE FUNCTION ISROOMAVAILABLE(P_ID_ROOM INT, P_DATE DATE) RETURN BOOLEAN
IS
V_COUNT INT;
BEGIN
SELECT count(*)
INTO V_COUNT
FROM CHECKIN A
LEFT JOIN CHECKOUT B ON (A.ID_RESERVATION = B.ID_RESERVATION)
WHERE A.ID_ROOM = P_ID_ROOM
AND ((A.DATE >= trunc(P_DATE) AND B.DATE IS NULL)
OR
(A.DATE <= trunc(P_DATE) AND B.DATE >= trunc(P_DATE)));
RETURN (V_COUNT > 0);
END;
如果房间(由其 ID 标识)在特定日期可用,则此 returns 为真。
我想使用上面的函数检查多个参数作为我选择的决定因素:
SELECT Q.ID, COUNT(R.DATE_OUT - R.DATE_IN) AS DAYS
FROM QUARTO Q
JOIN CHECKIN CI ON Q.ID = CI.ID_ROOM
JOIN RESERVATION R ON CI.ID_RESERVATION = R.ID
WHERE (EXTRACT(YEAR FROM R.DATE_IN) = EXTRACT(YEAR FROM SYSDATE))
AND (ISROOMAVAILABLE(Q.ID, SYSDATE))
GROUP BY Q.ID
ORDER BY DAYS;
我在函数中使用了 sysdate,因为我仍然缺少数据库中的一些数据,但我得到的错误仍然是“关系运算符无效”。
有什么方法可以使用我在“WHERE”子句中的函数吗?
请原谅我的葡萄牙语翻译不好,我不知道英文的确切术语。
我认为 Oracle 无法计算 SQL 查询的 WHERE
子句中的 PL/SQL 布尔值。
最简单的方法是修改函数,因此它 return 是可以评估的。例如,我们可以 return 1
表示真,0
表示假:
CREATE FUNCTION ISROOMAVAILABLE(P_ID_ROOM INT, P_DATE DATE) RETURN INT
IS
V_COUNT INT;
BEGIN
SELECT count(*)
INTO V_COUNT
FROM CHECKIN A
LEFT JOIN CHECKOUT B ON (A.ID_RESERVATION = B.ID_RESERVATION)
WHERE A.ID_ROOM = P_ID_ROOM
AND ((A.DATE >= trunc(P_DATE) AND B.DATE IS NULL)
OR
(A.DATE <= trunc(P_DATE) AND B.DATE >= trunc(P_DATE)));
RETURN LEAST(V_COUNT, 1);
END;
然后:
WHERE ...
AND ISROOMAVAILABLE(Q.ID, SYSDATE) = 1
如果您不能修改该函数,则需要将其包装在另一个函数中,该函数 return 是一种可以在 SQL 中计算的数据类型,然后调用包装函数原来的。
与您的查询无关的注释:
EXTRACT(YEAR FROM R.DATE_IN) = EXTRACT(YEAR FROM SYSDATE)
不是最理想的。这将通过直接过滤更有效地表达:
R.DATE_IN >= TRUNC(SYSDATE, 'YEAR')
AND R.DATE_IN < ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 12)
- 我想知道
COUNT(R.DATE_OUT - R.DATE_IN)
是否符合您的要求。它所做的是计算两个日期都不是 NULL
的所有行。也许你的意思是:SUM(R.DATE_OUT - R.DATE_IN)
?
我有这个功能:
CREATE FUNCTION ISROOMAVAILABLE(P_ID_ROOM INT, P_DATE DATE) RETURN BOOLEAN
IS
V_COUNT INT;
BEGIN
SELECT count(*)
INTO V_COUNT
FROM CHECKIN A
LEFT JOIN CHECKOUT B ON (A.ID_RESERVATION = B.ID_RESERVATION)
WHERE A.ID_ROOM = P_ID_ROOM
AND ((A.DATE >= trunc(P_DATE) AND B.DATE IS NULL)
OR
(A.DATE <= trunc(P_DATE) AND B.DATE >= trunc(P_DATE)));
RETURN (V_COUNT > 0);
END;
如果房间(由其 ID 标识)在特定日期可用,则此 returns 为真。
我想使用上面的函数检查多个参数作为我选择的决定因素:
SELECT Q.ID, COUNT(R.DATE_OUT - R.DATE_IN) AS DAYS
FROM QUARTO Q
JOIN CHECKIN CI ON Q.ID = CI.ID_ROOM
JOIN RESERVATION R ON CI.ID_RESERVATION = R.ID
WHERE (EXTRACT(YEAR FROM R.DATE_IN) = EXTRACT(YEAR FROM SYSDATE))
AND (ISROOMAVAILABLE(Q.ID, SYSDATE))
GROUP BY Q.ID
ORDER BY DAYS;
我在函数中使用了 sysdate,因为我仍然缺少数据库中的一些数据,但我得到的错误仍然是“关系运算符无效”。
有什么方法可以使用我在“WHERE”子句中的函数吗?
请原谅我的葡萄牙语翻译不好,我不知道英文的确切术语。
我认为 Oracle 无法计算 SQL 查询的 WHERE
子句中的 PL/SQL 布尔值。
最简单的方法是修改函数,因此它 return 是可以评估的。例如,我们可以 return 1
表示真,0
表示假:
CREATE FUNCTION ISROOMAVAILABLE(P_ID_ROOM INT, P_DATE DATE) RETURN INT
IS
V_COUNT INT;
BEGIN
SELECT count(*)
INTO V_COUNT
FROM CHECKIN A
LEFT JOIN CHECKOUT B ON (A.ID_RESERVATION = B.ID_RESERVATION)
WHERE A.ID_ROOM = P_ID_ROOM
AND ((A.DATE >= trunc(P_DATE) AND B.DATE IS NULL)
OR
(A.DATE <= trunc(P_DATE) AND B.DATE >= trunc(P_DATE)));
RETURN LEAST(V_COUNT, 1);
END;
然后:
WHERE ...
AND ISROOMAVAILABLE(Q.ID, SYSDATE) = 1
如果您不能修改该函数,则需要将其包装在另一个函数中,该函数 return 是一种可以在 SQL 中计算的数据类型,然后调用包装函数原来的。
与您的查询无关的注释:
EXTRACT(YEAR FROM R.DATE_IN) = EXTRACT(YEAR FROM SYSDATE)
不是最理想的。这将通过直接过滤更有效地表达:
R.DATE_IN >= TRUNC(SYSDATE, 'YEAR')
AND R.DATE_IN < ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 12)
- 我想知道
COUNT(R.DATE_OUT - R.DATE_IN)
是否符合您的要求。它所做的是计算两个日期都不是NULL
的所有行。也许你的意思是:SUM(R.DATE_OUT - R.DATE_IN)
?