pyqt SQL Server 数据库查询-优化2

news2025/5/13 6:35:40

1、增加导出数据功能
2、增加删除表里数据功能
在这里插入图片描述

import sys
import pyodbc
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QLineEdit, QPushButton, \
    QTableWidget, QTableWidgetItem, QLabel, QMessageBox
from PyQt6.QtGui import QFont
from PyQt6.QtCore import Qt
import pandas as pd
from datetime import datetime


class DatabaseQueryApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.connect_to_database()

    def initUI(self):
        # 设置窗口字体
        font = QFont()
        font.setPointSize(18)
        self.setFont(font)

        # 创建布局
        main_layout = QVBoxLayout()

        # 表列表、字段列表和输入框布局
        list_input_layout = QHBoxLayout()

        # 表列表部分
        table_label = QLabel("表:")
        list_input_layout.addWidget(table_label)
        self.table_list = QListWidget()
        # 调整显示表的控件大小
        self.table_list.setFixedHeight(100)
        # 设置 QListWidget 选中项整行变蓝色
        self.table_list.setStyleSheet("QListWidget::item:selected { background-color: blue; color: white; }")
        self.table_list.itemClicked.connect(self.show_table_columns)
        list_input_layout.addWidget(self.table_list)

        # 字段列表部分
        column_label = QLabel("字段:")
        list_input_layout.addWidget(column_label)
        self.column_list = QListWidget()
        self.column_list.setFixedHeight(100)
        self.column_list.setStyleSheet("QListWidget::item:selected { background-color: blue; color: white; }")
        list_input_layout.addWidget(self.column_list)

        # 查询输入部分
        value_label = QLabel("查询值:")
        list_input_layout.addWidget(value_label)
        self.value_input = QLineEdit()
        self.query_button = QPushButton('查询')

        # 获取当前按钮的大小
        current_width = self.query_button.sizeHint().width()
        current_height = self.query_button.sizeHint().height()
        # 设置按钮大小为原来的两倍
        button_size = (current_width * 2, current_height * 2)
        self.query_button.setFixedSize(*button_size)
        self.query_button.clicked.connect(self.execute_query)
        list_input_layout.addWidget(self.value_input)
        list_input_layout.addWidget(self.query_button)

        # 导出按钮
        self.export_button = QPushButton('导出')
        self.export_button.setFixedSize(*button_size)
        self.export_button.clicked.connect(self.export_table)
        list_input_layout.addWidget(self.export_button)

        # 清空按钮
        self.clear_button = QPushButton('清空')
        self.clear_button.setFixedSize(*button_size)
        self.clear_button.clicked.connect(self.clear_table)
        list_input_layout.addWidget(self.clear_button)

        main_layout.addLayout(list_input_layout)

        # 自定义查询输入部分
        custom_query_layout = QHBoxLayout()
        custom_query_label = QLabel("自定义查询:")
        custom_query_layout.addWidget(custom_query_label)
        self.custom_query_input = QLineEdit()
        self.custom_execute_button = QPushButton('执行')
        self.custom_execute_button.setFixedSize(*button_size)
        self.custom_execute_button.clicked.connect(self.execute_custom_query)
        custom_query_layout.addWidget(self.custom_query_input)
        custom_query_layout.addWidget(self.custom_execute_button)

        main_layout.addLayout(custom_query_layout)

        # 查询结果表格部分
        result_label = QLabel("查询结果:")
        main_layout.addWidget(result_label)
        self.result_table = QTableWidget()
        self.result_table.setColumnCount(0)
        self.result_table.setRowCount(0)
        # 设置 QTableWidget 选择行为为整行选择
        self.result_table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        # 设置 QTableWidget 选中行整行变蓝色
        self.result_table.setStyleSheet("QTableWidget::item:selected { background-color: blue; color: white; }")

        main_layout.addWidget(self.result_table)

        self.setLayout(main_layout)
        self.setWindowTitle('数据库查询工具')
        self.setGeometry(300, 300, 1200, 900)
        self.setStyleSheet("""
            QWidget {
                background-color: #f0f0f0;
            }
            QLabel {
                font-weight: bold;
            }
            QPushButton {
                background-color: #4CAF50;
                color: white;
                padding: 10px 20px;
                border: none;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 5px;
            }
        """)
        self.show()

    def connect_to_database(self):
        try:
            # 使用指定的连接字符串
            connection_string = 'DRIVER={SQL Server};SERVER=LEGENDLI;DATABASE=testbase;UID=sa;PWD=1'
            self.conn = pyodbc.connect(connection_string)
            cursor = self.conn.cursor()
            cursor.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")
            tables = cursor.fetchall()
            for table in tables:
                self.table_list.addItem(table[0])
        except Exception as e:
            self.show_error_message(f"数据库连接错误: {e}")

    def show_table_columns(self, item):
        table_name = item.text()
        try:
            cursor = self.conn.cursor()
            cursor.execute(f"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{table_name}'")
            columns = cursor.fetchall()
            self.column_list.clear()
            for column in columns:
                self.column_list.addItem(column[0])
        except Exception as e:
            self.show_error_message(f"获取字段信息错误: {e}")

    def execute_query(self):
        selected_table_items = self.table_list.selectedItems()
        selected_column_items = self.column_list.selectedItems()
        if not selected_table_items:
            self.show_error_message("请选择一个表。")
            return

        table_name = selected_table_items[0].text()
        value = self.value_input.text()

        if not selected_column_items or not value:
            query = f"SELECT * FROM {table_name}"
        else:
            column_name = selected_column_items[0].text()
            query = f"SELECT * FROM {table_name} WHERE {column_name} = '{value}'"

        try:
            cursor = self.conn.cursor()
            cursor.execute(query)
            results = cursor.fetchall()
            headers = [description[0] for description in cursor.description]

            self.result_table.setColumnCount(len(headers))
            self.result_table.setRowCount(len(results))
            self.result_table.setHorizontalHeaderLabels(headers)

            for row_index, row_data in enumerate(results):
                for col_index, col_data in enumerate(row_data):
                    item = QTableWidgetItem(str(col_data))
                    self.result_table.setItem(row_index, col_index, item)

        except Exception as e:
            self.show_error_message(f"查询错误: {e}")

    def execute_custom_query(self):
        query = self.custom_query_input.text().strip().lower()
        # 检查是否包含危险指令
        if "drop" in query or "DROP" in query \
                or 'update' in query or 'UPDATE' in query \
                or 'delete' in query or 'DELETE' in query \
                or 'truncate' in query or 'TRUNCATE' in query:
            self.show_error_message("不允许执行删除表或删除数据库的指令。")
            return

        try:
            cursor = self.conn.cursor()
            cursor.execute(query)
            results = cursor.fetchall()
            headers = [description[0] for description in cursor.description]

            self.result_table.setColumnCount(len(headers))
            self.result_table.setRowCount(len(results))
            self.result_table.setHorizontalHeaderLabels(headers)

            for row_index, row_data in enumerate(results):
                for col_index, col_data in enumerate(row_data):
                    item = QTableWidgetItem(str(col_data))
                    self.result_table.setItem(row_index, col_index, item)

        except Exception as e:
            self.show_error_message(f"查询错误: {e}")

    def export_table(self):
        selected_table_items = self.table_list.selectedItems()
        if not selected_table_items:
            self.show_error_message("请选择一个表。")
            return

        table_name = selected_table_items[0].text()
        try:
            # 导出数据到 Excel
            query = f"SELECT * FROM {table_name}"
            df = pd.read_sql(query, self.conn)
            now = datetime.now().strftime("%Y%m%d%H%M%S")
            file_name = f"{table_name}_{now}.xlsx"
            df.to_excel(file_name, index=False)
            self.show_success_message(f"数据已导出到 {file_name}。")
        except Exception as e:
            self.show_error_message(f"导出数据时出错: {e}")

    def clear_table(self):
        selected_table_items = self.table_list.selectedItems()
        if not selected_table_items:
            self.show_error_message("请选择一个表。")
            return

        table_name = selected_table_items[0].text()
        reply = QMessageBox.question(self, '确认', f'是否真的要清空表 {table_name} 的数据?',
                                     QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                                     QMessageBox.StandardButton.No)
        if reply == QMessageBox.StandardButton.Yes:
            try:
                cursor = self.conn.cursor()
                cursor.execute(f"DELETE FROM {table_name}")
                self.conn.commit()
                self.show_success_message(f"表 {table_name} 的数据已清空。")
            except Exception as e:
                self.show_error_message(f"清空表数据时出错: {e}")

    def show_error_message(self, message):
        msg_box = QMessageBox()
        msg_box.setIcon(QMessageBox.Icon.Critical)
        msg_box.setText(message)
        msg_box.setWindowTitle("错误提示")
        msg_box.exec()

    def show_success_message(self, message):
        msg_box = QMessageBox()
        msg_box.setIcon(QMessageBox.Icon.Information)
        msg_box.setText(message)
        msg_box.setWindowTitle("成功提示")
        msg_box.exec()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = DatabaseQueryApp()
    sys.exit(app.exec())

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

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

相关文章

Hyperlane:高性能 Rust HTTP 服务器框架评测

Hyperlane:高性能 Rust HTTP 服务器框架评测 在当今快速发展的互联网时代,选择一个高效、可靠的 HTTP 服务器框架对于开发者来说至关重要。最近,我在评估各种服务器框架性能时,发现了一个名为 Hyperlane 的 Rust HTTP 服务器库&a…

Laravel 中使用 JWT 作用户登录,身份认证

什么是JWT: JWT 全名 JSON Web Token,是一种开放标准 (RFC 7519)。 用于在网络应用环境间安全地传输信息作为 JSON 对象。 它是一种轻量级的认证和授权机制,特别适合分布式系统的身份验证。 核心特点 紧凑格式:体积小&#x…

VBA中类的解读及应用第二十二讲:利用类判断任意单元格的类型-5

《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程,目前已经是第一版修订了。这套教程定位于最高级,是学完初级,中级后的教程。 类,是非常抽象的,更具研究的价值。随着我们学习、应用VBA的深入&#xff0…

STM32F103_LL库+寄存器学习笔记13 - 梳理外设CAN与如何发送CAN报文(串行发送)

导言 CAN总线因其高速稳定的数据传输与卓越抗干扰性能,在汽车、机器人及工业自动化中被广泛应用。它采用分布式网络结构,实现多节点间实时通信,确保各控制模块精准协同。在汽车领域,CAN总线连接发动机、制动、车身系统&#xff0c…

Linux系统调用编程

文章目录 一、进程和线程二、Linux的虚拟内存管理和stm32的真实物理内存**Linux虚拟内存管理**STM32物理内存映射2. 主要区别 三、Linux系统调用函数 fork()、wait()、exec()1. fork():创建子进程2. wait():等待子进程状态改变3. exec():替换…

游戏引擎学习第203天

回顾当前情况 在这里我将直播完成整个游戏的制作。我们现在面临一些技术上的困难,确实如此。我的笔记本电脑的电源接口坏了,所以我不得不准备了这台备用笔记本,希望它能够正常工作。我所以希望一切都还好,尽管我不完全确定是否一…

深度学习数据集划分比例多少合适

在机器学习和深度学习中,测试集的划分比例需要根据数据量、任务类型和领域需求灵活调整。 1. 常规划分比例 通用场景 训练集 : 验证集 : 测试集 60% : 20% : 20% 适用于大多数中等规模数据集(如数万到数十万样本),平衡了训练数…

CExercise_1_5 水仙花数

题目: 经典循环案例:请求出所有的水仙花数,并统计总共有几个。 所谓的水仙花数是指一个三位数,其各位数字的立方和等于该数本身。 举例:153就是一个水仙花数,153 1 * 1 * 1 5 * 5 * 5 3 * 3 * 3 1 125…

哈密尔顿路径(Hamiltonian Path)及相关算法题目

哈密尔顿路径要求访问图中每个顶点恰好一次,通常用于解决旅行商问题(TSP)或状态压缩DP问题。 哈密尔顿路径(Hamiltonian Path)是指在一个图中经过每个顶点恰好一次的路径。如果这条路径的起点和终点相同(即…

MINIQMT学习课程Day10

开始获取股票数据课程的学习: 获取qmt账号的持仓情况后,我们进入下一步,如何获得当前账号的委托状况 还是之前的步骤,打开qmt,选择独立交易, 之后使用pycharm,编写py文件 导入包&#xff1a…

JAVA实战开源项目:智慧图书管理系统(Vue+SpringBoot) 附源码

本文项目编号 T 152 ,文末自助获取源码 \color{red}{T152,文末自助获取源码} T152,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

Linux 系统管理综合实训 —— 基于 NAT 模式的多 IP 配置、Nginx 服务部署及存储管理

1. 虚拟机网络配置:NAT模式与多IP地址设置 将你的虚拟机的网卡模式设置为nat模式,给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 设置静态IP [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 192.168.2.100/2…

如何在windows 环境、且没有显卡的情况下用python跑通从ModelScope下载的大模型的调用

文章目录 背景介绍源代码:安装调试过程1.设置第三方镜像源2.预先安装:3.在python中创建代码:4.最终修改程序,将device_map从“cuda”改成“auto”,大模型调用1.5B(1___5B)的5.最终跑出结果解释:示例&#x…

黑马点评redis改 part 1

本篇将主要阐述短信登录的相关知识,感谢黑马程序员开源,感谢提供初始源文件(给到的是实战第7集开始的代码)【Redis实战篇】黑马点评学习笔记(16万字超详细、Redis实战项目学习必看、欢迎点赞⭐收藏)-CSDN博…

【Ragflow】11. 文件解析流程分析/批量解析实现

概述 本文继续对ragflow文档解析部分进行分析,并通过脚本的方式实现对文件的批量上传解析。 文件解析流程 文件解析的请求处理流程大致如下: 1.前端上传文件,通过v1/document/run接口,发起文件解析请求 2.后端api\apps\docum…

第三期:深入理解 Spring Web MVC [特殊字符](数据传参+ 特殊字符处理 + 编码问题解析)

✨前言:传参和状态管理,看似简单其实门道不少 在 Web 开发中,前端和后端最核心的交流方式就是“传参”,而“传参”除了涉及如何写代码获取参数,还藏着很多开发者容易忽略的细节: 为什么 URL 带了中文&…

Everything 安装教程与使用教程(附安装包)

文章目录 前言一、Everything 介绍二、Everything 安装教程1.Everything 安装包下载2.选择安装文件3.选择安装语言4.接受许可协议5.选择安装位置6.配置安装选项7.完成安装 三、Everything 使用教程1.启动软件2.简单关键词搜索3.按类型搜索 前言 在日常使用电脑时,随…

SQL语句(三)—— DQL

目录 基本语法 一、基础查询 1、查询多个字段 2、字段设置别名 3、去除重复记录 4、示例代码 二、条件查询 1、语法 2、条件列表常用的运算符 3、示例代码 三、分组查询 (一)聚合函数 1、介绍 2、常见的聚合函数 3、语法 4、示例代码 &…