【问题标题】:Add unique constraint on two not null fields在两个非空字段上添加唯一约束
【发布时间】:2018-05-28 10:05:00
【问题描述】:

我有一个包含两个字段的实体:

@ManyToOne(fetch = FetchType.LAZY, optional = true)
private Organization organization;

@Column(length = 15)
private String ref;

我想在organizationref 上添加唯一键,这个唯一键只有在organizationref 都不为空时才有效。

例如当我插入两条记录时:

organization = 1, ref = 'R1'

organization = 1, ref = 'R1'

这会产生违反约束的情况,到目前为止我对这种情况没有任何问题。

当我在哪里插入两条记录时:

organization = null, ref = null

organization = null, ref = null

这不会产生约束冲突,到目前为止我对这种情况也没有任何问题。

我遇到的问题是在这种情况下:

organization = 1, ref = null

organization = 1, ref = null

或者

organization = null, ref = 'R1'

organization = null, ref = 'R1'

这两种情况都会产生约束冲突,这是我不希望的,因为我只希望只有 organizationref 都不为空时唯一约束才有效。

这就是我声明唯一约束的方式:

@Table(uniqueConstraints = {
        @UniqueConstraint(columnNames = { "organization", "ref" })
})

我该如何解决这个问题。

PS:我使用的是 Oracle 12c。

编辑:

  • organizationref 两个字段都可以为空。 JPA

  • 我声明的@UniqueConstraint注解会生成SQL代码:

    CREATE UNIQUE INDEX "USERNAME"."UK_TABLENAME_1" ON "USERNAME"."TABLENAME" ("organization", "ref")

【问题讨论】:

  • 实体可以改吗?
  • @pirho 是的
  • 为什么不在两个字段上同时添加@NotNull@Unique 约束..
  • @AmolRaje 因为它们是可为空的字段

标签: java sql oracle jpa


【解决方案1】:

您需要为此创建一个基于函数的索引。

CREATE UNIQUE INDEX uidx_my_table ON my_table
  (CASE WHEN organization IS NOT NULL AND ref IS NOT NULL
        THEN organization || ref 
   END);

【讨论】:

  • 如何使用 JPA 来完成,因为我的问题是关于 JPA。
【解决方案2】:

Oracle 对唯一索引比较奇怪:

升序唯一索引允许多个 NULL 值。然而,在 降序唯一索引,多个 NULL 值被视为 重复值,因此是不允许的。

因此,您可以使用唯一索引来处理此问题:

create unique index unq_t_organization_ref on t(organization, ref);

索引应忽略唯一值。

【讨论】:

  • 这与我在 JPA 实体上使用 @UniqueConstraint 注释生成的查询相同。
猜你喜欢
  • 2013-01-19
  • 1970-01-01
  • 2016-08-29
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
相关资源
最近更新 更多