H2 vs PostgreSQL 生成的具有函数的列
H2 vs PostgreSQL generated column with function
我正在尝试设置一个生成的列,该列在减去值时也会考虑空值检查。在 PostgreSQL 中我做了:
ALTER TABLE session ADD COLUMN
duration INTERVAL GENERATED ALWAYS AS age(time_ended, time_started) STORED;
H2 不支持 age 函数,所以我又打了一个补丁来为函数创建别名:
CREATE ALIAS age FOR "net.agileb.config.H2Functions.age";
和相应的java代码:
package net.agileb.config;
import java.time.Duration;
import java.time.LocalDateTime;
public class H2Functions {
public static Duration age(LocalDateTime endDate, LocalDateTime startDate) {
return Duration.between(endDate, startDate);
}
}
I 运行 H2 在 PostgreSQL 兼容模式下:
public:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:mem:agileb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;
driverClassName: org.h2.Driver
但 h2 仍然不喜欢生成列的语法:
SQL State : 42001
Error Code : 42001
Message : Syntax error in SQL statement "ALTER TABLE SESSION ADD COLUMN
DURATION INTERVAL GENERATED[*] ALWAYS AS AGE(TIME_ENDED, TIME_STARTED) STORED"; expected "YEAR, MONTH, DAY, HOUR, MINUTE, SECOND"; SQL statement:
ALTER TABLE session ADD COLUMN
duration INTERVAL GENERATED ALWAYS AS age(time_ended, time_started) STORED [42001-200]
Location : db/migration/V1606395529__topic_calculated_duration_column.sql (/home/agilob/Projects/springowy/build/resources/main/db/migration/V1606395529__topic_calculated_duration_column.sql)
Line : 3
Statement : ALTER TABLE session ADD COLUMN
duration INTERVAL GENERATED ALWAYS AS age(time_ended, time_started) STORED
我知道 H2 希望我使用特定的时间间隔,例如 INTERVAL SECOND
,生成为标识,STORED
关键字似乎不受支持。
有没有办法让这个查询在 PostgreSQL 和 H2 中工作?
无法对 PostgreSQL 和 H2 中的生成列使用相同的语法。
INTERVAL
没有间隔限定符的数据类型是 PostgreSQL 的一个特性。其他 DBMS,包括 H2,仅支持符合标准的区间,例如 INTERVAL YEAR
、INTERVAL YEAR(3) TO MONTH
、INTERVAL DAY TO SECOND
等。希望您可以在 Postgre[=] 中使用符合标准的区间数据类型42=] 同样,它们也受支持。但所有这些类型要么是年月间隔,要么是白天间隔。 YEAR
and/or MONTH
字段的间隔不能有 DAY
、HOUR
、MINUTE
或 SECOND
字段,反之亦然.如果你真的需要所有这些字段的混合间隔,你可以只使用 PostgreSQL 及其分支。
H2 1.4.200 仅支持使用 AS
关键字生成列的非标准语法(即将推出的 H2 2.0 也支持标准语法 GENERATED ALWAYS AS
)。 PostgreSQL 不支持来自 H2 的非标准语法。您可以从其当前源构建 H2,以便可以在此处使用相同的标准语法。
最大的问题是 PostgreSQL 出于某些奇怪的原因在生成列的定义末尾需要非标准的 STORED
子句并且不接受标准- 兼容的列定义。 H2等人没有也不接受此条款
所以这里唯一的解决办法是对 PostgreSQL 和 H2 使用不同的 SQL。
我正在尝试设置一个生成的列,该列在减去值时也会考虑空值检查。在 PostgreSQL 中我做了:
ALTER TABLE session ADD COLUMN
duration INTERVAL GENERATED ALWAYS AS age(time_ended, time_started) STORED;
H2 不支持 age 函数,所以我又打了一个补丁来为函数创建别名:
CREATE ALIAS age FOR "net.agileb.config.H2Functions.age";
和相应的java代码:
package net.agileb.config;
import java.time.Duration;
import java.time.LocalDateTime;
public class H2Functions {
public static Duration age(LocalDateTime endDate, LocalDateTime startDate) {
return Duration.between(endDate, startDate);
}
}
I 运行 H2 在 PostgreSQL 兼容模式下:
public:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:mem:agileb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;
driverClassName: org.h2.Driver
但 h2 仍然不喜欢生成列的语法:
SQL State : 42001
Error Code : 42001
Message : Syntax error in SQL statement "ALTER TABLE SESSION ADD COLUMN
DURATION INTERVAL GENERATED[*] ALWAYS AS AGE(TIME_ENDED, TIME_STARTED) STORED"; expected "YEAR, MONTH, DAY, HOUR, MINUTE, SECOND"; SQL statement:
ALTER TABLE session ADD COLUMN
duration INTERVAL GENERATED ALWAYS AS age(time_ended, time_started) STORED [42001-200]
Location : db/migration/V1606395529__topic_calculated_duration_column.sql (/home/agilob/Projects/springowy/build/resources/main/db/migration/V1606395529__topic_calculated_duration_column.sql)
Line : 3
Statement : ALTER TABLE session ADD COLUMN
duration INTERVAL GENERATED ALWAYS AS age(time_ended, time_started) STORED
我知道 H2 希望我使用特定的时间间隔,例如 INTERVAL SECOND
,生成为标识,STORED
关键字似乎不受支持。
有没有办法让这个查询在 PostgreSQL 和 H2 中工作?
无法对 PostgreSQL 和 H2 中的生成列使用相同的语法。
INTERVAL
没有间隔限定符的数据类型是 PostgreSQL 的一个特性。其他 DBMS,包括 H2,仅支持符合标准的区间,例如INTERVAL YEAR
、INTERVAL YEAR(3) TO MONTH
、INTERVAL DAY TO SECOND
等。希望您可以在 Postgre[=] 中使用符合标准的区间数据类型42=] 同样,它们也受支持。但所有这些类型要么是年月间隔,要么是白天间隔。YEAR
and/orMONTH
字段的间隔不能有DAY
、HOUR
、MINUTE
或SECOND
字段,反之亦然.如果你真的需要所有这些字段的混合间隔,你可以只使用 PostgreSQL 及其分支。H2 1.4.200 仅支持使用
AS
关键字生成列的非标准语法(即将推出的 H2 2.0 也支持标准语法GENERATED ALWAYS AS
)。 PostgreSQL 不支持来自 H2 的非标准语法。您可以从其当前源构建 H2,以便可以在此处使用相同的标准语法。最大的问题是 PostgreSQL 出于某些奇怪的原因在生成列的定义末尾需要非标准的
STORED
子句并且不接受标准- 兼容的列定义。 H2等人没有也不接受此条款
所以这里唯一的解决办法是对 PostgreSQL 和 H2 使用不同的 SQL。