记录一个SQL自动执行的html页面
在实际工作场景中,需要运用到大量SQL语句更新业务逻辑,对程序员本身,写好的sql语句执行没有多大问题,但是对于普通用户来说还是有操作难度的。因此我们需要构建一个HTML页面,并结合JavaScript来发送请求到服务器端执行SQL语句。这里需要注意的是,在实际应用中直接通过前端请求执行SQL语句存在严重的安全隐患(如SQL注入攻击),通常的做法是在服务端进行严格的验证和处理。
以下是我的一个实际案例:
HTML 页面代码
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f4f4f4;
}
h2 {
color: #333;
}
button {
background-color: #007BFF;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #0056b3;
}
#output, #failedSql, #slowSql, #completionMessage {
margin-top: 20px;
padding: 15px;
background-color: white;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#failedSql {
background-color: #ffe6e6;
border-left: 5px solid #d9534f;
}
#slowSql {
background-color: #fff3cd;
border-left: 5px solid #f0ad4e;
}
#completionMessage {
background-color: #dff0d8;
border-left: 5px solid #5cb85c;
}
.modal {
display: none; /* 默认隐藏 */
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
padding-top: 60px;
}
.modal-content {
background-color: #fefefe;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
border-radius: 5px;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
}
</style>
<h2>第53届名家具展邀约渠道统计</h2>
<h5>仅限公司内网操作(192.168.100.100-250)</h5>
<button onclick="fetchAndExecuteSqlStatements()">开始执行</button>
<div id="output"></div>
<!-- 新增一个区域用于展示失败的SQL -->
<div id="failedSql" style="">
<h3>失败的SQL语句:</h3>
</div>
<!-- 新增一个区域用于展示耗时超过1秒的SQL -->
<div id="slowSql" style="">
<h3>耗时超过1秒的SQL语句:</h3>
</div>
<!-- 新增一个区域用于展示所有任务执行完成后的信息 -->
<div id="completionMessage" style="">
<h3>成功与否</h3>
</div>
<!--<a href="#" id="openModalBtn">点击查看弹窗</a>-->
<!-- 模态框 -->
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<p>这是一个模态框的内容。</p>
</div>
</div>
<script>
const url = 'xxx.com/api' // 实际业务api
const sqlTasks = {$sqlTasks} // sql语句通过模板赋值
async function fetchAndExecuteSqlStatements() {
let outputDiv = document.getElementById('output');
let failedSqlDiv = document.getElementById('failedSql');
let slowSqlDiv = document.getElementById('slowSql');
let completionMessageDiv = document.getElementById('completionMessage');
let totalTasks = Object.keys(sqlTasks).length;
let completedTasks = 0;
let hasFailedTask = false;
for (let [description, sql] of Object.entries(sqlTasks)) {
try {
let startTime = new Date().getTime();
const response = await fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({sql: sql})
});
let endTime = new Date().getTime();
let executionTime = (endTime - startTime) / 1000;
const result = await response.json();
if(result.code == 1) {
outputDiv.innerHTML += `<p>执行任务: "${description}" 结果: 成功,耗时: ${executionTime.toFixed(2)} 秒</p>`;
if(executionTime > 1) {
slowSqlDiv.innerHTML += `<p>SQL语句: "${sql}" 耗时: ${executionTime.toFixed(2)} 秒</p>`;
}
} else {
outputDiv.innerHTML += `<p>执行任务: "${description}" 结果: 失败 - ${result.msg}</p>`;
failedSqlDiv.innerHTML += `<p>SQL语句: "${sql}"</p>`;
hasFailedTask = true;
}
} catch (error) {
let endTime = new Date().getTime();
let executionTime = (endTime - startTime) / 1000;
outputDiv.innerHTML += `<p>执行任务: "${description}" 结果: 失败 - ${error.message},耗时: ${executionTime.toFixed(2)} 秒</p>`;
failedSqlDiv.innerHTML += `<p>SQL语句: "${sql}"</p>`;
hasFailedTask = true;
}
completedTasks++;
if(completedTasks === totalTasks) {
if(hasFailedTask) {
completionMessageDiv.innerHTML = '<h3>注意:</strong>部分任务执行失败,请检查错误日志。<h3>';
} else {
completionMessageDiv.innerHTML = '<h3>恭喜:</strong>所有任务执行成功。记得刷新<h3>';
}
}
}
}
// 模态框相关脚本
var modal = document.getElementById("myModal");
var btn = document.getElementById("openModalBtn");
var span = document.getElementsByClassName("close")[0];
btn.onclick = function() { modal.style.display = "block"; }
span.onclick = function() { modal.style.display = "none"; }
window.onclick = function(event) {
if (event.target == modal) { modal.style.display = "none"; }
}
</script>
模板赋值
private function getSql(){
$name = 'miniform';
$info = get_addon_info($name);
$config = get_addon_config($name);
$arr = isset($config['qudaosql']) ? $config['qudaosql'] : [];
return $arr;
}
public function aa(){
if($this->request->isGet()){
$arr = self::getSql();
$this->view->assign('sqlTasks',json_encode($arr));
return $this->view->fetch();
}
}
执行SQL后端部分(PHP )
public function execSql($sql){
// sql语句校验
$arr = self::getSql();
$arr = array_values($arr);
if(!in_array($sql,$arr)){
return json_encode(['code'=>0,'msg'=>'非法sql']);
}
$exec = Db::execute($sql);
if($exec===false){
return json_encode(['code'=>0]);
}
return json_encode(['code'=>1]);
}
执行结果:
安全设置:
1、防火墙设置IP白名单,如我这里只允许公司内网部分IP可用;
2、后端检查SQL语句是否自己预设的语句,否则提示“非法语句”;