sql - 使用基于函数的索引延迟唯一约束?

标签 sql oracle unique-constraint

我认为这会有点深奥,但我想把它放在那里以防万一有人尝试过这样的事情,或者如果有人已经尝试过并发现这是不可能的。

我们有一个表需要对某组列进行唯一性约束,但它也有一个“软删除”指示符。已标记为“已删除”的记录不应包含在唯一性检查中。

没关系,我可以用一个独特的基于函数的索引轻松解决这个问题。然而,让事情变得复杂的是,如果我们要在数据库中实现这个约束,它必须是一个延迟约束,因为 Hibernate 的工作方式。如果无法完成,我们将不得不省略约束,如果可能的话,我宁愿不要这样做。

例如:

CREATE TABLE jkemp_test
  ( id NUMBER NOT NULL
  , deleted_ind CHAR(1) DEFAULT 'N' NOT NULL);

CREATE UNIQUE INDEX jkemp_test_funique
  ON jkemp_test
  (CASE WHEN deleted_ind = 'N' THEN id END);

-- make this use the function-based index, maybe?
ALTER TABLE jkemp_test
  ADD CONSTRAINT jkemp_test_unique
  UNIQUE (id)
  DEFERRABLE INITIALLY DEFERRED;

INSERT INTO jkemp_test VALUES (1,'N');
INSERT INTO jkemp_test VALUES (2,'N');

COMMIT;

UPDATE jkemp_test SET deleted_ind='Y' WHERE id=1;

COMMIT;

-- depending on whether the constraint is deferred or not, either
-- the insert or the commit will fail "unique constraint violated"

INSERT INTO jkemp_test VALUES (1,'N');
COMMIT;

一个双赢的场景是最后一次提交成功,同时仍然允许延迟约束。 (我知道唯一索引的存在意味着约束当前没有延迟。)

目前我们唯一的选择是使用应用程序实现约束,这并不可靠。此外,我们不想过多更改数据模型(例如,我们可以将删除的行移动到不同的表,例如 JKEMP_TEST_DELETED,但这会使应用程序过于复杂)。

这是在 Oracle 11.2.0.1.0 上。

最佳答案

这在 apex.oracle.com 后面的 11.2.0.2 中有效。它应该在 11.2.0.1 中工作(也许在 11.1 中,但在 10g 中不行,因为虚拟列是 11g 的增强)

归功于 Lucas Jellma

CREATE TABLE jkemp_test
  ( id NUMBER NOT NULL
  , deleted_ind CHAR(1) DEFAULT 'N' NOT NULL);

alter table jkemp_test
ADD (active_id AS (CASE WHEN deleted_ind = 'N' THEN id END))
/

ALTER TABLE jkemp_test
  ADD CONSTRAINT jkemp_test_unique
  UNIQUE (active_id)
  DEFERRABLE INITIALLY DEFERRED;

您必须为插入指定列列表,因为不应指定派生列(虚拟列)。我很确定 Hibernate 可以使用它不接触的列。

INSERT INTO jkemp_test (id, deleted_ind) VALUES (1,'N');
INSERT INTO jkemp_test (id, deleted_ind) VALUES (2,'N');

COMMIT;

UPDATE jkemp_test SET deleted_ind='Y' WHERE id=1;

COMMIT;

INSERT INTO jkemp_test (id, deleted_ind) VALUES (1,'N');

关于sql - 使用基于函数的索引延迟唯一约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5453827/

相关文章:

mysql - 是否可以根据表中的另一个约束或其他变量打开或关闭唯一性

java - Java 中两个 Timestamp 对象之间的差异

php - 关系划分SQL

sql - 如何提高 Oracle DB 中 SQL 查询的性能

sql - 什么是适用于 Mac OSX 的 Toad 的良好替代品?

sql - PostgreSQL 8.3 中具有非空和唯一约束的增量字段

sql - 查询以查找今天和昨天的数据以及伪列之间的差异

c# - 如何测试具有数据库查询来更新数据的方法?

oracle - sqlcl错误日志配置

MySQL:删除约束UNIQUE KEY