Skip to content

L4 · ora-newshop — 신규 이커머스 플랫폼 + FK 원본 ​

포트 1524 · 앱 계정 shop / shop(컨테이너 공통 규약용, 실습에는 안 쓴다) · 크기 약 2GB · 쓰는 화 12 · 18 컨테이너 하나에 성격이 정반대인 스키마 둘이 들어간다. 12화 전에 ORA_SQL_TEST만 만들고, ECOMMERCE는 18화 직전에 만든다.


왜 이 컨테이너가 따로 있나 ​

스키마내용왜 필요한가화
ORA_SQL_TEST『SQL BOOSTER』 책 원본 테이블 9개 + FK 7개 + 채번 테이블인덱스 없는 FK가 자식 테이블 전체에 락을 거는 현상은 FK가 실제로 걸려 있어야 재현된다. 다른 세 컨테이너에는 FK가 없다12
ECOMMERCE3NF로 정규화한 테이블 30개, 445,422행. 구성은 18화에서 직접 조사한다18화 졸업 과제. 처음 보는 스키마를 혼자 진단하는 것이 시험이다18

💡 ORA_SQL_TEST(FK 7개)와 한빛유통(FK 0개)을 나란히 두면 "제약을 걸었을 때와 안 걸었을 때 락 범위가 어떻게 달라지는가"를 두 컨테이너에서 비교할 수 있다(12화가 그렇게 했다).

🔒 ECOMMERCE 봉인 규칙. 18화까지 ERD도, 테이블 목록도 열어 보지 않는다. 미리 보면 졸업 과제가 시험이 아니라 복습이 된다. 이 폴더의 이커머스/는 구축 절차가 필요할 때만 연다. 이커머스_ERD_조감도.md는 18화에서 채점할 때 편다.


만들기 ​

1. 기동 ​

bash
launch_ora ora-newshop 1524 shop
wait_ora   ora-newshop

(launch_ora / wait_ora는 01_첫_고객사_ora-hanorder.md §3 참고)

두 스키마는 각자의 스크립트가 계정을 만들면서 권한까지 준다. shop에는 따로 할 일이 없다.

2. ORA_SQL_TEST (12화 전) — SQL_BOOSTER/README.md의 1~4장 ​

그 README는 컨테이너를 하나만 쓰던 시절(oracle-free)에 쓴 문서다. oracle-free는 ora-newshop으로 바꿔 읽는다.

단계무엇명령 (Git Bash · SQL_BOOSTER/에서)
1계정(SYS, README 1장의 적응판)README의 SQL 블록을 MSYS_NO_PATHCONV=1 docker exec -i ora-newshop sqlplus -s / as sysdba에 흘려 넣는다. 책 원본 C1_01_DB사용자생성.sql은 E:\ 경로를 쓰므로 그대로 실행하면 안 된다
2테이블 9개 + FK 7개아래 블록 ①
3기준 데이터아래 블록 ②. ★ 앞에 SET SQLBLANKLINES ON을 붙여서
4통계 + 검증아래 블록 ③

Git Bash(SQL_BOOSTER/에서):

bash
S="docker exec -i ora-newshop sqlplus -s ORA_SQL_TEST/1qaz2wsx@localhost/FREEPDB1"
{ echo "SET SQLBLANKLINES ON"; cat C1_02_테이블생성.sql; echo; echo EXIT; } | $S     # ①
{ echo "SET SQLBLANKLINES ON"; cat C1_03_데이터생성.sql; echo; echo EXIT; } | $S     # ②
echo "EXEC DBMS_STATS.GATHER_SCHEMA_STATS('ORA_SQL_TEST');" | $S                     # ③

PowerShell(SQL_BOOSTER\에서):

powershell
$OutputEncoding = New-Object System.Text.UTF8Encoding $false     # 공통코드 이름이 한글이다
function Feed($File) { & { 'SET SQLBLANKLINES ON'; Get-Content $File -Encoding UTF8; ''; 'EXIT' } | docker exec -i ora-newshop sqlplus -s ORA_SQL_TEST/1qaz2wsx@localhost/FREEPDB1 }
Feed C1_02_테이블생성.sql; Feed C1_03_데이터생성.sql
"EXEC DBMS_STATS.GATHER_SCHEMA_STATS('ORA_SQL_TEST');" | docker exec -i ora-newshop sqlplus -s ORA_SQL_TEST/1qaz2wsx@localhost/FREEPDB1

🐞 SET SQLBLANKLINES ON을 빼면 C_BAS_CD(공통코드)가 조용히 0행이 된다. 책 원본의 INSERT … SELECT … UNION ALL 문 중간에 공백만 있는 줄이 끼어 있어서, SQL*Plus가 거기서 문장을 끊고 오류 없이 버리기 때문이다(실측). 버거원 생성기와 같은 함정이다. 원본 파일은 고치지 않고, 흘려 넣을 때 앞에 한 줄을 붙인다.

계정명과 비밀번호는 책과 같은 ORA_SQL_TEST / 1qaz2wsx로 고정한다. C6의 통계 명령에 스키마명이 하드코딩되어 있기 때문이다. 12화에 필요한 건 여기까지다. C6(T_ORD_BIG) 이후 챕터는 책을 따라가고 싶을 때만 한다.

검증: 12화의 전제

sql
SELECT COUNT(*) FROM user_constraints WHERE constraint_type = 'R';   -- 7  (FK 가 실제로 걸려 있다)
SELECT table_name, num_rows FROM user_tables ORDER BY 1;
-- 9 테이블: C_BAS_CD 15 · C_BAS_CD_DV 6 · M_CUS 90 · M_ITM 100 · M_ITM_PRC_HIS 120 · M_RGN 5
--           T_ITM_EVL 345 · T_ORD 3,047 · T_ORD_DET 3,224      (C_BAS_CD 가 0 이면 SQLBLANKLINES 를 빠뜨린 것)
SELECT bas_cd, bas_cd_nm FROM C_BAS_CD WHERE bas_cd_dv = 'ITM_TP';   -- 옷 · 주방도구 · 가전제품 · 컴퓨터 (? 로 나오면 PowerShell 인코딩)

3. ECOMMERCE (18화 직전) — 이커머스/이커머스_데이터셋_구축가이드.md ​

데이터는 저장소에 없다. 내 PC에서 Python(uv)으로 생성해서 컨테이너로 넣는다. 가이드의 oracle-free는 ora-newshop으로 바꿔 읽는다. uv가 없으면 먼저 설치한다. Windows에서는 winget install --id astral-sh.uv로 설치하고 셸을 새로 연다. 그 밖의 OS는 https://docs.astral.sh/uv/ 참고.

단계무엇요점
1생성(내 PC)git clone https://github.com/voidmain443/oracle_db_tutorial.git → 그 폴더에서 uv run python <이 저장소>/10_본편_튜너의_1년/00_자료준비/고객사/L4_ora-newshop/이커머스/고정_실행.py → output/에 CSV · ctl · install.sql · load_data.sh가 생긴다(수십 초)
2전송 + 소유권docker exec ora-newshop mkdir -p /opt/oracle/all_schema → MSYS_NO_PATHCONV=1 docker cp output/ ora-newshop:/opt/oracle/all_schema/output/ → MSYS_NO_PATHCONV=1 docker exec -u 0 ora-newshop chown -R oracle:oinstall /opt/oracle/all_schema
3스키마(SYS)MSYS_NO_PATHCONV=1 docker exec -it ora-newshop sqlplus / as sysdba → @/opt/oracle/all_schema/output/install.sql. 비밀번호를 프롬프트로 묻는다(예: ecommerce)
4적재(컨테이너 안)docker exec -it ora-newshop bash → cd /opt/oracle/all_schema/output && bash load_data.sh. 3단계와 같은 비밀번호 · 약 4분
5통계 + 대조(SYS)이커머스/이커머스_적재후_통계수집_점검.sql: 통계 수집 · 테이블 30개 행수 대조 · sqlp 읽기 권한

★ 왜 uv run src/main.py(레포 README)가 아니라 고정_실행.py인가? 원본 생성기는 난수 시드를 고정하지 않고, 날짜를 "지금부터 최근 5년"처럼 실행 시각 기준으로 만든다. 그대로 돌리면 사람마다, 날마다 다른 데이터가 나온다(실측: 같은 PC에서 두 번 돌렸더니 파일 18개가 달랐다). 고정_실행.py는 원본 코드를 고치지 않고 ① 시드를 고정하고 ② 생성기가 보는 '지금'을 고정하고 ③ Windows에서 생성할 때 .sh · .sql · .ctl이 CRLF가 되는 것을 LF로 되돌린다. 이렇게 하지 않으면 4단계가 ORA-01005: invalid password로 30개 테이블을 하나도 싣지 못한다(실측). 이 방법으로 두 번 생성했더니 파일 67개가 바이트까지 같았고, 서로 다른 컨테이너 두 대에 실었을 때 테이블 30개의 모든 컬럼 해시가 같았다.

검증: 5단계 스크립트 끝에 30개 전부 OK와 테이블 수=30 · 총 행수=445422가 나와야 한다. 구성(테이블, 키, 인덱스)은 18화에서 직접 조사하고, 여기서는 행수만 맞춘다.

⚠️ 5단계 스크립트에서 읽기 권한을 받는 sqlp는 한빛유통 컨테이너가 아니라 이 컨테이너의 sqlp 계정이다. 이 컨테이너에는 sqlp가 없으므로 그 GRANT는 실패해도 된다(주석 처리해도 된다). 18화는 ecommerce 계정으로 직접 접속한다.


안 쓸 때는 끈다 ​

bash
docker stop ora-newshop         # 12·18화가 아니면 꺼 둔다

📚 데이터 출처: 『SQL BOOSTER』(유일환) 책 원본 SQL · oracle_db_tutorial (Python Faker 생성기)