ollama 오픈소스 LLM gemma4 를 이용해서, 자연어로 sql 검색 가능한 text2sql 기능 테스트.
### 작성물 : ollama 로컬 LLM gemma4 를 이용한 Mysql DB 의 text2sql 기능 테스트
### 작성일 : 2026-05-15
### 작성자 : 바다클라우드 [email protected]
LLM 로 놀다가 gemma4 도움으로 초보적인걸 간단하게 만들어봤습니다.
Mysql DB 에 저장된 정보를, sql 전문가가 쿼리문으로 정보를 뽑는게 아니라,
sql을 몰라도 자연어, 일상어로 입력해서 정보를 다룰수 있는 기능입니다.
이 text2sql 기능은,
원래 openAI 에서 만든 API 에 있는 기능인데, 다른 언어모델들도 같이 적용을해서
ollama 에 공개된 모델들도 같은 API 로 사용가능하게 됐다고 합니다.
내 PC 가 리눅스인데, 여기에 ollama 를 설치하고, 최근에 나온 gemma4 를 설치해서
테스트 해봤습니다.
자신의 PC 에 설치된 오픈소스 LLM 을 사용하므로, 토큰비용 없이 사용가능합니다.
### 사전 설정 사항.
1. ollama 설치해서 gemma4:31b-cloud 를 설치합니다.
gemma4:latest 를 직접 설치해도 되는데 , 내 컴이 사양이 낮아서 cloud 로 했습니다.
>> nonots@nonots-hp:~$ ollama list
>> NAME ID SIZE MODIFIED
>> gemma4:31b-cloud c382fbfbc73b - 43 hours ago ===> 이걸 사용합니다.
>> kimi-k2.6:cloud a90cd0d1590c - 3 weeks ago
>> nemotron-3-super:cloud be3943c5a818 - 5 weeks ago
>> gemma4:latest c6eb396dbd59 9.6 GB 5 weeks ago
>> qwen3-coder-next:cloud aa626c11ae8d - 8 weeks ago
>> qwen3.5:cloud a7bf6f7891c3 - 8 weeks ago
2. Mysql 데몬을 설치해서, db 와 db사용자를 만들어서 아래 간단한 테스트용
테이블 2개를 생성합니다. member 는 회원정보, orderinfo 는 주문정보입니다.
CREATE TABLE `member` (
`idx` int NOT NULL AUTO_INCREMENT,
`userid` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`username` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`address` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`email` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`tel` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth` date DEFAULT NULL,
`indate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`idx`),
UNIQUE KEY `userid` (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `member` VALUES (2,'nonots','나이름','서울시 갈현','[email protected]','010-2222-333','2026-04-16','2026-04-01 07:11:02');
INSERT INTO `member` VALUES (3,'bada3','나바다','서울시 바다면 면','[email protected]','011-222-3333','2026-04-16','2026-04-01 07:30:23');
INSERT INTO `member` VALUES (4,'user001','김철수','서울특별시 강남구 테헤란로 123','cheolsu.[email protected]','010-1234-5678','1990-05-15','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (5,'user002','이영희','부산광역시 해운대구 해운대로 456','younghee.[email protected]','010-2345-6789','1985-08-22','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (6,'user003','김민수','경기도 성남시 분당구 불정로 789','minsu.[email protected]','010-3456-7890','1992-11-03','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (7,'user004','정수진','대광역시 수성구 달구벌대로 1011','sujin.[email protected]','010-4567-8901','1988-03-28','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (8,'user005','최동현','서울특별시 마포구弘대문로 1213','donghyun.[email protected]','010-5678-9012','1995-07-19','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (9,'user006','강지영','인천광역시 남구 인하로 1415','jiyoung.[email protected]','010-6789-0123','1993-12-05','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (10,'user007','윤서준','서울특별시 강동구 천호대로 1617','seojun.[email protected]','010-7890-1234','1991-09-14','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (11,'user008','홍길동','광주광역시东区笔山洞 1819','gildong.[email protected]','010-8901-2345','1987-04-25','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (12,'user009','임미영','대전광역시 유성구 계백로 2021','miyoung.[email protected]','010-9012-3456','1994-06-08','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (13,'user010','신동욱','서울특별시 동작구 사당로 2223','donguk.[email protected]','010-0123-4567','1989-10-30','2026-04-10 01:17:26');
CREATE TABLE `orderinfo` (
`idx` int NOT NULL AUTO_INCREMENT,
`userid` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`product` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`price` int DEFAULT NULL,
`count_num` int DEFAULT NULL,
`indate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `orderinfo` VALUES (1,'bada3','마법의 다이어트 껌',10000,1,'2024-01-18 15:00:00');
INSERT INTO `orderinfo` VALUES (2,'nonots','밤샘 보장 고카페인 물약',20000,2,'2024-10-22 15:00:00');
INSERT INTO `orderinfo` VALUES (3,'user001','어색함 제거용 대화 가이드',15000,1,'2024-11-27 15:00:00');
INSERT INTO `orderinfo` VALUES (4,'user002','월요병 치료용 상상 휴가권',30000,3,'2024-02-11 15:00:00');
INSERT INTO `orderinfo` VALUES (5,'user003','로또 당첨 기원 부적',12000,1,'2024-11-03 15:00:00');
INSERT INTO `orderinfo` VALUES (6,'user004','전남친/전여친 차단용 특수 안경',25000,2,'2024-11-15 15:00:00');
INSERT INTO `orderinfo` VALUES (7,'user005','과제 자동완성 펜',8000,5,'2024-11-05 15:00:00');
INSERT INTO `orderinfo` VALUES (8,'user006','잠 깨우는 벼락 알람',40000,1,'2024-08-13 15:00:00');
INSERT INTO `orderinfo` VALUES (9,'user007','사회생활 만렙 가면',11000,2,'2024-07-17 15:00:00');
INSERT INTO `orderinfo` VALUES (10,'user008','먼지 먹는 최첨단 청소기',5000,10,'2024-11-15 15:00:00');
### 이제 웹서버를 실행해서 아래 파일을 실행합니다.
php 실행용 간단한 웹서버는 php -S localhost:8000 와 같이 하면
서버에서 일반 사용자 권한으로 웹서버를 8000 번 포트로 접속 가능합니다.
아래 소스에서 핵심은 $schema 와 $prompt 부분인거 같습니다.
아래 소스를 text2sql.php 로 저장후 , 웹서버에서 실행합니다.
http://localhost:8000/text2sql.php 와 같이 접속하면, 첨부한 이미지와 같이 사용가능합니다.
이제 개떡같이 말해도 gemma4 가 찰떡같이 알아듣고 자동으로 SQL 문을 생성해서
실행해 줍니다.
예를 들면,
"회원 나이가 40대인 회원을 뽑아줘."
"회원중 서울에 사는 회원을 알려줘."
"회원중 김씨 성을 가진 회원이 주문한 정보와 그 회원의 정보를 같이 보여줘."
"주문한 정보중 주문 금액 순으로 정렬해서 5개만 보여줘."
"회원정보에
이름 : 나그네
아이디 : guest
주소 : 안동시 중구 대신동
이메일 : [email protected]
생일 : 1922-01-22
이 정보로 회원을 추가 해줘."
"회원중에 아이디가 guest 인 회원을 삭제해줘."
이런 입력을 하면, 알아듣고 직접 db 에 쿼리문을 생성해 줍니다.
### 주의할점.
- 보안상 select 검색 기능만 부여한 db 아이디를 사용하는게 좋습니다.
delete , update ,insert 권한으로 잘못하면, 낭패를 당할수도.
- select 로 출력시 매우 많은 row 출력은 자원을 고갈시킬수 있으므로,
아래 소스에서 주석처리한 limit 를 강제 적용해서 제한하는게 좋습니다.
//========================== 소스 시작 ======================
<?php
// DB 접속정보
$host = 'localhost';
$dbname = 'db_name';
$username = 'db_id';
$password = 'xxxxxx';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
function textToSqlOllama($userInput, $pdo) {
// 1. 스키마 정보
//$stmt = $pdo->query("DESCRIBE member");
//$columns = $stmt->fetchAll(PDO::FETCH_COLUMN);
//$schema = "Table: member(회원정보) , Columns: " . implode(", ", $columns);
$schema = "
Table: member(회원정보) ,
Columns: idx, userid(아이디) , username, address(주소), email, tel, birth, indate (가입일)
Table: orderinfo(주문정보),
Columns: idx, userid, product(제품명), price(주문액), count_num(갯수), indate(주문일)
";
$prompt = "당신은 SQL 전문가입니다. 자연어로 된 질의를 완전한 MySQL SQL 쿼리 문으로 변환해 주세요.\n";
$prompt .= "Database Schema: $schema\n";
$prompt .= "Request: $userInput\n";
$prompt .= "Return ONLY the SQL query without any markdown, explanation, or backticks.";
//Ollama API 호출 설정
$url = 'http://localhost:11434/v1/chat/completions'; // Ollama API 주소
$data = [
'model' => 'gemma4:31b-cloud', // 설치하신 Ollama 모델명으로 변경
'messages' => [['role' => 'user', 'content' => $prompt]],
'temperature' => 0
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json'
// Ollama는 기본적으로 API Key가 필요 없으므로 생략 가능합니다.
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
return trim($result['choices'][0]['message']['content'] ?? '');
}
//사용자 입력
$userInput = $_REQUEST['userInput'];
if( $userInput){
$sql = textToSqlOllama($userInput, $pdo);
/*
// 출력 목록이 많을 경우 강제로 limit 제한
if( preg_match("/^select/i", $sql) && !preg_match("/limit/i", $sql)) {
$sql = str_replace(";","",$sql);
$sql .= " limit 300 "; // 최대 300건 제한
}
*/
try {
// 보안 주의: 생성된 SQL을 그대로 실행하는 것은 매우 위험합니다 (SQL Injection)
// 실제 서비스에서는 실행 전 SQL 검증 단계가 반드시 필요합니다.
$stmt = $pdo->query($sql);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo "Query 실행 오류: " . $e->getMessage();
}
}
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>SQL</title>
</head>
<body>
<form method=post>
<textarea name=userInput rows=5 cols=60 id="userInput"><?php echo $userInput;?></textarea> <br>
* 생성한 SQL : <?php echo $sql;?><br>
<input type=submit value='실행'>
<input type=button value='취소' onclick="document.getElementById('userInput').value='';">
</form>
<hr>
<table border=1>
<?php
if( $results){
//foreach( $results as $k=>$v){ $karr = array_keys($v); }
$karr = array_keys($results[0]);
echo "<tr>";
foreach($karr as $vv){ echo "<td>".$vv."</td>"; }
echo "</tr>";
foreach( $results as $k=>$v){
echo "<tr>";
foreach($v as $vvv){ echo "<td>".$vvv."</td>"; }
echo "</tr>";
}
}
//echo "<pre>"; print_r($results); echo "</pre>"; ?>
</table>
</body>
</html>
//========================== 소스 끝 ======================
### 작성일 : 2026-05-15
### 작성자 : 바다클라우드 [email protected]
LLM 로 놀다가 gemma4 도움으로 초보적인걸 간단하게 만들어봤습니다.
Mysql DB 에 저장된 정보를, sql 전문가가 쿼리문으로 정보를 뽑는게 아니라,
sql을 몰라도 자연어, 일상어로 입력해서 정보를 다룰수 있는 기능입니다.
이 text2sql 기능은,
원래 openAI 에서 만든 API 에 있는 기능인데, 다른 언어모델들도 같이 적용을해서
ollama 에 공개된 모델들도 같은 API 로 사용가능하게 됐다고 합니다.
내 PC 가 리눅스인데, 여기에 ollama 를 설치하고, 최근에 나온 gemma4 를 설치해서
테스트 해봤습니다.
자신의 PC 에 설치된 오픈소스 LLM 을 사용하므로, 토큰비용 없이 사용가능합니다.
### 사전 설정 사항.
1. ollama 설치해서 gemma4:31b-cloud 를 설치합니다.
gemma4:latest 를 직접 설치해도 되는데 , 내 컴이 사양이 낮아서 cloud 로 했습니다.
>> nonots@nonots-hp:~$ ollama list
>> NAME ID SIZE MODIFIED
>> gemma4:31b-cloud c382fbfbc73b - 43 hours ago ===> 이걸 사용합니다.
>> kimi-k2.6:cloud a90cd0d1590c - 3 weeks ago
>> nemotron-3-super:cloud be3943c5a818 - 5 weeks ago
>> gemma4:latest c6eb396dbd59 9.6 GB 5 weeks ago
>> qwen3-coder-next:cloud aa626c11ae8d - 8 weeks ago
>> qwen3.5:cloud a7bf6f7891c3 - 8 weeks ago
2. Mysql 데몬을 설치해서, db 와 db사용자를 만들어서 아래 간단한 테스트용
테이블 2개를 생성합니다. member 는 회원정보, orderinfo 는 주문정보입니다.
CREATE TABLE `member` (
`idx` int NOT NULL AUTO_INCREMENT,
`userid` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`username` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`address` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`email` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`tel` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth` date DEFAULT NULL,
`indate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`idx`),
UNIQUE KEY `userid` (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `member` VALUES (2,'nonots','나이름','서울시 갈현','[email protected]','010-2222-333','2026-04-16','2026-04-01 07:11:02');
INSERT INTO `member` VALUES (3,'bada3','나바다','서울시 바다면 면','[email protected]','011-222-3333','2026-04-16','2026-04-01 07:30:23');
INSERT INTO `member` VALUES (4,'user001','김철수','서울특별시 강남구 테헤란로 123','cheolsu.[email protected]','010-1234-5678','1990-05-15','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (5,'user002','이영희','부산광역시 해운대구 해운대로 456','younghee.[email protected]','010-2345-6789','1985-08-22','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (6,'user003','김민수','경기도 성남시 분당구 불정로 789','minsu.[email protected]','010-3456-7890','1992-11-03','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (7,'user004','정수진','대광역시 수성구 달구벌대로 1011','sujin.[email protected]','010-4567-8901','1988-03-28','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (8,'user005','최동현','서울특별시 마포구弘대문로 1213','donghyun.[email protected]','010-5678-9012','1995-07-19','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (9,'user006','강지영','인천광역시 남구 인하로 1415','jiyoung.[email protected]','010-6789-0123','1993-12-05','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (10,'user007','윤서준','서울특별시 강동구 천호대로 1617','seojun.[email protected]','010-7890-1234','1991-09-14','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (11,'user008','홍길동','광주광역시东区笔山洞 1819','gildong.[email protected]','010-8901-2345','1987-04-25','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (12,'user009','임미영','대전광역시 유성구 계백로 2021','miyoung.[email protected]','010-9012-3456','1994-06-08','2026-04-10 01:17:26');
INSERT INTO `member` VALUES (13,'user010','신동욱','서울특별시 동작구 사당로 2223','donguk.[email protected]','010-0123-4567','1989-10-30','2026-04-10 01:17:26');
CREATE TABLE `orderinfo` (
`idx` int NOT NULL AUTO_INCREMENT,
`userid` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`product` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`price` int DEFAULT NULL,
`count_num` int DEFAULT NULL,
`indate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `orderinfo` VALUES (1,'bada3','마법의 다이어트 껌',10000,1,'2024-01-18 15:00:00');
INSERT INTO `orderinfo` VALUES (2,'nonots','밤샘 보장 고카페인 물약',20000,2,'2024-10-22 15:00:00');
INSERT INTO `orderinfo` VALUES (3,'user001','어색함 제거용 대화 가이드',15000,1,'2024-11-27 15:00:00');
INSERT INTO `orderinfo` VALUES (4,'user002','월요병 치료용 상상 휴가권',30000,3,'2024-02-11 15:00:00');
INSERT INTO `orderinfo` VALUES (5,'user003','로또 당첨 기원 부적',12000,1,'2024-11-03 15:00:00');
INSERT INTO `orderinfo` VALUES (6,'user004','전남친/전여친 차단용 특수 안경',25000,2,'2024-11-15 15:00:00');
INSERT INTO `orderinfo` VALUES (7,'user005','과제 자동완성 펜',8000,5,'2024-11-05 15:00:00');
INSERT INTO `orderinfo` VALUES (8,'user006','잠 깨우는 벼락 알람',40000,1,'2024-08-13 15:00:00');
INSERT INTO `orderinfo` VALUES (9,'user007','사회생활 만렙 가면',11000,2,'2024-07-17 15:00:00');
INSERT INTO `orderinfo` VALUES (10,'user008','먼지 먹는 최첨단 청소기',5000,10,'2024-11-15 15:00:00');
### 이제 웹서버를 실행해서 아래 파일을 실행합니다.
php 실행용 간단한 웹서버는 php -S localhost:8000 와 같이 하면
서버에서 일반 사용자 권한으로 웹서버를 8000 번 포트로 접속 가능합니다.
아래 소스에서 핵심은 $schema 와 $prompt 부분인거 같습니다.
아래 소스를 text2sql.php 로 저장후 , 웹서버에서 실행합니다.
http://localhost:8000/text2sql.php 와 같이 접속하면, 첨부한 이미지와 같이 사용가능합니다.
이제 개떡같이 말해도 gemma4 가 찰떡같이 알아듣고 자동으로 SQL 문을 생성해서
실행해 줍니다.
예를 들면,
"회원 나이가 40대인 회원을 뽑아줘."
"회원중 서울에 사는 회원을 알려줘."
"회원중 김씨 성을 가진 회원이 주문한 정보와 그 회원의 정보를 같이 보여줘."
"주문한 정보중 주문 금액 순으로 정렬해서 5개만 보여줘."
"회원정보에
이름 : 나그네
아이디 : guest
주소 : 안동시 중구 대신동
이메일 : [email protected]
생일 : 1922-01-22
이 정보로 회원을 추가 해줘."
"회원중에 아이디가 guest 인 회원을 삭제해줘."
이런 입력을 하면, 알아듣고 직접 db 에 쿼리문을 생성해 줍니다.
### 주의할점.
- 보안상 select 검색 기능만 부여한 db 아이디를 사용하는게 좋습니다.
delete , update ,insert 권한으로 잘못하면, 낭패를 당할수도.
- select 로 출력시 매우 많은 row 출력은 자원을 고갈시킬수 있으므로,
아래 소스에서 주석처리한 limit 를 강제 적용해서 제한하는게 좋습니다.
//========================== 소스 시작 ======================
<?php
// DB 접속정보
$host = 'localhost';
$dbname = 'db_name';
$username = 'db_id';
$password = 'xxxxxx';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
function textToSqlOllama($userInput, $pdo) {
// 1. 스키마 정보
//$stmt = $pdo->query("DESCRIBE member");
//$columns = $stmt->fetchAll(PDO::FETCH_COLUMN);
//$schema = "Table: member(회원정보) , Columns: " . implode(", ", $columns);
$schema = "
Table: member(회원정보) ,
Columns: idx, userid(아이디) , username, address(주소), email, tel, birth, indate (가입일)
Table: orderinfo(주문정보),
Columns: idx, userid, product(제품명), price(주문액), count_num(갯수), indate(주문일)
";
$prompt = "당신은 SQL 전문가입니다. 자연어로 된 질의를 완전한 MySQL SQL 쿼리 문으로 변환해 주세요.\n";
$prompt .= "Database Schema: $schema\n";
$prompt .= "Request: $userInput\n";
$prompt .= "Return ONLY the SQL query without any markdown, explanation, or backticks.";
//Ollama API 호출 설정
$url = 'http://localhost:11434/v1/chat/completions'; // Ollama API 주소
$data = [
'model' => 'gemma4:31b-cloud', // 설치하신 Ollama 모델명으로 변경
'messages' => [['role' => 'user', 'content' => $prompt]],
'temperature' => 0
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json'
// Ollama는 기본적으로 API Key가 필요 없으므로 생략 가능합니다.
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
return trim($result['choices'][0]['message']['content'] ?? '');
}
//사용자 입력
$userInput = $_REQUEST['userInput'];
if( $userInput){
$sql = textToSqlOllama($userInput, $pdo);
/*
// 출력 목록이 많을 경우 강제로 limit 제한
if( preg_match("/^select/i", $sql) && !preg_match("/limit/i", $sql)) {
$sql = str_replace(";","",$sql);
$sql .= " limit 300 "; // 최대 300건 제한
}
*/
try {
// 보안 주의: 생성된 SQL을 그대로 실행하는 것은 매우 위험합니다 (SQL Injection)
// 실제 서비스에서는 실행 전 SQL 검증 단계가 반드시 필요합니다.
$stmt = $pdo->query($sql);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo "Query 실행 오류: " . $e->getMessage();
}
}
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>SQL</title>
</head>
<body>
<form method=post>
<textarea name=userInput rows=5 cols=60 id="userInput"><?php echo $userInput;?></textarea> <br>
* 생성한 SQL : <?php echo $sql;?><br>
<input type=submit value='실행'>
<input type=button value='취소' onclick="document.getElementById('userInput').value='';">
</form>
<hr>
<table border=1>
<?php
if( $results){
//foreach( $results as $k=>$v){ $karr = array_keys($v); }
$karr = array_keys($results[0]);
echo "<tr>";
foreach($karr as $vv){ echo "<td>".$vv."</td>"; }
echo "</tr>";
foreach( $results as $k=>$v){
echo "<tr>";
foreach($v as $vvv){ echo "<td>".$vvv."</td>"; }
echo "</tr>";
}
}
//echo "<pre>"; print_r($results); echo "</pre>"; ?>
</table>
</body>
</html>
//========================== 소스 끝 ======================
첨부파일
|
댓글을 작성하시려면 로그인이 필요합니다.