006_fix_unique_constraint_fundamental.sql 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. -- DDL 006: UNIQUE 제약조건 근본적 수정
  2. -- 생성일: 2024-12-20
  3. -- 목적: 중복 키 오류 근본 해결을 위한 UNIQUE 제약조건 수정
  4. -- 1. 기존 UNIQUE 제약조건 제거
  5. ALTER TABLE `VENDOR_INFLUENCER_MAPPING`
  6. DROP INDEX `unique_vendor_influencer_status`;
  7. -- 2. 새로운 UNIQUE 제약조건 추가 (IS_ACT='Y'인 레코드만 적용)
  8. -- MySQL 8.0+에서는 함수 기반 인덱스 지원
  9. -- 아래 방식은 MySQL 5.7에서도 호환 가능한 방식
  10. -- 방법 A: 조건부 UNIQUE 인덱스 (MySQL 8.0+)
  11. -- ALTER TABLE `VENDOR_INFLUENCER_MAPPING`
  12. -- ADD UNIQUE INDEX `unique_active_vendor_influencer_status`
  13. -- (`VENDOR_SEQ`, `INFLUENCER_SEQ`, `STATUS`)
  14. -- WHERE `IS_ACT` = 'Y';
  15. -- 방법 B: 가상 컬럼을 이용한 UNIQUE 제약조건 (MySQL 5.7+ 호환)
  16. -- 1) 가상 컬럼 추가 (IS_ACT가 'Y'일 때만 값을 가짐)
  17. ALTER TABLE `VENDOR_INFLUENCER_MAPPING`
  18. ADD COLUMN `UNIQUE_KEY_HELPER` VARCHAR(50)
  19. GENERATED ALWAYS AS (
  20. CASE
  21. WHEN `IS_ACT` = 'Y' THEN CONCAT(`VENDOR_SEQ`, '-', `INFLUENCER_SEQ`, '-', `STATUS`)
  22. ELSE NULL
  23. END
  24. ) STORED;
  25. -- 2) 가상 컬럼에 UNIQUE 인덱스 적용
  26. ALTER TABLE `VENDOR_INFLUENCER_MAPPING`
  27. ADD UNIQUE INDEX `unique_active_vendor_influencer_status` (`UNIQUE_KEY_HELPER`);
  28. -- 3. 기존 데이터 정리 (중복 제거)
  29. -- 활성 상태에서 중복된 레코드가 있다면 가장 최근 것만 남기고 나머지는 비활성화
  30. UPDATE `VENDOR_INFLUENCER_MAPPING` v1
  31. JOIN (
  32. SELECT
  33. `VENDOR_SEQ`,
  34. `INFLUENCER_SEQ`,
  35. `STATUS`,
  36. MAX(`SEQ`) as latest_seq
  37. FROM `VENDOR_INFLUENCER_MAPPING`
  38. WHERE `IS_ACT` = 'Y'
  39. GROUP BY `VENDOR_SEQ`, `INFLUENCER_SEQ`, `STATUS`
  40. HAVING COUNT(*) > 1
  41. ) v2 ON v1.`VENDOR_SEQ` = v2.`VENDOR_SEQ`
  42. AND v1.`INFLUENCER_SEQ` = v2.`INFLUENCER_SEQ`
  43. AND v1.`STATUS` = v2.`STATUS`
  44. AND v1.`SEQ` < v2.latest_seq
  45. SET v1.`IS_ACT` = 'N',
  46. v1.`MOD_DATE` = NOW()
  47. WHERE v1.`IS_ACT` = 'Y';
  48. -- 4. 검증 쿼리 (중복 레코드 확인)
  49. -- 아래 쿼리 결과가 0이어야 함
  50. SELECT
  51. `VENDOR_SEQ`,
  52. `INFLUENCER_SEQ`,
  53. `STATUS`,
  54. COUNT(*) as duplicate_count
  55. FROM `VENDOR_INFLUENCER_MAPPING`
  56. WHERE `IS_ACT` = 'Y'
  57. GROUP BY `VENDOR_SEQ`, `INFLUENCER_SEQ`, `STATUS`
  58. HAVING COUNT(*) > 1;