如何在具有两列的oracledb中具有唯一约束,以便其中一列中不能出现重复。
假设这张table
|id | A | B |
|---|---|---|
| 1 | 1 | 2 |
| 2 | 3 | 4 |
一个新的行不允许在列“a”中有一个与列“a”或“b”中的值重复的值。
在上面的例子中:我可以在列“a”中添加5,但不能添加1、2、3或4。
我的想法是:
CREATE UNIQUE INDEX crossTest ON test (
SELECT t.A AS x FROM test t
UNION ALL
SELECT t.B AS x FROM test t
)
但它不起作用,因为oracle不接受这种语法。
两种经典方法:
有两个唯一的约束 CREATE UNIQUE INDEX uidxA ON test A
以及 CREATE UNIQUE INDEX uidxB ON test B
不起作用,因为我可以在“a”列中添加2和4
具有两列的唯一约束 CREATE UNIQUE INDEX uidxB ON test (A, B)
因为这只检查现有的对。
(附加问题:应该允许同一行的“a”和“b”可以相等)
示例的sql脚本
CREATE TABLE test (id NUMBER (10) NOT NULL, a VARCHAR2(12), b VARCHAR2(12));
INSERT INTO test (id,a,b) VALUES(1, '1', '2');
INSERT INTO test (id,a,b) VALUES(2, '3', '4');
INSERT INTO test (id,a,b) VALUES(3, '4', 'x'); -> should fail
INSERT INTO test (id,a,b) VALUES(3, '5', 'x'); -> should work
4条答案
按热度按时间jhdbpxl91#
@tejash的回答给了我一个避免锁定或序列化的想法。您可以创建一个辅助表
duet_index
生成包含所有行的扩展数据集。然后一个简单的触发器就可以了,包括你的奖金问题。例如:
然后触发:
请认为我不擅长编写oracle触发器。语法可能是错误的,但想法应该是正确的。
8ftvxx2r2#
我在甲骨文公司工作了几十年,我不记得有过这样的要求。你的数据模型让我很紧张。
你想做的事不能用一个索引来完成。在所有多用户情况下,基于触发器的方法都很难正常工作。物化视图方法似乎很有前途。
我的建议是创建一个在提交时刷新并包含连接的物化视图(
UNION ALL
)列a和列b的值。以下是我的意思(更多细节请参见代码中的注解):
缺点
这里有一个可伸缩性问题。oracle将在提交时同步。我相信,解决你问题的每一个有效办法都会有这个缺点
在事务尝试提交之前,不会出现错误,此时无法更正和恢复事务。我相信在任何解决方案中,您都无法解决这个缺点,而不会使缺点#1变得更糟(即,您的表上没有更广泛和更持久的锁)。
a0zr77ik3#
我建议修复我们的数据模型,使值以行而不是列的形式出现:
唯一的约束很容易。
db2dz4w84#
不可能使用
INDEX
或者CONSTRAINT
. 你需要一个trigger
,类似于: