--- description: TradeDB/MariaDB 임시 조회 시 스키마 확인·PyMySQL % 이스케이프 필수 (실패 재시도 금지) alwaysApply: true --- # DB 임시 조회(adhoc) 안전 규칙 TradeDB/`database.py`로 SQL을 날릴 때 **추측 쿼리 금지**. 실패하면 같은 가정을 반복하지 말 것(토큰 낭비). ## 1. 쿼리 전에 스키마 확인 (필수) 모르는 테이블/컬럼이면 **먼저** `SHOW COLUMNS FROM ` 또는 `DESCRIBE
`. 대표 함정: | 테이블 | 주의 | |--------|------| | `target_candidates` | **전략 컬럼 없음** (code/name/score/price/scan_time/updated_at + market/sector/theme). `strategy_id` SELECT 금지 | | `target_candidates_history` | 컬럼은 `SHOW COLUMNS`로 확인 후 사용. CREATE 기본 DDL과 실제 DB가 다를 수 있음 | | 전략별 후보 | history의 `strategy_id` 또는 별도 테이블/코드 경로를 문서·스키마로 확인 | ## 2. PyMySQL `%` 포맷 충돌 (필수) `TradeDB.conn.execute()`는 pymysql이라 SQL 문자열의 `%`가 포맷으로 해석된다. - ❌ `LIKE '20260712%'` / `LIKE '%BREAK%'` (단독 문자열에 `%`) - ✅ 바인딩: `LIKE %s` + params `('20260712%',)` - ✅ 또는 `%%` 이스케이프: `LIKE '20260712%%'` `not enough arguments for format string` = 이 문제. 스키마 문제가 아님. ## 3. 실패 시 재시도 규칙 1. 에러 읽기 → 원인 분류(포맷 vs 컬럼없음 vs 테이블없음) 2. **스키마/바인딩 고친 뒤 1회만** 재실행 3. 같은 실패를 다른 날짜·다른 strategy 문자열로 반복 금지 4. 불확실하면 `database.py`의 CREATE/migrate/`get_*` 헬퍼를 읽고 그걸 쓰거나, 헬퍼에 없는 조회면 스키마 확인 후 작성 ## 4. 최소 템플릿 ```python from database import TradeDB db = TradeDB() cols = [r["Field"] for r in db.conn.execute("SHOW COLUMNS FROM target_candidates_history").fetchall()] # cols 확인 후 SELECT. LIKE는 반드시 %s 바인딩 rows = db.conn.execute( "SELECT slot_key, COUNT(*) n FROM target_candidates_history WHERE slot_key LIKE %s GROUP BY slot_key", ("20260712%",), ).fetchall() ```