Skip to content

Commit 4d28e73

Browse files
committed
동적변수 기능 추가
1 parent dcbc676 commit 4d28e73

File tree

6 files changed

+745
-9
lines changed

6 files changed

+745
-9
lines changed

CHANGELOG.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,74 @@
11
# SQL2Excel 버전 히스토리
22

3+
## v1.2.2 - 동적 변수 시스템 추가 (2025-08-20)
4+
5+
### ✨ 새로운 기능
6+
- **🔄 동적 변수 시스템**: 데이터베이스에서 실시간으로 값을 조회하여 동적 쿼리 생성
7+
- **📊 3가지 동적 변수 타입**: `column_identified`, `key_value_pairs`, 기본 타입 지원
8+
- **🔗 시각 함수 통합**: 동적 변수에서 `CURRENT_TIMESTAMP`, `CURRENT_DATE` 등 시각 함수 사용 가능
9+
- **🌐 환경 변수 지원**: 동적 변수에서 환경 변수 사용 가능
10+
- **🐛 디버그 모드**: `DEBUG_VARIABLES=true` 환경 변수로 변수 치환 과정 상세 로깅
11+
12+
### 🔄 동적 변수 타입별 기능
13+
14+
#### 1. column_identified 타입
15+
- 각 컬럼별로 배열 생성
16+
- `${변수명.컬럼명}` 형태로 특정 컬럼의 값들만 사용
17+
- 예시: `${customerData.CustomerID}`, `${customerData.Region}`
18+
19+
#### 2. key_value_pairs 타입
20+
- 첫 번째 컬럼을 키로, 두 번째 컬럼을 값으로 생성
21+
- `${변수명.키명}` 형태로 키 값들만 사용
22+
- 예시: `${productPrices.ProductID}`
23+
24+
#### 3. 기본 타입
25+
- 첫 번째 컬럼의 값들을 배열로 생성
26+
- `${변수명}` 형태로 전체 배열 사용
27+
- 예시: `${activeCategories}`
28+
29+
### 📝 사용 예시
30+
```xml
31+
<!-- 동적 변수 정의 -->
32+
<dynamicVars>
33+
<dynamicVar name="customerData" type="column_identified" description="고객 데이터 컬럼별 분류">
34+
<![CDATA[
35+
SELECT CustomerID, CustomerName, City, Region
36+
FROM Customers WHERE IsActive = 1
37+
]]>
38+
</dynamicVar>
39+
40+
<dynamicVar name="productPrices" type="key_value_pairs" description="상품별 가격 정보">
41+
<![CDATA[
42+
SELECT ProductID, UnitPrice
43+
FROM Products WHERE Discontinued = 0
44+
]]>
45+
</dynamicVar>
46+
</dynamicVars>
47+
48+
<!-- 동적 변수 사용 -->
49+
<sheet name="고객주문분석">
50+
<![CDATA[
51+
SELECT * FROM Orders
52+
WHERE CustomerID IN (${customerData.CustomerID})
53+
AND Region IN (${customerData.Region})
54+
AND ProductID IN (${productPrices.ProductID})
55+
]]>
56+
</sheet>
57+
```
58+
59+
### 🔧 개선사항
60+
- **변수 치환 우선순위**: 동적 변수 > 일반 변수 > 시각 함수 > 환경 변수 순서로 처리
61+
- **SQL 인젝션 방지**: 모든 변수 값에 대해 적절한 이스케이핑 처리
62+
- **오류 처리 강화**: 동적 변수 처리 중 오류 발생 시 빈 배열로 대체하여 안전성 확보
63+
- **성능 최적화**: 동적 변수는 DB 연결 후, 시트 처리 전에 한 번만 실행
64+
65+
### 📚 문서화
66+
- **README.md 업데이트**: 동적 변수 기능 소개 및 예시 추가
67+
- **USER_MANUAL.md 확장**: 동적 변수 상세 사용법 및 타입별 설명 추가
68+
- **예제 파일 추가**: `queries-with-dynamic-variables.xml`, `queries-with-dynamic-variables.json` 생성
69+
70+
---
71+
372
## v1.2.1 - 문서화 개선 (2025-08-11)
473

574
### 📚 문서화

README.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ SQL 쿼리 결과를 엑셀 파일로 생성하는 Node.js 기반 도구입니
88
- 🎨 **엑셀 스타일링**: 헤더/데이터 영역 각각 폰트, 색상, 테두리, 정렬 등 세부 스타일 설정
99
- 🔗 **다중 DB 연결**: 시트별로 다른 데이터베이스 연결 가능
1010
- 📝 **변수 시스템**: 쿼리 내 변수 사용으로 동적 쿼리 생성
11+
- 🔄 **동적 변수**: 데이터베이스에서 실시간으로 값을 조회하여 동적 쿼리 생성
1112
- 🔄 **쿼리 재사용**: 공통 쿼리 정의 후 여러 시트에서 재사용
1213
- 📋 **자동 목차**: 목차 시트 자동 생성 및 하이퍼링크 제공
1314
- 📊 **집계 기능**: 지정 컬럼의 값별 건수 자동 집계 및 표시
@@ -79,7 +80,7 @@ node src/excel-cli.js help
7980

8081
## 💡 사용 예시
8182

82-
### XML 설정 파일 예시
83+
### XML 설정 파일 예시 (동적 변수 포함)
8384
```xml
8485
<queries>
8586
<excel db="sampleDB" output="output/매출보고서.xlsx">
@@ -89,10 +90,28 @@ node src/excel-cli.js help
8990
</header>
9091
</excel>
9192

93+
<!-- 일반 변수 -->
94+
<vars>
95+
<var name="startDate">2024-01-01</var>
96+
<var name="endDate">2024-12-31</var>
97+
</vars>
98+
99+
<!-- 동적 변수 -->
100+
<dynamicVars>
101+
<dynamicVar name="activeCustomers" type="column_identified" description="활성 고객 목록">
102+
<![CDATA[
103+
SELECT CustomerID, CustomerName, Region
104+
FROM Customers WHERE IsActive = 1
105+
]]>
106+
</dynamicVar>
107+
</dynamicVars>
108+
92109
<sheet name="월별매출" use="true" aggregateColumn="Month">
93110
<![CDATA[
94111
SELECT MONTH(OrderDate) as Month, SUM(TotalAmount) as Sales
95-
FROM Orders WHERE YEAR(OrderDate) = 2024
112+
FROM Orders
113+
WHERE YEAR(OrderDate) = 2024
114+
AND CustomerID IN (${activeCustomers.CustomerID})
96115
GROUP BY MONTH(OrderDate)
97116
]]>
98117
</sheet>
@@ -119,4 +138,4 @@ node src/excel-cli.js export --xml ./queries/sales-report.xml \
119138

120139
---
121140

122-
**버전**: v1.2.1 | **최종 업데이트**: 2025-01-15
141+
**버전**: v1.2.2 | **최종 업데이트**: 2025-08-20

USER_MANUAL.md

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,14 @@ db-test.bat
356356

357357
### 6. 변수 시스템
358358

359-
#### 변수 정의 및 사용
359+
#### 일반 변수 정의 및 사용
360360
```xml
361361
<!-- 변수 정의 -->
362362
<vars>
363363
<var name="startDate">2024-01-01</var>
364364
<var name="endDate">2024-12-31</var>
365365
<var name="targetRegion">서울</var>
366+
<var name="regionList">["서울", "부산", "대구"]</var>
366367
</vars>
367368

368369
<!-- 쿼리에서 변수 사용 -->
@@ -372,6 +373,7 @@ db-test.bat
372373
WHERE Region = '${targetRegion}'
373374
AND SaleDate >= '${startDate}'
374375
AND SaleDate <= '${endDate}'
376+
AND Region IN (${regionList})
375377
]]>
376378
</sheet>
377379
```
@@ -381,6 +383,84 @@ db-test.bat
381383
node src/excel-cli.js export --xml queries.xml --var "startDate=2024-06-01" --var "endDate=2024-06-30"
382384
```
383385

386+
### 7. 동적 변수 시스템
387+
388+
#### 동적 변수 정의
389+
동적 변수는 데이터베이스에서 실시간으로 값을 조회하여 쿼리에 사용할 수 있는 고급 변수 시스템입니다.
390+
391+
```xml
392+
<!-- 동적 변수 정의 -->
393+
<dynamicVars>
394+
<!-- column_identified 타입: 각 컬럼별로 배열 생성 -->
395+
<dynamicVar name="customerData" type="column_identified" description="고객 데이터 컬럼별 분류">
396+
<![CDATA[
397+
SELECT CustomerID, CustomerName, City, Region
398+
FROM Customers WHERE IsActive = 1
399+
]]>
400+
</dynamicVar>
401+
402+
<!-- key_value_pairs 타입: 첫 번째 컬럼을 키로, 두 번째 컬럼을 값으로 -->
403+
<dynamicVar name="productPrices" type="key_value_pairs" description="상품별 가격 정보">
404+
<![CDATA[
405+
SELECT ProductID, UnitPrice
406+
FROM Products WHERE Discontinued = 0
407+
]]>
408+
</dynamicVar>
409+
410+
<!-- 기본 타입: 첫 번째 컬럼의 값들을 배열로 -->
411+
<dynamicVar name="activeCategories" description="활성 카테고리 목록">
412+
<![CDATA[
413+
SELECT CategoryID FROM Categories WHERE IsActive = 1
414+
]]>
415+
</dynamicVar>
416+
</dynamicVars>
417+
```
418+
419+
#### 동적 변수 사용 방법
420+
421+
**1. column_identified 타입 사용**
422+
```sql
423+
-- ${customerData.CustomerID} 형태로 특정 컬럼의 값들만 사용
424+
SELECT * FROM Orders
425+
WHERE CustomerID IN (${customerData.CustomerID})
426+
AND Region IN (${customerData.Region})
427+
```
428+
429+
**2. key_value_pairs 타입 사용**
430+
```sql
431+
-- ${productPrices.ProductID} 형태로 키 값들만 사용
432+
SELECT * FROM OrderDetails
433+
WHERE ProductID IN (${productPrices.ProductID})
434+
```
435+
436+
**3. 기본 타입 사용**
437+
```sql
438+
-- ${activeCategories} 형태로 전체 배열 사용
439+
SELECT * FROM Products
440+
WHERE CategoryID IN (${activeCategories})
441+
```
442+
443+
#### 동적 변수 타입별 특징
444+
445+
| 타입 | 설명 | 사용법 | 예시 |
446+
|------|------|--------|------|
447+
| `column_identified` | 각 컬럼별로 배열 생성 | `${변수명.컬럼명}` | `${customerData.CustomerID}` |
448+
| `key_value_pairs` | 키-값 쌍으로 생성 | `${변수명.키명}` | `${productPrices.ProductID}` |
449+
| 기본 (없음) | 첫 번째 컬럼의 값들을 배열로 | `${변수명}` | `${activeCategories}` |
450+
451+
#### 시각 함수와 조합 사용
452+
```xml
453+
<dynamicVar name="recentOrders" description="최근 주문 정보">
454+
<![CDATA[
455+
SELECT OrderID, OrderNumber
456+
FROM Orders
457+
WHERE OrderDate >= '${startDate}'
458+
AND OrderDate <= '${endDate}'
459+
AND OrderDate >= DATEADD(day, -30, '${CURRENT_DATE}')
460+
]]>
461+
</dynamicVar>
462+
```
463+
384464
## 📋 CLI 명령어 참조
385465

386466
### 1. export - 엑셀 파일 생성
@@ -504,6 +584,6 @@ node src/excel-cli.js help
504584

505585
---
506586

507-
**📝 버전**: v1.2.1
508-
**📅 최종 업데이트**: 2025-01-15
587+
**📝 버전**: v1.2.2
588+
**📅 최종 업데이트**: 2025-08-20
509589
**🔧 주요 기능**: 멀티시트 엑셀 생성, 스타일링, 다중 DB 연결, 쿼리 재사용, 자동 목차
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"excel": {
3+
"db": "sampleDB",
4+
"output": "d:/temp/동적변수_테스트_2024.xlsx",
5+
"separateToc": false,
6+
"maxRows": 20,
7+
"style": "modern"
8+
},
9+
"vars": {
10+
"envType": "운영",
11+
"startDate": "2024-01-01",
12+
"endDate": "2024-06-30",
13+
"regionList": ["서울", "부산"],
14+
"statusList": ["ACTIVE", "PENDING", "COMPLETED"],
15+
"categoryIds": [1, 2, 3, 5],
16+
"maxRows": 1000
17+
},
18+
"dynamicVars": [
19+
{
20+
"name": "customerData",
21+
"type": "column_identified",
22+
"description": "고객 데이터 컬럼별 분류",
23+
"query": "SELECT CustomerID, CustomerName, City, Region, CustomerType FROM SampleDB.dbo.Customers WHERE IsActive = 1 ORDER BY CustomerID"
24+
},
25+
{
26+
"name": "orderDetails",
27+
"type": "key_value_pairs",
28+
"description": "주문상세 정보",
29+
"query": "SELECT OrderID, OrderDetailID FROM SampleDB.dbo.OrderDetails ORDER BY OrderID"
30+
},
31+
{
32+
"name": "activeOrders",
33+
"description": "활성 주문 목록",
34+
"query": "SELECT OrderID FROM SampleDB.dbo.Orders WHERE OrderStatus = 'Pending' ORDER BY OrderID"
35+
},
36+
{
37+
"name": "recentOrders",
38+
"description": "최근 주문 정보",
39+
"query": "SELECT OrderID, OrderNumber, OrderDate FROM SampleDB.dbo.Orders WHERE OrderDate >= '${startDate}' AND OrderDate <= '${endDate}' AND OrderDate >= DATEADD(day, -30, '${CURRENT_DATE}') ORDER BY OrderDate DESC"
40+
}
41+
],
42+
"sheets": [
43+
{
44+
"name": "${envType}_동적변수_테스트",
45+
"use": true,
46+
"aggregateColumn": "지역",
47+
"maxRows": 100,
48+
"db": "sampleDB",
49+
"query": "SELECT c.CustomerID as 고객ID, c.CustomerName as 고객명, c.City as 도시, c.Region as 지역, c.CustomerType as 고객유형 FROM SampleDB.dbo.Customers c WHERE c.CustomerID IN (${customerData.CustomerID}) AND c.Region IN (${regionList}) ORDER BY c.CustomerID"
50+
},
51+
{
52+
"name": "주문상세_동적변수_테스트2",
53+
"use": true,
54+
"aggregateColumn": "주문상태",
55+
"query": "SELECT o.OrderID as 주문ID, o.OrderNumber as 주문번호, o.OrderStatus as 주문상태, od.OrderDetailID as 상세ID, FORMAT(o.TotalAmount, 'N0') as 총금액 FROM SampleDB.dbo.Orders o INNER JOIN SampleDB.dbo.OrderDetails od ON o.OrderID = od.OrderID WHERE o.OrderID IN (${orderDetails.OrderID}) AND o.OrderID IN (${activeOrders}) ORDER BY o.OrderID DESC"
56+
},
57+
{
58+
"name": "주문상세_동적변수_테스트",
59+
"use": true,
60+
"aggregateColumn": "주문상태",
61+
"query": "SELECT o.OrderNumber as 주문번호, FORMAT(o.OrderDate, 'yyyy-MM-dd') as 주문일, o.OrderStatus as 주문상태, c.CustomerName as 고객명, FORMAT(o.TotalAmount, 'N0') as 총금액 FROM SampleDB.dbo.Orders o INNER JOIN SampleDB.dbo.Customers c ON o.CustomerID = c.CustomerID WHERE o.OrderID IN (${recentOrders.OrderID}) AND o.OrderStatus IN (${statusList}) ORDER BY o.OrderDate DESC"
62+
},
63+
{
64+
"name": "복합_동적변수_테스트",
65+
"use": true,
66+
"query": "SELECT c.CustomerName as 고객명, c.Region as 지역, COUNT(o.OrderID) as 주문건수, FORMAT(SUM(o.TotalAmount), 'N0') as 총주문금액 FROM SampleDB.dbo.Customers c INNER JOIN SampleDB.dbo.Orders o ON c.CustomerID = o.CustomerID WHERE c.CustomerID IN (${customerData.CustomerID}) AND c.Region IN (${customerData.Region}) AND o.OrderID IN (${activeOrders}) AND o.OrderDate >= '${startDate}' AND o.OrderDate <= '${endDate}' GROUP BY c.CustomerName, c.Region ORDER BY 총주문금액 DESC"
67+
},
68+
{
69+
"name": "시각함수_동적변수_테스트",
70+
"use": true,
71+
"query": "SELECT '현재시각' as 구분, '${CURRENT_TIMESTAMP}' as 현재시각, '${CURRENT_DATE}' as 현재날짜, '${CURRENT_TIME}' as 현재시간, '${UNIX_TIMESTAMP}' as 유닉스타임스탬프, '${GETDATE}' as SQL서버_GETDATE UNION ALL SELECT '동적변수_테스트' as 구분, CONVERT(VARCHAR, GETDATE(), 120) as 현재시각, CONVERT(VARCHAR, GETDATE(), 23) as 현재날짜, CONVERT(VARCHAR, GETDATE(), 108) as 현재시간, DATEDIFF(SECOND, '1970-01-01', GETDATE()) as 유닉스타임스탬프, GETDATE() as SQL서버_GETDATE"
72+
}
73+
]
74+
}

0 commit comments

Comments
 (0)