如何更新数据库中的日期间隔(Hibernate HQL)
How can I update an interval of dates in the database (Hibernate HQL)
考虑,对于 id id
的某些特定数据库条目,数据库中的日期间隔,从 BEGIN_DATE
到 END_DATE
,表示为 (BEGIN_DATE
, END_DATE
).
给定两个形成区间 (newBeginDate
, newEndDate
) 的新日期,我必须更新 (BEGIN_DATE
,END_DATE
) 以便生成的区间包含所有 4 个日期。换句话说,我想 添加两个间隔 (并且由于我添加它们,结果间隔可能保持不变或增加,但永远不会缩小)。
举几个例子:
如果(BEGIN_DATE
,END_DATE
) = (January 10
,January 20
),则:
(BEGIN_DATE
,END_DATE
) + (Jan 15
,Jan 25
) = (Jan 10
,Jan 25
)
(BEGIN_DATE
,END_DATE
) + (Jan 05
,Jan 15
) = (Jan 05
,Jan 20
)
(BEGIN_DATE
,END_DATE
) + (Jan 05
,Jan 25
) = (Jan 05
,Jan 25
)
(BEGIN_DATE
,END_DATE
) + (Jan 15
,Jan 15
) = (Jan 10
,Jan 20
)
(BEGIN_DATE
,END_DATE
) + (Jan 10
,Jan 13
) = (Jan 10
,Jan 20
)
以下两个查询共同实现了这个目标。第一个更新BEGIN_DATE
,第二个更新END_DATE
:
session.createQuery(
"update APPOINTMENTS " +
"set BEGIN_DATE = :newBeginDate " +
"where " +
"(BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) " +
"and ID = :id ")
.setParameter("newBeginDate", newBeginDate)
.setParameter("id", id)
.executeUpdate();
session.createQuery(
"update APPOINTMENTS " +
"set END_DATE = :newEndDate " +
"where " +
"(END_DATE is null or END_DATE < :newEndDate) " +
"and ID = :id ")
.setParameter("newEndDate", newEndDate)
.setParameter("id", id)
.executeUpdate();
我的问题是:
如何在单个查询中完成?
SQL 在涉及更复杂的编程结构时受到限制,因此由于您使用 Hibernate,我将只读取约会实体实例并更新其字段。这将需要两个查询,一个用于读取,一个用于更新,但它仍然只是一个更新语句,并且是最具可读性的解决方案。
如果您仍然只需要一个更新语句而别无其他,可以使用 case
将您的两个语句合并为一个:
update APPOINTMENTS
set BEGIN_DATE = case when (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) then :newBeginDate else BEGIN_DATE end,
END_DATE = case when (END_DATE is null or END_DATE < :newEndDate) then :newEndDate else END_DATE end
where (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate or END_DATE is null or END_DATE < :newEndDate)
and ID = :id
使用LEAST()
和GREATEST()
函数。对于 NULL,使用 COALESCE()
.
update APPOINTMENTS
set BEGIN_DATE = coalesce(least(BEGIN_DATE, :newBeginDate), :newBeginDate),
END_DATE = coalesce(greatest(END_DATE, :newEndDate), :newEndDate)
where ID = :id
我认为 LEAST 和 GREATEST 不需要解释。如果旧日期为 NULL,COALESCE 将选择新日期。因此,除了 ID = :id
之外,WHERE 子句中不需要任何条件。
考虑,对于 id id
的某些特定数据库条目,数据库中的日期间隔,从 BEGIN_DATE
到 END_DATE
,表示为 (BEGIN_DATE
, END_DATE
).
给定两个形成区间 (newBeginDate
, newEndDate
) 的新日期,我必须更新 (BEGIN_DATE
,END_DATE
) 以便生成的区间包含所有 4 个日期。换句话说,我想 添加两个间隔 (并且由于我添加它们,结果间隔可能保持不变或增加,但永远不会缩小)。
举几个例子:
如果(BEGIN_DATE
,END_DATE
) = (January 10
,January 20
),则:
(
BEGIN_DATE
,END_DATE
) + (Jan 15
,Jan 25
) = (Jan 10
,Jan 25
)(
BEGIN_DATE
,END_DATE
) + (Jan 05
,Jan 15
) = (Jan 05
,Jan 20
)(
BEGIN_DATE
,END_DATE
) + (Jan 05
,Jan 25
) = (Jan 05
,Jan 25
)(
BEGIN_DATE
,END_DATE
) + (Jan 15
,Jan 15
) = (Jan 10
,Jan 20
)(
BEGIN_DATE
,END_DATE
) + (Jan 10
,Jan 13
) = (Jan 10
,Jan 20
)
以下两个查询共同实现了这个目标。第一个更新BEGIN_DATE
,第二个更新END_DATE
:
session.createQuery(
"update APPOINTMENTS " +
"set BEGIN_DATE = :newBeginDate " +
"where " +
"(BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) " +
"and ID = :id ")
.setParameter("newBeginDate", newBeginDate)
.setParameter("id", id)
.executeUpdate();
session.createQuery(
"update APPOINTMENTS " +
"set END_DATE = :newEndDate " +
"where " +
"(END_DATE is null or END_DATE < :newEndDate) " +
"and ID = :id ")
.setParameter("newEndDate", newEndDate)
.setParameter("id", id)
.executeUpdate();
我的问题是: 如何在单个查询中完成?
SQL 在涉及更复杂的编程结构时受到限制,因此由于您使用 Hibernate,我将只读取约会实体实例并更新其字段。这将需要两个查询,一个用于读取,一个用于更新,但它仍然只是一个更新语句,并且是最具可读性的解决方案。
如果您仍然只需要一个更新语句而别无其他,可以使用 case
将您的两个语句合并为一个:
update APPOINTMENTS
set BEGIN_DATE = case when (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) then :newBeginDate else BEGIN_DATE end,
END_DATE = case when (END_DATE is null or END_DATE < :newEndDate) then :newEndDate else END_DATE end
where (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate or END_DATE is null or END_DATE < :newEndDate)
and ID = :id
使用LEAST()
和GREATEST()
函数。对于 NULL,使用 COALESCE()
.
update APPOINTMENTS
set BEGIN_DATE = coalesce(least(BEGIN_DATE, :newBeginDate), :newBeginDate),
END_DATE = coalesce(greatest(END_DATE, :newEndDate), :newEndDate)
where ID = :id
我认为 LEAST 和 GREATEST 不需要解释。如果旧日期为 NULL,COALESCE 将选择新日期。因此,除了 ID = :id
之外,WHERE 子句中不需要任何条件。