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

news2025/3/19 1:53:39

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

图1:

图2:

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

HTML 页面代码(代码99%用AI工具生成即可,1%根据实际微调)

<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'    // 实际业务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>

模板赋值(ThinkPHP5)

    // 获取SQL执行语句的方法
    private function getSql(){
        $name = 'miniform';
        $config = get_addon_config($name);
        $arr = isset($config['qudaosql']) ? $config['qudaosql'] : [];
        return $arr;
    }

    // 渠道更新页面访问方法
    public function aa(){
        if($this->request->isGet()){    // GET请求
            $arr = self::getSql();    // 获取SQL执行语句
            // dump($arr);
            $this->view->assign('sqlTasks',json_encode($arr));    // 模板赋值,输出json字符串
            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,'msg'=>'执行失败']);
        } 
        return json_encode(['code'=>1,'msg'=>'执行成功']);
    }

 执行结果:

安全设置:

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.coloradmin.cn/o/2317515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qt介绍图表 charts 一

qt chartsj基于Q的Graphics View框架&#xff0c;其核心组件是QChartView和QChart.QChartView是一个显示图表的独立部件&#xff0c;基类为QGraphicsView.QChar类管理图表的序列&#xff0c;图例和轴示意图。 绘制一个cos和sin曲线图&#xff0c;效果如下 实现代码 #include…

Transformer:GPT背后的造脑工程全解析(含手搓过程)

Transformer&#xff1a;GPT背后的"造脑工程"全解析&#xff08;含手搓过程&#xff09; Transformer 是人工智能领域的革命性架构&#xff0c;通过自注意力机制让模型像人类一样"全局理解"上下文关系。它摒弃传统循环结构&#xff0c;采用并行计算实现高…

S32K144入门笔记(十):TRGMUX的初始化

目录 1. 概述 2. 代码配置 1. 概述 书接上回&#xff0c;TRGMUX本质上是一个多路选择开关&#xff0c;根据用户手册中的描述&#xff0c;它可以实现多个输入的选择输出&#xff0c;本篇文章将验证如何通过配置工具来生成初始化配置代码。 2. 代码配置 笔者通过配置TRGMUX实现…

有了大模型为何还需要Agent智能体

一、什么是Agent&#xff1f; Agent&#xff08;智能体&#xff09; 是一种能感知环境、自主决策、执行动作的智能实体&#xff0c;当它与大语言模型&#xff08;如通义千问QWen、GPT&#xff09;结合时&#xff0c;形成一种**“增强型AI系统”**。其核心架构如下&#xff1a;…

DNS主从服务器

1.1环境准备 作用系统IP主机名web 服务器redhat9.5192.168.33.8webDNS 主服务器redhat9.5192.168.33.18dns1DNS 从服务器redhat9.5192.168.33.28dns2客户端redhat9.5192.168.33.7client 1.2修改主机名和IP地址 web服务器 [rootweb-8 ~]# hostnamectl hostname web [rootweb-8…

Flume详解——介绍、部署与使用

1. Flume 简介 Apache Flume 是一个专门用于高效地 收集、聚合、传输 大量日志数据的 分布式、可靠 的系统。它特别擅长将数据从各种数据源&#xff08;如日志文件、消息队列等&#xff09;传输到 HDFS、HBase、Kafka 等大数据存储系统。 特点&#xff1a; 可扩展&#xff1…

【Linux系列】文件压缩

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

微服务架构中10个常用的设计模式

​在当今的微服务架构中&#xff0c;常见的十种设计模式&#xff0c;分别是服务发现模式、API网关模式、断路器模式、边车模式、负载均衡模式、Saga事务模式、CQRS模式、分片模式、分布式日志跟踪模式、熔断与降级模式 。其中&#xff0c;服务发现模式十分关键&#xff0c;通过…

Vue3组件+leaflet,实现重叠marker的Popup切换显示

一、前言 GIS开发过程中&#xff0c;经常需要绘制marker&#xff0c;这些marker很大概率会有坐标相同导致的叠加问题&#xff0c;这种情况下会降低使用体验感。所以我们可以将叠加的marker的popup做一个分页效果&#xff0c;可以切换显示的marker。 二、技术要点 我们以leaf…

机器学习之距离度量方法

常见的距离度量方法及相关函数、图示如下: 1. 欧几里得距离(Euclidean Distance) 函数公式:对于两个 ( n ) 维向量 ( x = ( x 1 , x 2 , ⋯   ,

3.1 在VisionPro脚本中添加CogGraphicLabel

本案例需要实现如下功能&#xff1a; 1.加载toolBlock 2.加载图片&#xff0c; 3.运行Block 4.VisionPro中添加脚本显示数值。 见下图&#xff1a;详细代码&#xff08;C#以及visionPro&#xff09;见下面链接&#xff1a; https://download.csdn.net/download/qq_340474…

AI:Machine Learning Data Science

机器学习与数据科学 左侧 机器学习 Machine Learning 机器学习是一门多领域交叉学科&#xff0c;涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为&#xff0c;以获取新的知识或技能&#xff0c;重新组织已有的知…

软件需求分类、需求获取(高软46)

系列文章目录 软件需求分类&#xff0c;需求获取 文章目录 系列文章目录前言一、软件需求二、获取需求三、真题总结 前言 本节讲明软件需求分类、需求获取的相关知识。 一、软件需求 二、获取需求 三、真题 总结 就是高软笔记&#xff0c;大佬请略过&#xff01;

嵌入式Linux | 什么是 BootLoader、Linux 内核(kernel)、和文件系统?

01 什么是 BootLoader 呢&#xff1f; 它是个引导程序&#xff0c;也就是硬件复位以后第一个要执行的程序&#xff0c;它主要工作就是初始化操作系统运行的环境&#xff0c;比如说内存、定时器、缓冲器等&#xff0c;当这个工作做完以后&#xff0c;再把操作系统的代码加载…

函数(函数的概念、库函数、自定义函数、形参和实参、return语句、数组做函数参数、嵌套调用和链式访问、函数的声明和定义、static和extern)

一、函数的概念 •C语⾔中的函数&#xff1a;⼀个完成某项特定的任务的⼀⼩段代码 •函数又被翻译为子函数&#xff08;更准确&#xff09; •在C语⾔中我们⼀般会⻅到两类函数&#xff1a;库函数 ⾃定义函数 二、库函数 1 .标准库和头文件 •C语⾔的国际标准ANSIC规定了⼀…

ImGui 学习笔记(五) —— 字体文件加载问题

ImGui 加载字体文件的函数似乎存在编码问题&#xff0c;这一点可能跟源文件的编码也有关系&#xff0c;我目前源文件编码是 UTF-16。 当参数中包含中文字符时&#xff0c;ImGui 内部将字符转换为宽字符字符集时候&#xff0c;采用的 MultiByteToWideChar API 参数不太对&#…

OpenCV计算摄影学(20)非真实感渲染之增强图像的细节函数detailEnhance()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 此滤波器增强特定图像的细节。 cv::detailEnhance用于增强图像的细节&#xff0c;通过结合空间域和频率域的处理&#xff0c;提升图像中特定细节…

Android PC 要来了?Android 16 Beta3 出现 Enable desktop experience features 选项

在之前的 《Android 桌面窗口新功能推进》 我们就聊过&#xff0c;Google 就一直在努力改进 Android 的内置桌面模式&#xff0c;例如添加了适当的窗口标题、捕捉窗口的能力、悬停选项、窗口大小调整、最小化支持、app-to-web 等。 比如在搭载 Android 15 QPR 1 Beta 2 的 Pix…

Git常用操作之GitLab

Git常用操作之GitLab 小薛博客官网&#xff1a;小薛博客Git常用操作之GitLab官方地址 1、GitLab安装 https://gitlab.cn/install/ 1、Docker安装GitLab https://docs.gitlab.cn/jh/install/docker.html 1、设置卷位置 在设置其他所有内容之前&#xff0c;请配置一个新的…

Netty基础—NIO的使用简介

1.Buffer缓冲区 (1)Buffer缓冲区的作用 在NIO中&#xff0c;所有的数据都是通过使用Buffer缓冲区来处理的。如果要通过NIO&#xff0c;将数据写到文件和网络或从文件和网络中读取数据&#xff0c;那么就需要使用Buffer缓冲区来进行处理。 (2)Buffer缓冲区的4个核心概念 Buffer缓…