记录一个SQL自动执行的html页面

在实际工作场景中,需要运用到大量SQL语句更新业务逻辑,对程序员本身,写好的sql语句执行没有多大问题(图1),但是对于普通用户来说还是有操作难度的。因此我们需要构建一个HTML页面(图2),并结合JavaScript来发送请求到服务器端执行SQL语句。这里需要注意的是,在实际应用中直接通过前端请求执行SQL语句存在严重的安全隐患(如SQL注入攻击),通常的做法是在服务端进行严格的验证和处理。

图1:

图2:

以下是我的一个实际案例:

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">&times;</span><p>这是一个模态框的内容。</p></div>
</div><script>const url = 'xxx.com/api'    // 实际业务apiconst 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>

模板赋值(ThinkPHP5)

    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语句是否自己预设的语句,否则提示“非法语句”;

补充一段上述代码中涉及到的SQL语句,供参考:

 

array(18) {["更新表单id=18"] => string(77) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui SET project_id=18;"["更正original_data"] => string(183) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui         SET original_data=REPLACE(original_data,'addfromcode-zh','addfromcode_zh')         WHERE addfromcode='fromyudengji';"["补充addfromcode"] => string(472) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a INNER JOIN (         SELECT id,REPLACE(adfc,'\"','') as adfc,REPLACE(ly,'\"','') as ly FROM (         SELECT id,original_data,JSON_EXTRACT(original_data, '$.addfromcode_zh') as adfc 				,JSON_EXTRACT(original_data, '$.ly') as ly         FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui         WHERE addfromcode='fromyudengji' 				) a         ) b ON a.id=b.id         SET a.addfromcode=b.adfc,a.ly=b.ly "["归零"] => string(91) "UPDATE fa_miniform_qudao              SET items=0,items2=0             WHERE project_id=18;"["匹配得上的统计"] => string(281) "UPDATE fa_miniform_qudao a INNER JOIN (             SELECT addfromcode,count(*) as jls FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui             GROUP BY addfromcode) b             ON a.qdcode=b.addfromcode              SET a.items=b.jls             WHERE project_id=18;"["匹配得上的统计2"] => string(193) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a INNER JOIN fa_miniform_qudao b             ON a.addfromcode=b.qdcode              SET a.qdid=b.id             WHERE b.project_id=18;"["统计英文登记"] => string(323) "UPDATE fa_miniform_qudao a SET a.items=( SELECT SUM(jls) FROM ( SELECT addfromcode,count(*) as jls FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a LEFT JOIN fa_miniform_qudao b ON a.addfromcode=b.qdcode WHERE b.qdcode is NULL AND lang='en' AND a.project_id=18 GROUP BY addfromcode ) aa ) WHERE qdcode='sjyyclmj';"["统计英文登记2"] => string(135) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a INNER JOIN fa_miniform_qudao b  ON a.addfromcode=b.qdcode SET a.qdid=b.id;"["统计英文登记3"] => string(469) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a              SET a.qdid=(SELECT id FROM fa_miniform_qudao WHERE qdcode='sjyyclmj' AND project_id=18)             WHERE lang='en' AND addfromcode in (SELECT addfromcode from (SELECT addfromcode,count(*) as jls FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a LEFT JOIN fa_miniform_qudao b ON a.addfromcode=b.qdcode WHERE b.qdcode is NULL AND lang='en' AND a.project_id=18 GROUP BY addfromcode) aa );"["更新好友邀请1"] => string(307) "UPDATE fa_miniform_qudao a INNER JOIN (             SELECT 'shujuyunyinghaoyoufenxiang' as addfromcode,count(*) as jls FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui WHERE ly='fs'             ) b             ON a.qdcode=b.addfromcode              SET a.items=b.jls             WHERE project_id=18;"["更新好友邀请2"] => string(206) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a              SET a.qdid=(SELECT id FROM fa_miniform_qudao WHERE qdcode='shujuyunyinghaoyoufenxiang' AND project_id=18)             WHERE ly='fs';"["3-7号馆1"] => string(307) "UPDATE fa_miniform_qudao a INNER JOIN (             SELECT '1711zs' as addfromcode,count(*) as jls FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui              WHERE (ly LIKE 'zs')             ) b             ON a.qdcode=b.addfromcode              SET a.items=b.jls             WHERE project_id=18;"["3-7号馆2"] => string(207) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a              SET a.qdid=(SELECT id FROM fa_miniform_qudao WHERE qdcode='1711zs' AND project_id=18)             WHERE (addfromcode LIKE '1711zs%');"["8-9号馆1"] => string(329) "UPDATE fa_miniform_qudao a INNER JOIN (             SELECT 'yingyunpinpaihaibaoliebian' as addfromcode,count(*) as jls FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui              WHERE (ly LIKE 'zshb')             ) b             ON a.qdcode=b.addfromcode              SET a.items=b.jls             WHERE project_id=18;"["8-9号馆2"] => string(215) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a              SET a.qdid=(SELECT id FROM fa_miniform_qudao WHERE qdcode='yingyunpinpaihaibaoliebian' AND project_id=18)             WHERE (ly LIKE 'zshb');"["导入闸机数据后,更新观众登记表"] => string(195) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a INNER JOIN ( SELECT qrcode,count(*) as jls FROM fa_miniform_di52jiezhajishuju GROUP BY qrcode) b ON a.qrcode=b.qrcode SET a.dds=b.jls;"["更新渠道邀约数"] => string(200) "UPDATE fa_miniform_qudao a INNER JOIN ( SELECT qdid,count(*) as jls FROM fa_miniform_di53jieguojimingjiajudongguanzhanlanhui WHERE qdid>0 AND dds>0 GROUP BY qdid ) b ON a.id=b.qdid SET a.items2=b.jls;"["补充en数据ly为空"] => string(179) "UPDATE fa_miniform_di53jieguojimingjiajudongguanzhanlanhui a INNER JOIN fa_miniform_qudao b ON a.addfromcode=b.qdcode SET a.ly='qd' WHERE (a.ly IS NULL OR a.ly='') AND a.lang='en'"
}

在fa后台,用fieldset组件简单做一个SQL配置,虽然不太好看但能用就行,如下图所示:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/32811.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac安装mysql之后报错zsh: command not found: mysql !

在Mac上安装MySQL后&#xff0c;如果终端中找不到mysql命令&#xff0c;通常是 因为MySQL的命令行工具&#xff08;如mysql客户端&#xff09;没有被正确地添加到你的环境变量中。 检查 MySQL 是否已安装 ps -ef|grep mysql查看到路径在 /usr/local/mysql/bin 查看 .bash_pro…

socket编程与TCP协议

如果你想和远方的朋友通电话&#xff0c;但是&#xff0c;没有办法直接把自己的声音放在电线上变成电流信号&#xff0c;你需要使用电话机拿起听筒拨号&#xff0c;而这个电话就是Socket&#xff0c;它让你简单方便地完成电流通话&#xff0c;从我们编程的角度来看&#xff0c;…

css基本功

为什么 ::first-letter 是伪元素&#xff1f; ::first-letter 的作用是选择并样式化元素的第一个字母&#xff0c;它创建了一个虚拟的元素来包裹这个字母&#xff0c;因此属于伪元素。 grid布局 案例一 <!DOCTYPE html> <html lang"zh-CN"><head&…

环境配置 | 5分钟极简Git入门:从零上手版本控制

你是否刚接触Git&#xff1f;别担心&#xff01;这篇指南将用最简单的步骤带你掌握Git核心操作&#xff0c;快速开启版本控制之旅&#xff01;✨ 1.git在win10上的下载安装 1.1.下载git 打开官方网站 Git - Downloadshttps://git-scm.com/downloads ​ ​​ 1.2.git安装 …

软件工程概述、软件过程模型、逆向工程(高软45)

系列文章目录 软件工程概述、软件过程模型、逆向工程。 文章目录 系列文章目录前言一、软件工程概述二、能力成熟度模型1.能力成熟度模型CMM2.能力成熟度模型集成CMMI 三、软件过程模型1.瀑布模型SDLC2.原型化模型3.螺旋模型4.增量模型5.喷泉模型6.敏捷模型7.统一过程模型RUP 四…

接口自动化入门 —— Jmeter实现在接口工具中关联接口处理方案

1. JMeter 接口关联处理的核心概念 接口关联是指在多个接口请求之间共享数据&#xff0c;例如将一个接口的返回值作为另一个接口的输入参数。常见的场景包括&#xff1a; 使用登录接口返回的 Token 作为后续接口的认证信息。 将一个接口返回的 ID 作为另一个接口的请求参数。…

websocket学习手册及python实现简单的聊天室

概述 WebSocket 是一种网络通信协议&#xff0c;允许在单个 TCP 连接上进行全双工通信。它最核心的优势就在于实现了持久连接&#xff0c;实现了实时的数据传输。HTTP 协议有一个很大的缺点&#xff0c;通信只能由客户端发起&#xff0c;服务器返回响应后连接就会关闭&#xf…

小白学习:提示工程(什么是prompt)

课程链接 https://www.bilibili.com/video/BV1PX9iYQEry/?spm_id_from333.337.search-card.all.click 一 什么是提示工程 【提示工程】也叫【指令工程】 prompt就是给大模型发的指令&#xff0c;如“给我讲个笑话” 懂得提示工程原理会带来什么优势 懂得原理 为什么有的指…

ROS实践(五)机器人自动导航(robot_navigation)

目录 一、知识点 1. 定位 2. 路径规划 (1)全局路径规划 (2)局部路径规划 3. 避障 二、常用工具和传感器 三、相关功能包 1. move_base(决策规划) 2. amcl(定位) 3. costmap_2d(代价地图) 4. global_planner(全局规划器) 5. local_planner(局部规划器…

分治算法区

分治 一.分治二.经典应用案例三.快速排序&#xff08;1&#xff09;颜色分类&#xff08;2&#xff09;排序数组&#xff08;3&#xff09;数组中第K个最大的元素 四.归并排序1.排序数组2.交易逆序对总数3.计算右侧小于当前元素的个数4.翻转对 一.分治 分治算法是一种通过将复…

设计模式C++

针对一些经典的常见的场景, 给定了一些对应的解决方案&#xff0c;这个就叫设计模式。 设计模式的作用&#xff1a;使代码的可重用性高&#xff0c;可读性强&#xff0c;灵活性好&#xff0c;可维护性强。 设计原则&#xff1a; 单一职责原则&#xff1a;一个类只做一方面的…

零成本搭建Calibre个人数字图书馆支持EPUB MOBI格式远程直读

文章目录 前言1.网络书库软件下载安装2.网络书库服务器设置3.内网穿透工具设置4.公网使用kindle访问内网私人书库 前言 嘿&#xff0c;各位书虫们&#xff01;今天要给大家安利一个超级炫酷的技能——如何在本地Windows电脑上搭建自己的私人云端书库。亚马逊服务停了&#xff…

Qt 数据库操作(Sqlite)

数据库简介 关于数据库的基础知识这里就不做介绍了&#xff0c;相关博客可以查看&#xff1a; SQL基础知识 数据库学霸笔记 上面博客都写的比较详细&#xff0c;本文主要介绍如何使用Qt进行数据库相关操作&#xff0c;数据库分为关系型数据库和非关系型数据&#xff0c;关系…

hackme靶机详细攻略

扫描ip arp-scan -l 访问网站后&#xff0c;点击sign up now注册 注册后登录 点击search显示全部数据 尝试sql注入 确认闭合方式 OSINTand 12# 确定列数 OSINT order by 3# 显示正常 OSINT order by 4# 显示异常 确认回显位置 -1 union select 1,2,3# 确认数据库名 -…

Tweak Power:全方位电脑系统优化的高效工具

在日常使用电脑时&#xff0c;系统性能的下降、垃圾文件的堆积以及硬盘的老化等问题常常困扰着用户。为了提升电脑性能、优化系统运行&#xff0c;许多人会选择系统优化工具。然而&#xff0c;国内一些系统优化软件常常因为广告过多或功能冗杂而让人望而却步。此时&#xff0c;…

element-plus中Autocomplete自动补全输入框组件的使用

目录 1.基本使用 ①从官网赋值如下代码 ②查看运行效果 ③代码解读 2.调用后端接口&#xff0c;动态获取建议数据 结语 1.基本使用 ①从官网赋值如下代码 <template> <div><!-- 自动补全输入框 --><el-autocompletev-model"state":fetc…

SSM基础专项复习6——Spring框架AOP(3)

系列文章 1、SSM基础专项复习1——SSM项目整合-CSDN博客 2、SSM基础专项复习2——Spring 框架&#xff08;1&#xff09;-CSDN博客 3、SSM基础专项复习3——Spring框架&#xff08;2&#xff09;-CSDN博客 4、SSM基础专项复习4——Maven项目管理工具&#xff08;1&#xff…

MATLAB基于ResNet18的交通标志识别系统

1. 数据准备 数据集&#xff1a;该数据集包含了大量标注好的交通标志图片&#xff0c;每类标志都有不同的样本。数据预处理&#xff1a;图像需要进行一些基本的预处理&#xff0c;如调整大小、归一化等&#xff0c;以适应ResNet18的输入要求。 2. 网络设计 使用MATLAB自带的…

【2步解决】phpstudy开机自启(自动启动phpstudy、mysql、nignx或apache、自动打开网址)

重启执行最终效果图&#xff1a; 一、场景 线下部署&#xff0c;需要开启自动动&#xff0c;并打开网址http://localhost/。 二、操作步骤 ①、新建start.txt&#xff0c;并修改为start.bat&#xff0c;使用记事本编辑&#xff0c;粘贴上方代码如下&#xff1a; echo off:…

C++20 `<bit>` 中的整数 2 的幂运算和 `std::bit_cast`:由浅入深的探索

文章目录 引言 1\. 整数 2 的幂运算1.1 检测是否为 2 的幂&#xff1a;std::has_single_bit1.2 计算不小于 x 的最小 2 的幂&#xff1a;std::bit_ceil1.3 计算不大于 x 的最大 2 的幂&#xff1a;std::bit_floor 2\. std::bit_cast2.1 基本用法2.2 实用场景&#xff1a;字节序…