首页 > 数据库 >使用 Python和 SQLite 打造一个简单的数据库浏览器

使用 Python和 SQLite 打造一个简单的数据库浏览器

时间:2024-08-17 17:52:06浏览次数:14  
标签:SQLite 浏览器 Python text self cursor grid conn wx

在日常开发中,我们常常需要快速查看和操作SQLite数据库中的数据。虽然有许多现成的工具可以完成这一任务,但有时你可能想要一个更为简单、可定制的解决方案。在这篇博客中,我将带你一步步构建一个简单的SQLite数据库浏览器,它可以用来列出数据库中的表名、查看表的字段名、编写SQL语句并执行查询操作,并将结果展示在网格中。我们将使用 wxPython 来创建这个图形用户界面。
C:\pythoncode\new\sqliteanalysis.py

全部代码

import wx
import sqlite3
import wx.grid as gridlib

class SQLiteBrowser(wx.Frame):
    def __init__(self, *args, **kw):
        super(SQLiteBrowser, self).__init__(*args, **kw)

        self.InitUI()
        self.conn = None

    def InitUI(self):
        panel = wx.Panel(self)

        vbox = wx.BoxSizer(wx.VERTICAL)

        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        self.btn_open = wx.Button(panel, label="Open Database")
        self.btn_open.Bind(wx.EVT_BUTTON, self.OnOpen)
        hbox1.Add(self.btn_open, flag=wx.LEFT, border=10)
        vbox.Add(hbox1, flag=wx.EXPAND | wx.TOP | wx.BOTTOM, border=10)

        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        self.listbox1 = wx.ListBox(panel)
        self.listbox1.Bind(wx.EVT_LISTBOX, self.OnTableSelected)
        hbox2.Add(self.listbox1, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
        
        self.listbox2 = wx.ListBox(panel)
        self.listbox2.Bind(wx.EVT_LISTBOX, self.OnColumnSelected)
        hbox2.Add(self.listbox2, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)

        vbox.Add(hbox2, proportion=1, flag=wx.EXPAND)

        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        self.text_ctrl = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
        hbox3.Add(self.text_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)

        self.btn_exec = wx.Button(panel, label="Execute SQL")
        self.btn_exec.Bind(wx.EVT_BUTTON, self.OnExecuteSQL)
        hbox3.Add(self.btn_exec, flag=wx.LEFT, border=10)

        vbox.Add(hbox3, proportion=1, flag=wx.EXPAND)

        hbox4 = wx.BoxSizer(wx.HORIZONTAL)
        self.grid = gridlib.Grid(panel)
        self.grid.CreateGrid(5, 5)
        hbox4.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)

        vbox.Add(hbox4, proportion=3, flag=wx.EXPAND)

        panel.SetSizer(vbox)
        self.SetTitle('SQLite Browser')
        self.Centre()

    def OnOpen(self, event):
        with wx.FileDialog(self, "Open SQLite file", wildcard="SQLite files (*.db)|*.db",
                           style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return

            path = fileDialog.GetPath()
            self.conn = sqlite3.connect(path)
            self.LoadTables()

    def LoadTables(self):
        if self.conn:
            cursor = self.conn.cursor()
            cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
            tables = [row[0] for row in cursor.fetchall()]
            self.listbox1.Set(tables)

    def OnTableSelected(self, event):
        table_name = self.listbox1.GetStringSelection()
        if self.conn:
            cursor = self.conn.cursor()
            cursor.execute(f"PRAGMA table_info({table_name})")
            columns = [row[1] for row in cursor.fetchall()]
            self.listbox2.Set(columns)

    def OnColumnSelected(self, event):
        column_name = self.listbox2.GetStringSelection()
        current_text = self.text_ctrl.GetValue()
        if current_text:
            current_text += f", {column_name}"
        else:
            current_text = column_name
        self.text_ctrl.SetValue(current_text)

    def OnExecuteSQL(self, event):
        sql_query = self.text_ctrl.GetValue()
        if self.conn and sql_query.strip():
            cursor = self.conn.cursor()
            try:
                cursor.execute(sql_query)
                results = cursor.fetchall()
                self.DisplayResults(results)
            except sqlite3.Error as e:
                wx.MessageBox(f"An error occurred: {e}", "Error", wx.OK | wx.ICON_ERROR)

    def DisplayResults(self, results):
        if results:
            rows = len(results)
            cols = len(results[0])
            self.grid.ClearGrid()
            if rows > self.grid.GetNumberRows():
                self.grid.AppendRows(rows - self.grid.GetNumberRows())
            if cols > self.grid.GetNumberCols():
                self.grid.AppendCols(cols - self.grid.GetNumberCols())

            for i, row in enumerate(results):
                for j, value in enumerate(row):
                    self.grid.SetCellValue(i, j, str(value))

if __name__ == '__main__':
    app = wx.App(False)
    frame = SQLiteBrowser(None)
    frame.Show(True)
    app.MainLoop()

环境准备

在开始之前,你需要确保已安装以下Python库:

  1. wxPython:用于创建桌面应用的GUI库。
  2. sqlite3:Python自带的SQLite接口模块,用于与SQLite数据库进行交互。

如果你尚未安装 wxPython,可以通过以下命令安装:

pip install wxPython

项目目标

我们将创建一个简单的应用程序,其主要功能包括:

  1. 选择SQLite数据库文件:通过文件选择对话框选择一个SQLite数据库文件,并与之建立连接。
  2. 列出表名:在左侧列表框中列出所选数据库的所有表名。
  3. 列出字段名:在中间列表框中列出所选表的所有字段名。
  4. 构建SQL查询:点击字段名,自动将其追加到查询输入框中。
  5. 执行SQL查询:点击执行按钮,运行输入框中的SQL查询语句,并将结果展示在网格中。

代码实现

以下是完整的Python代码,它实现了上述所有功能:

import wx
import sqlite3
import wx.grid as gridlib

class SQLiteBrowser(wx.Frame):
    def __init__(self, *args, **kw):
        super(SQLiteBrowser, self).__init__(*args, **kw)

        self.InitUI()
        self.conn = None

    def InitUI(self):
        panel = wx.Panel(self)

        vbox = wx.BoxSizer(wx.VERTICAL)

        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        self.btn_open = wx.Button(panel, label="Open Database")
        self.btn_open.Bind(wx.EVT_BUTTON, self.OnOpen)
        hbox1.Add(self.btn_open, flag=wx.LEFT, border=10)
        vbox.Add(hbox1, flag=wx.EXPAND | wx.TOP | wx.BOTTOM, border=10)

        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        self.listbox1 = wx.ListBox(panel)
        self.listbox1.Bind(wx.EVT_LISTBOX, self.OnTableSelected)
        hbox2.Add(self.listbox1, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
        
        self.listbox2 = wx.ListBox(panel)
        self.listbox2.Bind(wx.EVT_LISTBOX, self.OnColumnSelected)
        hbox2.Add(self.listbox2, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)

        vbox.Add(hbox2, proportion=1, flag=wx.EXPAND)

        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        self.text_ctrl = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
        hbox3.Add(self.text_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)

        self.btn_exec = wx.Button(panel, label="Execute SQL")
        self.btn_exec.Bind(wx.EVT_BUTTON, self.OnExecuteSQL)
        hbox3.Add(self.btn_exec, flag=wx.LEFT, border=10)

        vbox.Add(hbox3, proportion=1, flag=wx.EXPAND)

        hbox4 = wx.BoxSizer(wx.HORIZONTAL)
        self.grid = gridlib.Grid(panel)
        self.grid.CreateGrid(5, 5)
        hbox4.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)

        vbox.Add(hbox4, proportion=3, flag=wx.EXPAND)

        panel.SetSizer(vbox)
        self.SetTitle('SQLite Browser')
        self.Centre()

    def OnOpen(self, event):
        with wx.FileDialog(self, "Open SQLite file", wildcard="SQLite files (*.db)|*.db",
                           style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return

            path = fileDialog.GetPath()
            self.conn = sqlite3.connect(path)
            self.LoadTables()

    def LoadTables(self):
        if self.conn:
            cursor = self.conn.cursor()
            cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
            tables = [row[0] for row in cursor.fetchall()]
            self.listbox1.Set(tables)

    def OnTableSelected(self, event):
        table_name = self.listbox1.GetStringSelection()
        if self.conn:
            cursor = self.conn.cursor()
            cursor.execute(f"PRAGMA table_info({table_name})")
            columns = [row[1] for row in cursor.fetchall()]
            self.listbox2.Set(columns)

    def OnColumnSelected(self, event):
        column_name = self.listbox2.GetStringSelection()
        current_text = self.text_ctrl.GetValue()
        if current_text:
            current_text += f", {column_name}"
        else:
            current_text = column_name
        self.text_ctrl.SetValue(current_text)

    def OnExecuteSQL(self, event):
        sql_query = self.text_ctrl.GetValue()
        if self.conn and sql_query.strip():
            cursor = self.conn.cursor()
            try:
                cursor.execute(sql_query)
                results = cursor.fetchall()
                self.DisplayResults(results)
            except sqlite3.Error as e:
                wx.MessageBox(f"An error occurred: {e}", "Error", wx.OK | wx.ICON_ERROR)

    def DisplayResults(self, results):
        if results:
            rows = len(results)
            cols = len(results[0])
            self.grid.ClearGrid()
            if rows > self.grid.GetNumberRows():
                self.grid.AppendRows(rows - self.grid.GetNumberRows())
            if cols > self.grid.GetNumberCols():
                self.grid.AppendCols(cols - self.grid.GetNumberCols())

            for i, row in enumerate(results):
                for j, value in enumerate(row):
                    self.grid.SetCellValue(i, j, str(value))

if __name__ == '__main__':
    app = wx.App(False)
    frame = SQLiteBrowser(None)
    frame.Show(True)
    app.MainLoop()

代码讲解

1. 打开数据库
def OnOpen(self, event):
    with wx.FileDialog(self, "Open SQLite file", wildcard="SQLite files (*.db)|*.db",
                       style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
        if fileDialog.ShowModal() == wx.ID_CANCEL:
            return

        path = fileDialog.GetPath()
        self.conn = sqlite3.connect(path)
        self.LoadTables()

这里,我们使用 wx.FileDialog 来打开文件选择对话框。用户选择一个SQLite数据库文件后,我们使用 sqlite3.connect() 方法建立数据库连接,并调用 LoadTables 方法列出所有表名。

2. 列出表名和字段名
def LoadTables(self):
    if self.conn:
        cursor = self.conn.cursor()
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
        tables = [row[0] for row in cursor.fetchall()]
        self.listbox1.Set(tables)

LoadTables 方法通过执行 SELECT name FROM sqlite_master WHERE type='table'; 查询来获取所有表名,并将其添加到左侧的 ListBox 中。

def OnTableSelected(self, event):
    table_name = self.listbox1.GetStringSelection()
    if self.conn:
        cursor = self.conn.cursor()
        cursor.execute(f"PRAGMA table_info({table_name})")
        columns = [row[1] for row in cursor.fetchall()]
        self.listbox2.Set(columns)

当用户点击某个表名时,OnTableSelected 方法会被调用,它使用 PRAGMA table_info(table_name) 查询该表的所有字段名,并将其显示在中间的 ListBox 中。

3. 构建和执行SQL查询
def OnColumnSelected(self, event):
    column_name = self.listbox2.GetStringSelection()
    current_text = self.text_ctrl.GetValue()
    if current_text:
        current_text += f", {column_name}"
    else:
        current_text = column_name
    self.text_ctrl.SetValue(current_text)

用户点击字段名时,OnColumnSelected 方法会将字段名追加到右侧的SQL输入框中,帮助用户快速构建SQL查询语句。

def OnExecuteSQL(self, event):
    sql_query = self.text_ctrl.GetValue()
    if self.conn and sql_query.strip():
        cursor = self.conn.cursor()
        try:
            cursor.execute(sql_query)
            results = cursor.fetchall()
            self.DisplayResults(results)
        except sqlite3.Error as e:
            wx.MessageBox(f"An error occurred: {e}", "Error", wx.OK | wx.ICON_ERROR)

点击“Execute SQL”按钮后,OnExecuteSQL 方法将执行输入框中的SQL语句,并调用 DisplayResults 方法将查询结果展示在网格里。

4. 显示查询结果
def DisplayResults(self, results):
    if results:
        rows = len(results)
        cols = len(results[0])
        self.grid.ClearGrid()
        if rows > self.grid.GetNumberRows():
            self.grid.AppendRows(rows - self.grid.GetNumberRows())
        if cols > self.grid.GetNumberCols():
            self.grid.AppendCols(cols - self.grid.GetNumberCols())

        for i, row in enumerate(results):
            for j, value in enumerate(row):
                self.grid.SetCellValue(i, j, str(value))

DisplayResults 方法会根据查询结果动态调整网格的大小,并将查询结果逐个填充到网格中。

结果如下

在这里插入图片描述

结语

通过上述代码,我们已经成功创建了一个简单的SQLite数据库浏览器,它可以帮助你快速查看和操作数据库中的数据。这个项目非常适合用作学习 wxPythonsqlite3 的入门项目,你可以在此基础上进一步扩展功能,如支持更多的SQL操作、增加数据编辑功能、或改进用户界面。

标签:SQLite,浏览器,Python,text,self,cursor,grid,conn,wx
From: https://blog.csdn.net/winniezhang/article/details/141256404

相关文章

  • 【Python】距离
    写了一个计算距离的脚本,常见距离基本都有。其中测地距离需要依赖曲面,Hausdorff距离之前有实现,而Wasserstei距离可以用sinkhorn方法求解。代码如下:importnumpyasnpdefEuclidean(a,b):returnnp.sqrt(np.sum((a-b)*(a-b)))defManhattan(a,b):returnnp.sum(n......
  • Python系列(5)- 命令行应用 (Command Line Application)
     使用Windows、iOS、Android、HarmonyOS等操作系统的设备,用户与这些设备主要通过图形用户界面(GUI)来交互,比如:鼠标、触屏等。一般用户很少使用这些系统的命令行界面(CLI),在Windows下是通过命令提示符(Cmd)窗口来实现CLI交互,其它系统通过终端(Terminal)窗口。 命令行界面(CLI......
  • Python导入包时提示“attempted relative import beyond top-level package”的解决办
    一篇很好的文章:python跨目录导包失败python不同路径导入包错误 在涉及到相对导入时,package所对应的文件夹必须正确的被python解释器视作package,而不是普通文件夹。否则由于不被视作package,无法利用package之间的嵌套关系实现python中包的相对导入。文件夹被python解释器视作......
  • Python入门之Lesson1:出发!
    目录前言一、Python简介二、环境搭建1.Python安装2.Pycharm安装三.运行总结前言本章会带领同学们了解和入门python。一、Python简介Python是一种高级编程语言,具有简洁明了的语法和丰富的库,非常适合初学者学习。Python的设计注重代码的可读性和简洁性,其语法类似......
  • 【Python系列】命令 • 合集
    文件传输Python2//将http:///FileName写入Path中python2-c"importurllib2;u=urllib2.urlopen('http:///FileName');f=open('Path','w');f.write(u.read());f.close()"//Python3//将http:///FileName写入Path中,这里要注意decode()中......
  • python安装
    下载安装python到官网下载最新版这里是3.12.5版本https://www.python.org/downloads/在安装Python时,系统环境变量的长度超出了操作系统所允许的限制,如下所示。环境变量通常用于存储系统或应用程序的配置信息,如路径等。如果这些变量的总长度超出了操作系统或文件系统所......
  • 学习Python必备的8个网站,没有就举步维艰!
      学习Python时,选择合适的学习资源对于提升技能至关重要。以下是推荐的8个学习Python的必去网站及其地址:Python官方网站(Python.org)地址:WelcometoPython.org特点:官方文档是学习Python最权威的资料,涵盖了从基础语法到高级特性的全面指南。此外,网站还提供Python的下载和安......
  • Python编程常用英文单词大全!收藏别忘了!
      Python编程中常用的英文单词非常丰富,这些单词涵盖了编程的各个方面,包括基础概念、数据类型、控制结构、函数与模块、类与对象、异常处理等。以下是一些常用的英文单词及其简要说明:1.基础概念Variable(变量):用来存储和表示数据的容器。Function(函数):一段可重复使用的代码......
  • Python的71个内置函数,小白都能学会!
    Python是一种高级编程语言,具有很多强大的特性,其中之一就是内置函数。Python内置函数是指在Python解释器中可以直接使用的函数,无需导入任何模块或库。Python内置函数包含了很多常用的函数,可以快速地完成各种操作。本文将介绍Python内置函数的用法帮助初学者更好地掌握Python编程......
  • OpenCV图像处理——轮廓的面积与弧长计算(C++/Python)
    概述轮廓面积与轮廓周长是图像分析中的两项核心统计特征,它们为理解和量化图像中的形状提供了基础。轮廓面积:这代表了轮廓所界定区域的像素数量,是衡量区域大小的直接指标。面积的计算结果以像素平方为单位,为我们提供了一个量化的尺度来比较不同物体的相对大小。轮廓周长......