在 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)?