Swap unique indexed column values in database

前端 未结 12 897
伪装坚强ぢ
伪装坚强ぢ 2020-12-03 06:36

I have a database table and one of the fields (not the primary key) is having a unique index on it. Now I want to swap values under this column for two rows. How could this

相关标签:
12条回答
  • 2020-12-03 06:58

    Oracle has deferred integrity checking which solves exactly this, but it is not available in either SQL Server or MySQL.

    0 讨论(0)
  • 2020-12-03 06:58

    In SQL Server, the MERGE statement can update rows that would normally break a UNIQUE KEY/INDEX. (Just tested this because I was curious.)

    However, you'd have to use a temp table/variable to supply MERGE w/ the necessary rows.

    0 讨论(0)
  • 2020-12-03 07:00

    Further to Andy Irving's answer

    this worked for me (on SQL Server 2005) in a similar situation where I have a composite key and I need to swap a field which is part of the unique constraint.

    key: pID, LNUM rec1: 10, 0 rec2: 10, 1 rec3: 10, 2

    and I need to swap LNUM so that the result is

    key: pID, LNUM rec1: 10, 1 rec2: 10, 2 rec3: 10, 0

    the SQL needed:

    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))
    
    0 讨论(0)
  • 2020-12-03 07:06

    I think you should go for solution 2. There is no 'swap' function in any SQL variant I know of.

    If you need to do this regularly, I suggest solution 1, depending on how other parts of the software are using this data. You can have locking issues if you're not careful.

    But in short: there is no other solution than the ones you provided.

    0 讨论(0)
  • 2020-12-03 07:12

    For Oracle there is an option, DEFERRED, but you have to add it to your constraint.

    SET CONSTRAINT emp_no_fk_par DEFERRED; 
    

    To defer ALL constraints that are deferrable during the entire session, you can use the ALTER SESSION SET constraints=DEFERRED statement.

    Source

    0 讨论(0)
  • 2020-12-03 07:14

    The magic word is DEFERRABLE here:

    DROP TABLE ztable CASCADE;
    CREATE TABLE ztable
        ( id integer NOT NULL PRIMARY KEY
        , payload varchar
        );
    INSERT INTO ztable(id,payload) VALUES (1,'one' ), (2,'two' ), (3,'three' );
    SELECT * FROM ztable;
    
    
        -- This works, because there is no constraint
    UPDATE ztable t1
    SET payload=t2.payload
    FROM ztable t2
    WHERE t1.id IN (2,3)
    AND t2.id IN (2,3)
    AND t1.id <> t2.id
        ;
    SELECT * FROM ztable;
    
    ALTER TABLE ztable ADD CONSTRAINT OMG_WTF UNIQUE (payload)
        DEFERRABLE INITIALLY DEFERRED
        ;
    
        -- This should also work, because the constraint 
        -- is deferred until "commit time"
    UPDATE ztable t1
    SET payload=t2.payload
    FROM ztable t2
    WHERE t1.id IN (2,3)
    AND t2.id IN (2,3)
    AND t1.id <> t2.id
        ;
    SELECT * FROM ztable;
    

    RESULT:

    DROP TABLE
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "ztable_pkey" for table "ztable"
    CREATE TABLE
    INSERT 0 3
     id | payload
    ----+---------
      1 | one
      2 | two
      3 | three
    (3 rows)
    
    UPDATE 2
     id | payload
    ----+---------
      1 | one
      2 | three
      3 | two
    (3 rows)
    
    NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "omg_wtf" for table "ztable"
    ALTER TABLE
    UPDATE 2
     id | payload
    ----+---------
      1 | one
      2 | two
      3 | three
    (3 rows)
    
    0 讨论(0)
提交回复
热议问题