ERP에서 거래처 주문을 수신하는 설명용 업무 장면입니다. 수신 목록에는 A사의 000417이 이미 등록돼 있고, B사 파일에도 000417이 들어 있습니다. 두 회사가 각자 번호를 발급한다면 별개의 주문일 수 있습니다. 이때 외부 주문번호 열에 단일 UNIQUE 제약조건이 걸려 있으면 B사 주문은 저장 단계에서 충돌합니다. PostgreSQL 18을 기준으로 거래처 코드를 키에 넣는 판단과 운영 전 확인 절차를 살펴봅니다.

주문번호 발급 주체와 재사용 범위
먼저 연계 명세서와 원본 주문 샘플에서 번호를 누가 발급하는지 확인합니다. 중앙 주문 시스템이 모든 거래처에 걸쳐 번호의 유일성을 보장하면 UNIQUE (order_no)가 맞습니다. 이 경우 거래처별로 같은 번호를 허용하면 중앙 발급 규칙을 위반한 데이터도 저장될 수 있습니다. 거래처마다 독립적으로 번호를 발급하고 같은 거래처 안에서 유일성을 보장하면 UNIQUE (partner_code, order_no)가 맞습니다. PostgreSQL은 이때 두 열의 값 조합이 같은 행을 차단합니다. PostgreSQL 18 — 제약조건
| 번호를 발급하는 방식 | 유일성 제약 예시 | 판단 근거 |
|---|---|---|
| 중앙 시스템에서 통합 발급 | UNIQUE (order_no) | 전체 거래처에서 번호 하나가 주문 하나를 가리킵니다. |
| 거래처마다 독립 발급 | UNIQUE (partner_code, order_no) | 다른 거래처가 같은 번호를 발급할 수 있습니다. |
| 같은 거래처가 발급 연도마다 번호를 다시 사용 | UNIQUE (partner_code, issue_year, order_no) | 발급 연도 안에서 유일성이 보장된다는 전제가 필요합니다. |
연말에 번호가 초기화된다면 원본이 제공하는 발급 연도를 확인합니다. 12월 주문을 1월에 재수신했을 때 수신 연도로 키를 만들면 같은 주문이 새 조합으로 등록될 수 있습니다. 거래처 코드가 바뀌거나 재사용되는 환경이라면, 외부 코드를 내부의 고정된 거래처 ID로 매핑한 뒤 그 ID를 키에 사용하는 편이 안정적입니다.

기존 데이터에서 확인할 두 종류의 중복
기존 단일 제약이 이미 적용돼 있다면 운영 주문 테이블에는 다른 거래처 사이의 정상적인 번호 중복이 남아 있지 않을 수 있습니다. 기존 제약에 걸려 저장되지 않은 주문도 확인할 수 있도록, 동일 파일의 재전송분을 구분한 원본 주문 헤더를 검증용 테이블에 모읍니다. 아래 예시는 번호가 여러 거래처에 걸쳐 쓰인 경우와 같은 거래처 안에서 조합이 반복된 경우를 따로 조회합니다. PostgreSQL 18 — SELECT의 GROUP BY와 HAVING
SELECT order_no, COUNT(DISTINCT partner_code) AS partner_count
FROM order_header_stage
WHERE partner_code IS NOT NULL AND order_no IS NOT NULL
GROUP BY order_no
HAVING COUNT(DISTINCT partner_code) > 1;
SELECT partner_code, order_no, COUNT(*) AS row_count
FROM order_header_stage
WHERE partner_code IS NOT NULL AND order_no IS NOT NULL
GROUP BY partner_code, order_no
HAVING COUNT(*) > 1;
첫 결과는 번호가 여러 거래처에 나타난 목록입니다. 중앙 발급 방식이라면 원본 발급 내역과 대조하고, 거래처별 발급 방식이라면 서로 다른 주문으로 취급할 수 있는지 확인합니다. 두 번째 결과는 제약조건을 추가하기 전에 조사할 목록입니다. 원본 문서 ID와 수신 이력을 대조해 주문 정정본인지, 발급 범위를 더 나눠야 하는지 확인합니다. 쿼리에서 제외한 NULL 행은 별도로 집계합니다. 두 열이 필수인 설계라면 NOT NULL도 지정합니다. PostgreSQL의 기본 UNIQUE는 키 열에 NULL이 있는 행의 반복을 허용할 수 있습니다. PostgreSQL 18 — 제약조건

저장 키 변경이 조회와 재수신에 미치는 영향
제약조건을 바꾸면 주문번호만으로는 주문 한 건을 특정하기 어려워집니다. 내부 상세 조회와 주문 상세 테이블은 고유한 order_id를 사용하고, 외부 주문번호를 받는 검색·취소 연계에는 거래처 식별값을 함께 전달하도록 맞춥니다. 기존 외래 키가 order_no의 단일 유일성에 의존한다면, 제약을 제거하기 전에 참조를 order_id 또는 새 복합 키로 옮길 계획을 세웁니다. PostgreSQL 18 — 제약조건
재수신 때 ON CONFLICT (order_no)를 사용하는 저장 구문도 점검합니다. 두 열을 키로 확정했다면 ON CONFLICT (partner_code, order_no)로 충돌 대상을 맞춥니다. 번호 하나에 걸린 기존 유일 제약이 남아 있으면 다른 거래처의 동일 번호는 여전히 거절될 수 있습니다. 충돌 후 기존 행을 유지할지, 정정 데이터를 반영할지는 수신 계약에 맞춰 정합니다. PostgreSQL 18 — INSERT의 ON CONFLICT
전환 테스트에서는 A사와 B사의 000417이 각각 등록되는지 확인합니다. 이어 A사 주문을 다시 보내 기존 A사 행에만 합의한 재수신 처리가 적용되는지 확인하고, B사 주문을 조회·취소했을 때 A사 주문 상태가 바뀌지 않는지 비교합니다.
결론
거래처 코드는 주문번호의 유일성이 거래처별로 보장될 때 키에 포함합니다. 번호가 연도별로 재사용된다면 발급 연도까지 확인합니다. 운영 반영 전에는 원본에서 찾아낸 중복과 누락을 분류하고, 확정한 키로 주문 등록부터 재수신과 취소까지 같은 주문을 찾는지 검증합니다.