복붙노트

[SQL] 데이터베이스에서 고유 인덱스 컬럼 값을 스왑

SQL

데이터베이스에서 고유 인덱스 컬럼 값을 스왑

나는 데이터베이스 테이블 및 필드 (안 기본 키) 그것에 고유 인덱스를 데 중 하나가 있습니다. 지금은 두 행이 열 아래 스왑 값으로합니다. 이것은 어떻게 할 수 있을까? 내가 아는 두 해킹은 다음과 같습니다 :

그러나 나는 그들이 문제에 대한 적절한 해결책이 될 것 같지 않는 한이 가고 싶지 않아요. 수있는 사람이 도움을 밖으로 나?

해결법

  1. ==============================

    1.난 당신이 솔루션 2. 내가 아는 어떤 SQL 변형에는 '스왑'기능이 없습니다 가야한다고 생각합니다.

    난 당신이 솔루션 2. 내가 아는 어떤 SQL 변형에는 '스왑'기능이 없습니다 가야한다고 생각합니다.

    정기적으로이 작업을 수행해야하는 경우, 나는 소프트웨어의 다른 부분이 데이터를 사용하는 방법에 따라, 솔루션 1을 제안한다. 당신이 조심하지 않으면 당신은 잠금 문제가있을 수 있습니다.

    그러나 짧은 : 당신이 제공하는 것보다 다른 해결책은 없다.

  2. ==============================

    2.마법의 단어가 여기 DEFERRABLE입니다 :

    마법의 단어가 여기 DEFERRABLE입니다 :

    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;
    

    결과:

    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)
    
  3. ==============================

    3.앤디 어빙의 대답에 추가

    앤디 어빙의 대답에 추가

    이 비슷한 상황에서 (SQL 서버 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))
    
  4. ==============================

    4.임시 테이블을 사용하여 UPDATE 문에 조인 : SQL 서버와 작품을 또 다른 방법이있다.

    임시 테이블을 사용하여 UPDATE 문에 조인 : SQL 서버와 작품을 또 다른 방법이있다.

    문제는 같은 시간에 같은 값으로 두 행함으로써 발생하지만 (새로운 고유 값) 한 번에 두 행을 업데이트 할 경우, 어떤 제약 조건 위반이되지 않습니다.

    의사 코드 :

    -- setup initial data values:
    insert into data_table(id, name) values(1, 'A')
    insert into data_table(id, name) values(2, 'B')
    
    -- create temp table that matches live table
    select top 0 * into #tmp_data_table from data_table
    
    -- insert records to be swapped
    insert into #tmp_data_table(id, name) values(1, 'B')
    insert into #tmp_data_table(id, name) values(2, 'A')
    
    -- update both rows at once! No index violations!
    update data_table set name = #tmp_data_table.name
    from data_table join #tmp_data_table on (data_table.id = #tmp_data_table.id)
    

    이 기술에 대한 풍부한 H에게 감사드립니다. - 마크

  5. ==============================

    5.나는 또한이 경우 뭔가 트랜잭션에 포장을해야 것이지만 잘못된 중간 업데이트를 진행, # 2는 가장 좋은 방법이라고 생각합니다.

    나는 또한이 경우 뭔가 트랜잭션에 포장을해야 것이지만 잘못된 중간 업데이트를 진행, # 2는 가장 좋은 방법이라고 생각합니다.

    다른 값으로 고유 인덱스 값을 업데이트하기 (당신이 요청 이후) 대안은 다른 행의에 행에 다른 모든 값을 업데이트하는 것입니다. 이 방법을 이렇게하면 당신은 혼자가 고유 인덱스 값을 떠날 수 있고, 결국, 당신은 당신이 원하는 데이터로 끝날 것이다. 조심하지만 수, 경우에 외래 키 관계에있는 다른 테이블 참조이 테이블은 DB의 모든 관계는 그대로 유지있다.

  6. ==============================

    6.SQL Server의이 작품은 ... 당신은 업데이트 할 두 행의 PK를 알고 가정하면, 다른 제품에 대해 말할 수 없다. SQL은 문 수준에서 원자 (있어야)한다 :

    SQL Server의이 작품은 ... 당신은 업데이트 할 두 행의 PK를 알고 가정하면, 다른 제품에 대해 말할 수 없다. 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
    
  7. ==============================

    7.나는 같은 문제를 가지고있다. 여기에 PostgreSQL을 내 제안 된 기법이다. 내 경우에는, 내 고유 인덱스 내 행에 명시 적으로 사용자 순서를 정의하는 일련의 값입니다. 그런 다음 사용자는 변경 사항을 제출, 웹 응용 프로그램의 행을 주위 셔플한다.

    나는 같은 문제를 가지고있다. 여기에 PostgreSQL을 내 제안 된 기법이다. 내 경우에는, 내 고유 인덱스 내 행에 명시 적으로 사용자 순서를 정의하는 일련의 값입니다. 그런 다음 사용자는 변경 사항을 제출, 웹 응용 프로그램의 행을 주위 셔플한다.

    나는 트리거 "이전의"를 추가 할 계획입니다. 내 고유 인덱스 값이 갱신 될 때마다 방아쇠에서, 나는 다른 행이 이미 내 새로운 가치를 보유하고 있는지 볼 것이다. 그렇다면, 나는 그들에게 내 이전 값을주고, 효과적으로 오프 값을 훔치는 것입니다.

    나는 PostgreSQL의 날은 전에 트리거이 셔플을 할 수 것으로 기대하고있다.

    내가 다시 게시하고 내 주행 거리를 알려 드리겠습니다.

  8. ==============================

    8.Oracle의 경우이 옵션 이연이지만, 당신은 당신의 제약 조건에 추가해야합니다.

    Oracle의 경우이 옵션 이연이지만, 당신은 당신의 제약 조건에 추가해야합니다.

    SET CONSTRAINT emp_no_fk_par DEFERRED; 
    

    전체 세션 동안, 연기 모든 제약을 연기하려면 ALTER SESSION SET 제약 = DEFERRED 문을 사용할 수 있습니다.

    출처

  9. ==============================

    9.나는 보통 절대적으로 내 테이블에 인덱스가없는 수있는 가치를 생각합니다. 보통 - 고유의 열 값을 - 정말 간단합니다. 예를 들어, 열 '위치'(여러 요소의 순서에 대한 정보)의 값은 0이다.

    나는 보통 절대적으로 내 테이블에 인덱스가없는 수있는 가치를 생각합니다. 보통 - 고유의 열 값을 - 정말 간단합니다. 예를 들어, 열 '위치'(여러 요소의 순서에 대한 정보)의 값은 0이다.

    그런 다음, 변수에 값 A를 복사하여 변수의 값을 B 후 설정 값을 B로 업데이트 할 수 있습니다. 두 쿼리는, 그래도 난 더 나은 솔루션을 알 수 없습니다.

  10. ==============================

    10.오라클은 바로이 문제를 해결 무결성 검사를 연기했다,하지만 SQL Server 또는 MySQL의 중 하나에서 사용할 수 없습니다.

    오라클은 바로이 문제를 해결 무결성 검사를 연기했다,하지만 SQL Server 또는 MySQL의 중 하나에서 사용할 수 없습니다.

  11. ==============================

    11.SQL Server에서 MERGE 문은 일반적으로 UNIQUE KEY / INDEX를 끊을 행을 업데이트 할 수 있습니다. (I 호기심 때문에 그냥 이것을 테스트했습니다.)

    SQL Server에서 MERGE 문은 일반적으로 UNIQUE KEY / INDEX를 끊을 행을 업데이트 할 수 있습니다. (I 호기심 때문에 그냥 이것을 테스트했습니다.)

    그러나, 당신은 필요한 행 / w 공급 병합에 임시 테이블 / 변수를 사용해야 할 것입니다.

  12. ==============================

    12.1) 이름의 ID를 전환

    1) 이름의 ID를 전환

    id    student 
    
    1     Abbot   
    2     Doris  
    3     Emerson 
    4     Green  
    5     Jeames  
    

    샘플 입력, 출력은 :

    ID 학생

    1     Doris   
    2     Abbot   
    3     Green   
    4     Emerson 
    5     Jeames  
    

    "관리 방법 행의 경우 n 개의에 ......"

  13. from https://stackoverflow.com/questions/644/swap-unique-indexed-column-values-in-database by cc-by-sa and MIT license