# 마이그레이션 046 오류 수정 ## 🚨 발생한 오류 ``` SQL Error [23514]: ERROR: check constraint "check_menu_scope_requires_menu_objid" of relation "numbering_rules" is violated by some row ``` ## 🔍 원인 분석 기존 데이터베이스에 `scope_type='menu'`인데 `menu_objid`가 NULL인 레코드가 존재했습니다. 제약조건을 추가하기 전에 이러한 **불완전한 데이터를 먼저 정리**해야 했습니다. ## ✅ 수정 내용 마이그레이션 파일 `046_update_numbering_rules_scope_type.sql`에 **데이터 정리 단계** 추가: ### 1. 추가된 데이터 정리 로직 (제약조건 추가 전) ```sql -- 3. 기존 데이터 정리 (제약조건 추가 전 필수!) -- 3.1. menu 타입인데 menu_objid가 NULL인 경우 → global로 변경 UPDATE numbering_rules SET scope_type = 'global', table_name = NULL WHERE scope_type = 'menu' AND menu_objid IS NULL; -- 3.2. global 타입인데 table_name이 있는 경우 → table로 변경 UPDATE numbering_rules SET scope_type = 'table' WHERE scope_type = 'global' AND table_name IS NOT NULL; -- 3.3. 정리 결과 확인 (로그) DO $$ DECLARE menu_count INTEGER; global_count INTEGER; table_count INTEGER; BEGIN SELECT COUNT(*) INTO menu_count FROM numbering_rules WHERE scope_type = 'menu'; SELECT COUNT(*) INTO global_count FROM numbering_rules WHERE scope_type = 'global'; SELECT COUNT(*) INTO table_count FROM numbering_rules WHERE scope_type = 'table'; RAISE NOTICE '=== 데이터 정리 완료 ==='; RAISE NOTICE 'Menu 규칙: % 개', menu_count; RAISE NOTICE 'Global 규칙: % 개', global_count; RAISE NOTICE 'Table 규칙: % 개', table_count; RAISE NOTICE '========================='; END $$; ``` ### 2. 실행 순서 변경 **변경 전:** 1. scope_type 제약조건 추가 2. ❌ 유효성 제약조건 추가 (여기서 오류 발생!) 3. 데이터 마이그레이션 **변경 후:** 1. scope_type 제약조건 추가 2. ✅ **기존 데이터 정리** (추가) 3. 유효성 제약조건 추가 4. 인덱스 생성 5. 통계 업데이트 ## 🔄 재실행 방법 ### 옵션 1: 전체 롤백 후 재실행 (권장) ```sql -- 1. 기존 마이그레이션 롤백 BEGIN; -- 제약조건 제거 ALTER TABLE numbering_rules DROP CONSTRAINT IF EXISTS check_scope_type; ALTER TABLE numbering_rules DROP CONSTRAINT IF EXISTS check_table_scope_requires_table_name; ALTER TABLE numbering_rules DROP CONSTRAINT IF EXISTS check_global_scope_no_table_name; ALTER TABLE numbering_rules DROP CONSTRAINT IF EXISTS check_menu_scope_requires_menu_objid; -- 인덱스 제거 DROP INDEX IF EXISTS idx_numbering_rules_scope_table; DROP INDEX IF EXISTS idx_numbering_rules_scope_menu; COMMIT; -- 2. 수정된 마이그레이션 재실행 \i /Users/kimjuseok/ERP-node/db/migrations/046_update_numbering_rules_scope_type.sql ``` ### 옵션 2: 데이터 정리만 수동 실행 후 재시도 ```sql -- 1. 데이터 정리 UPDATE numbering_rules SET scope_type = 'global', table_name = NULL WHERE scope_type = 'menu' AND menu_objid IS NULL; UPDATE numbering_rules SET scope_type = 'table' WHERE scope_type = 'global' AND table_name IS NOT NULL; -- 2. 제약조건 추가 ALTER TABLE numbering_rules ADD CONSTRAINT check_menu_scope_requires_menu_objid CHECK ( (scope_type = 'menu' AND menu_objid IS NOT NULL) OR scope_type != 'menu' ); -- 3. 나머지 제약조건들... ``` ## 🧪 검증 쿼리 마이그레이션 실행 전에 문제 데이터 확인: ```sql -- 문제가 되는 레코드 확인 SELECT rule_id, rule_name, scope_type, table_name, menu_objid, company_code FROM numbering_rules WHERE (scope_type = 'menu' AND menu_objid IS NULL) OR (scope_type = 'global' AND table_name IS NOT NULL) OR (scope_type = 'table' AND table_name IS NULL); ``` 마이그레이션 실행 후 검증: ```sql -- 1. scope_type별 개수 SELECT scope_type, COUNT(*) as count FROM numbering_rules GROUP BY scope_type; -- 2. 제약조건 확인 SELECT conname, pg_get_constraintdef(oid) FROM pg_constraint WHERE conrelid = 'numbering_rules'::regclass AND conname LIKE '%scope%'; -- 3. 인덱스 확인 SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'numbering_rules' AND indexname LIKE '%scope%'; ``` ## 📝 수정 내역 - ✅ 제약조건 추가 전 데이터 정리 로직 추가 - ✅ 중복된 데이터 마이그레이션 코드 제거 - ✅ 섹션 번호 재정렬 - ✅ 데이터 정리 결과 로그 추가 ## 🎯 다음 단계 1. **현재 상태 확인** ```bash psql -h localhost -U postgres -d ilshin -f /Users/kimjuseok/ERP-node/db/check_numbering_rules.sql ``` 2. **롤백 (필요시)** - 기존 제약조건 제거 3. **수정된 마이그레이션 재실행** ```bash PGPASSWORD=<비밀번호> psql -h localhost -U postgres -d ilshin -f /Users/kimjuseok/ERP-node/db/migrations/046_update_numbering_rules_scope_type.sql ``` 4. **검증** - 제약조건 확인 - 데이터 개수 확인 - 인덱스 확인 --- **수정 완료!** 이제 마이그레이션을 다시 실행하면 성공할 것입니다. 🎉