将Oracle查询转换为H2。

huangapple go评论63阅读模式
英文:

Translate Oracle query to H2

问题

以下是翻译好的部分:

我有以下查询,在Oracle中运行良好:

此查询返回当前月份的所有日期列表。

问题在于我需要此查询在H2中也能工作,但H2不支持“LEVEL”、“TRUNC”或“CONNECT BY”。因此,我该如何重写查询,以使其在Oracle和H2中都能正常工作?

英文:

I have the following query, which works fine in Oracle:

SELECT TRUNC(CURRENT_DATE, 'MM') + LEVEL - 1 AS MYDATE FROM DUAL CONNECT BY LEVEL <= EXTRACT(DAY FROM LAST_DAY(CURRENT_DATE));

This query returns a list with all the days from current month.

The issue is that I need this query to also work in H2, but H2 does not support LEVEL or TRUNC or CONNECT BY. Therefore, how could I rewrite the query so that it works with both Oracle and H2?

答案1

得分: 2

以下是翻译好的内容:

You can use the following query with both Oracle and H2:

WITH T(MYDATE) AS (
SELECT CAST(TRUNC(CURRENT_DATE)
 - INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1) AS DATE) MYDATE
FROM DUAL
UNION ALL
SELECT CAST(MYDATE AS DATE) + INTERVAL '1' DAY
FROM T
WHERE EXTRACT(MONTH FROM CAST(MYDATE AS DATE) + INTERVAL '1' DAY)
  = EXTRACT(MONTH FROM CURRENT_DATE)
)
SELECT MYDATE FROM T;

But if you can use different queries, it will be better to use that one with H2:

SELECT DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' DAY * X MYDATE
FROM SYSTEM_RANGE(0, EXTRACT(DAY FROM
  DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' MONTH - INTERVAL '2' DAY));

(In future versions of H2 it will be possible to use a simpler query.)

英文:

You can use the following query with both Oracle and H2:

WITH T(MYDATE) AS (
SELECT CAST(TRUNC(CURRENT_DATE)
 - INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1) AS DATE) MYDATE
FROM DUAL
UNION ALL
SELECT CAST(MYDATE AS DATE) + INTERVAL '1' DAY
FROM T
WHERE EXTRACT(MONTH FROM CAST(MYDATE AS DATE) + INTERVAL '1' DAY)
  = EXTRACT(MONTH FROM CURRENT_DATE)
)
SELECT MYDATE FROM T;

But if you can use different queries, it will be better to use that one with H2:

SELECT DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' DAY * X MYDATE
FROM SYSTEM_RANGE(0, EXTRACT(DAY FROM
  DATE_TRUNC(MONTH, CURRENT_DATE) + INTERVAL '1' MONTH - INTERVAL '2' DAY));

(In future versions of H2 it will be possible to use a simpler query.)

答案2

得分: 1

不容易。比较Oracle和H2函数

  • Oracle支持TRUNC,H2支持DATE_TRUNC
  • Oracle支持LAST_DAY,而H2不支持。

H2似乎支持EXTRACTCAST函数,如果它支持递归查询,那么您可以仅使用这些函数编写一些内容(但不够优雅):

WITH days (day, month) AS (
  SELECT CURRENT_DATE
         - EXTRACT(DAY FROM CURRENT_DATE) + 1
         - EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP)) / 24
         - EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) / 24 / 60
         - FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)) / 24 / 60 / 60,
         EXTRACT(MONTH FROM CURRENT_DATE)
  FROM   DUAL
UNION ALL
  SELECT day + 1,
         month
  FROM   days
  WHERE  EXTRACT(MONTH FROM day + 1) = month
)
SELECT day
FROM   days;

或者,如果H2不支持将数字添加到日期,则可以使用INTERVAL

WITH days (day, month) AS (
  SELECT CURRENT_DATE
         - INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1)
         - INTERVAL '1' HOUR * EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP))
         - INTERVAL '1' MINUTE * EXTRACT(MINUTE FROM CURRENT_TIMESTAMP)
         - INTERVAL '1' SECOND * FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)),
         EXTRACT(MONTH FROM CURRENT_DATE)
  FROM   DUAL
UNION ALL
  SELECT day + INTERVAL '1' DAY,
         month
  FROM   days
  WHERE  EXTRACT(MONTH FROM day + INTERVAL '1' DAY) = month
)
SELECT day
FROM   days;

这两种方法都会输出:

DAY
2023-06-01 00:00:00
2023-06-02 00:00:00
2023-06-03 00:00:00
...
2023-06-29 00:00:00
2023-06-30 00:00:00

我无法访问H2实例来测试它是否在该RDBMS上运行。

然而,您可能会发现编写针对每个数据库的不同代码比尝试重用相同的代码更简单。

fiddle

英文:

> how could I rewrite the query so that it works with both Oracle and H2?

Not easily. Comparing Oracle and H2 functions:

  • Oracle supports TRUNC and H2 supports DATE_TRUNC
  • Oracle supports LAST_DAY and H2 does not.

H2 appears to support the functions EXTRACT and CAST and if it supports recursive queries then you could write something using only those functions (but it is not nice):

WITH days (day, month) AS (
  SELECT CURRENT_DATE
         - EXTRACT(DAY FROM CURRENT_DATE) + 1
         - EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP)) / 24
         - EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) / 24 / 60
         - FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)) / 24 / 60 / 60,
         EXTRACT(MONTH FROM CURRENT_DATE)
  FROM   DUAL
UNION ALL
  SELECT day + 1,
         month
  FROM   days
  WHERE  EXTRACT(MONTH FROM day + 1) = month
)
SELECT day
FROM   days;

or, if H2 does not support adding numbers to dates then you can use INTERVALs:

WITH days (day, month) AS (
  SELECT CURRENT_DATE
         - INTERVAL '1' DAY * (EXTRACT(DAY FROM CURRENT_DATE) - 1)
         - INTERVAL '1' HOUR * EXTRACT(HOUR FROM CAST(CURRENT_TIMESTAMP AS TIMESTAMP))
         - INTERVAL '1' MINUTE * EXTRACT(MINUTE FROM CURRENT_TIMESTAMP)
         - INTERVAL '1' SECOND * FLOOR(EXTRACT(SECOND FROM CURRENT_TIMESTAMP)),
         EXTRACT(MONTH FROM CURRENT_DATE)
  FROM   DUAL
UNION ALL
  SELECT day + INTERVAL '1' DAY,
         month
  FROM   days
  WHERE  EXTRACT(MONTH FROM day + INTERVAL '1' DAY) = month
)
SELECT day
FROM   days;

Which both output:

DAY
2023-06-01 00:00:00
2023-06-02 00:00:00
2023-06-03 00:00:00
...
2023-06-29 00:00:00
2023-06-30 00:00:00

I don't have access to a H2 instance to test whether it works on that RDBMS.

However, you may find it simpler to write different code for each database rather than trying to re-use the same code.

fiddle

huangapple
  • 本文由 发表于 2023年6月22日 19:57:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531641.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定