交换数据库中唯一的索引列值

时间:2020-03-05 18:37:23  来源:igfitidea点击:

我有一个数据库表,并且其中一个字段(不是主键)上有一个唯一索引。现在,我想将该列下的值交换为两行。怎么办呢?我知道的两个技巧是:

删除这两行并重新插入它们用其他值更新行并交换,然后更新为实际值。

但是我不想追求这些,因为它们似乎并不是解决问题的适当方法。
有人可以帮我吗?

解决方案:

我认为我们应该寻求## 解决方案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中均不提供此功能。