交换数据库中唯一的索引列值
我有一个数据库表,并且其中一个字段(不是主键)上有一个唯一索引。现在,我想将该列下的值交换为两行。怎么办呢?我知道的两个技巧是:
删除这两行并重新插入它们用其他值更新行并交换,然后更新为实际值。
但是我不想追求这些,因为它们似乎并不是解决问题的适当方法。
有人可以帮我吗?
解决方案:
我认为我们应该寻求## 解决方案2. 据我所知,在任何SQL变体中都没有"交换"功能。
如果我们需要定期执行此操作,则建议## 解决方案1,具体取决于软件的其他部分如何使用此数据。如果不小心,可能会遇到锁定问题。
简而言之:除了我们提供的## 解决方案外,没有其他## 解决方案。
我还认为#2是最好的选择,尽管我会确保将其包装在事务中,以防更新期间出现问题。
用不同的值更新唯一索引值的另一种方法(是我们要求的)是将行中的所有其他值更新为另一行的值。这样做意味着我们可以保留唯一索引值,最后得到所需的数据。但是要小心,以防万一其他表在外键关系中引用了该表,则数据库中的所有关系都保持不变。
假设我们知道要更新的两行的PK ...在SQL Server中有效,不能代表其他产品。 SQL在语句级别上(应该是)是原子的:
CREATE TABLE testing ( cola int NOT NULL, colb CHAR(1) NOT NULL ); CREATE UNIQUE INDEX UIX_testing_a ON testing(colb); INSERT INTO testing VALUES (1, 'b'); INSERT INTO testing VALUES (2, 'a'); SELECT * FROM testing; UPDATE testing SET colb = CASE cola WHEN 1 THEN 'a' WHEN 2 THEN 'b' END WHERE cola IN (1,2); SELECT * FROM testing;
因此我们将来自:
cola colb ------------ 1 b 2 a
到:
cola colb ------------ 1 a 2 b
进一步回答安迪·欧文(Andy Irving)
这在类似情况下对我有效(在SQL Server 2005上)
在这里,我有一个复合键,我需要交换作为唯一约束一部分的字段。
密钥:pID,LNUM
rec1:10,0
rec2:10、1
rec3:10、2
我需要交换LNUM,以便结果是
密钥:pID,LNUM
rec1:10、1
rec2:10、2
rec3:10、0
需要的SQL:
UPDATE DOCDATA SET LNUM = CASE LNUM WHEN 0 THEN 1 WHEN 1 THEN 2 WHEN 2 THEN 0 END WHERE (pID = 10) AND (LNUM IN (0, 1, 2))
我也有同样的问题。这是我在PostgreSQL中建议的方法。就我而言,我的唯一索引是一个序列值,在我的行上定义了一个明确的用户顺序。用户将在网络应用程序中随机排列行,然后提交更改。
我打算添加一个"之前"触发器。在该触发器中,每当我更新唯一索引值时,我都会查看是否有其他行已经保存了我的新值。如果是这样,我会给他们我以前的价值,并有效地窃取他们的价值。
我希望PostgreSQL将允许我在before触发器中进行此混洗。
我会回发,让你知道我的里程。
Oracle推迟了完整性检查,可以完全解决此问题,但是SQL Server或者MySQL中均不提供此功能。