python连接数据库——create_engine和conn.cursor

本文介绍两种使用Python操作PostgreSQL数据库的方法:一是通过sqlalchemy库,二是利用psycopg2库。这两种方式均可实现数据库的查询、更新及数据表的创建等操作。
python操作数据库的方法:
一种是导入sqlalchemy包另一种是导入psycopg2包。

具体用法如下(此处以postgre数据库举例)
第一种:

# 导入包
from sqlalchemy import create_engine
import pandas as pd
from string import Template
# 初始化引擎
engine = create_engine('postgresql+psycopg2://' + pg_username + ':' + pg_password + '@' + pg_host + ':' + str(
    pg_port) + '/' + pg_database)
query_sql = """
      select * from $arg1
      """
query_sql = Template(query_sql) # template方法

df = pd.read_sql_query(query_sql .substitute(arg1=tablename),engine) # 配合pandas的方法读取数据库值

# 配合pandas的to_sql方法使用十分方便(dataframe对象直接入库)
df.to_sql(table, engine, if_exists='replace', index=False) #覆盖入库
df.to_sql(table, engine, if_exists='append', index=False)  #增量入库

第二种方法,与jdbc使用极为相似
# 导入包
import psycopg2
# 初始化
conn = psycopg2.connect(database = database, user = username, password = passwd, host = host, port = port)
cursor = conn.cursor()
# 执行sql
cursor.execute(sql, values)  # 与jdbc的prepareStatement极为类似,执行的是一个具体的sql语句。

cursor也能调存储过程,并且获取返回值。
import sys import pymysql import os from PyQt5.QtWidgets import ( QWidget, QApplication, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, QPushButton, QCheckBox, QScrollArea, QFileDialog, QMessageBox, QRadioButton ) from PyQt5.QtCore import Qt import traceback import re class DatabaseExporter(QWidget): def __init__(self): super().__init__() self.setWindowTitle("MySQL 数据库导出为 SQLite 兼容 SQL") self.default_host = "localhost" self.default_user = "root" self.default_password = "123456" # 替换为你自己的密码 self.select_all_state = False self.resize(700, 800) self.init_ui() def init_ui(self): layout = QVBoxLayout() # 数据库选择 self.database_combobox = QComboBox() self.database_combobox.addItem("") # 空白选项 self.database_combobox.addItem("疾病库") self.database_combobox.addItem("智能中医系统") self.database_combobox.addItem("实验") self.load_tables_button = QPushButton("加载表名") self.load_tables_button.clicked.connect(self.load_tables) layout.addWidget(QLabel("数据库名称:")) layout.addWidget(self.database_combobox) layout.addWidget(self.load_tables_button) # 表选择按钮 table_button_layout = QHBoxLayout() self.select_all_button = QPushButton("全选") self.select_all_button.clicked.connect(self.toggle_select_all) table_button_layout.addWidget(self.select_all_button) layout.addLayout(table_button_layout) # 滚动区域显示表 self.scroll_area = QScrollArea() self.scroll_content = QWidget() self.scroll_layout = QVBoxLayout(self.scroll_content) self.scroll_content.setLayout(self.scroll_layout) self.scroll_area.setWidget(self.scroll_content) self.scroll_area.setWidgetResizable(True) layout.addWidget(QLabel("选择要导出的表:")) layout.addWidget(self.scroll_area) # 导出格式选择 export_format_layout = QHBoxLayout() self.overwrite_sql_radio = QRadioButton("覆盖性 SQLite SQL") self.append_sql_radio = QRadioButton("添加性 SQLite SQL") self.overwrite_sql_radio.setChecked(True) export_format_layout.addWidget(self.overwrite_sql_radio) export_format_layout.addWidget(self.append_sql_radio) layout.addLayout(export_format_layout) # 导出按钮 self.export_button = QPushButton("导出为 SQLite SQL") self.export_button.clicked.connect(self.export_database) layout.addWidget(self.export_button) self.setLayout(layout) self.tables = [] def toggle_select_all(self): self.select_all_state = not self.select_all_state for i in range(self.scroll_layout.count()): widget = self.scroll_layout.itemAt(i).widget() if isinstance(widget, QCheckBox): widget.setChecked(self.select_all_state) self.select_all_button.setText("取消全选" if self.select_all_state else "全选") def load_tables(self): database = self.database_combobox.currentText() if not database: QMessageBox.warning(self, "输入错误", "请选择一个数据库") return try: connection = pymysql.connect( host=self.default_host, user=self.default_user, password=self.default_password, database=database, charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor ) with connection.cursor() as cursor: cursor.execute("SHOW TABLES") self.tables = [table[f"Tables_in_{database}"] for table in cursor.fetchall()] # 清空滚动区域 for i in reversed(range(self.scroll_layout.count())): widget = self.scroll_layout.itemAt(i).widget() if widget: widget.setParent(None) if not self.tables: self.scroll_layout.addWidget(QLabel("该数据库中没有表")) else: for table in self.tables: cb = QCheckBox(table) self.scroll_layout.addWidget(cb) except Exception as e: QMessageBox.critical(self, "数据库错误", str(e)) finally: if 'connection' in locals() and connection.open: connection.close() def convert_to_sqlite_create(self, create_sql, table_name): # 替换表名 create_sql = re.sub(r'CREATE TABLE `.*?`', f'CREATE TABLE "{table_name}"', create_sql) # 替换字段类型 create_sql = re.sub(r'varchar$[0-9]+$|char$[0-9]+$|text|longtext|mediumtext', 'TEXT', create_sql) create_sql = re.sub(r'int unsigned|bigint unsigned|int|integer', 'INTEGER', create_sql) create_sql = re.sub(r'datetime|date|timestamp', 'TEXT', create_sql) create_sql = re.sub(r'decimal$[0-9,]+$|float|double|real', 'REAL', create_sql) create_sql = re.sub(r'blob|mediumblob|longblob', 'BLOB', create_sql) create_sql = re.sub(r'boolean|bool', 'INTEGER', create_sql) # 主键自增替换 create_sql = re.sub(r'`id` int(?: unsigned)? NOT NULL AUTO_INCREMENT', '`id` INTEGER PRIMARY KEY', create_sql) # 删除 KEY 定义 create_sql = re.sub(r',\s*(?:UNIQUE\s+KEY|KEY|PRIMARY KEY)[^,]*$', '', create_sql, flags=re.MULTILINE) # 删除 ENGINE, CHARSET 等 create_sql = re.sub(r'(?:ENGINE|CHARSET|COLLATE|ROW_FORMAT|AUTO_INCREMENT)=.*?(\s|$)', '', create_sql) return create_sql def export_table_to_sqlite(self, connection, database, table_name, export_dir, overwrite=True): file_path = os.path.join(export_dir, f"{table_name}_sqlite.sql") mode = 'w' if overwrite else 'a' try: with open(file_path, mode, encoding='utf-8') as f: with connection.cursor() as cursor: # 获取表结构 try: cursor.execute(f"SHOW CREATE TABLE `{table_name}`") result = cursor.fetchone() create_sql = result['Create Table'] # ✅ 正确的字段名 except Exception as e: print(f"[{table_name}] 获取表结构失败:") traceback.print_exc() QMessageBox.critical(self, "SQL错误", f"获取表结构失败: {e}") return sqlite_create_sql = self.convert_to_sqlite_create(create_sql, table_name) if overwrite: f.write(f"-- 表结构: {table_name}\n") f.write(f"DROP TABLE IF EXISTS \"{table_name}\";\n") f.write(f"{sqlite_create_sql};\n\n") # 获取数据 try: cursor.execute(f"SELECT * FROM `{table_name}`") rows = cursor.fetchall() if not rows: print(f"表 {table_name} 中没有数据") return except Exception as e: print(f"[{table_name}] 查询表数据失败:") traceback.print_exc() QMessageBox.critical(self, "SQL错误", f"查询表数据失败: {e}") return columns = list(rows[0].keys()) # 构建插入语句 column_str = ", ".join(f'"{col}"' for col in columns) for row in rows: values = [] for val in row.values(): if isinstance(val, str): escaped_val = val.replace("'", "''") values.append(f"'{escaped_val}'") elif isinstance(val, (bytes, bytearray)): hex_val = "x'" + val.hex() + "'" values.append(hex_val) elif isinstance(val, (int, float)): values.append(str(val)) elif val is None: values.append("NULL") else: values.append(f"'{str(val)}'") value_str = ", ".join(values) f.write(f"INSERT INTO \"{table_name}\" ({column_str}) VALUES ({value_str});\n") f.write("\n") except Exception as e: print(f"[{table_name}] 写入文件失败:") traceback.print_exc() QMessageBox.critical(self, "文件写入错误", f"写入 SQL 文件失败: {e}") def export_database(self): database = self.database_combobox.currentText() if not database: QMessageBox.warning(self, "输入错误", "请输入数据库名称") return selected_tables = [] for i in range(self.scroll_layout.count()): widget = self.scroll_layout.itemAt(i).widget() if isinstance(widget, QCheckBox) and widget.isChecked(): selected_tables.append(widget.text()) if not selected_tables: QMessageBox.warning(self, "未选择表", "请选择至少一个表进行导出") return try: connection = pymysql.connect( host=self.default_host, user=self.default_user, password=self.default_password, database=database, charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor ) print(f"已连接数据库: {database}") export_dir = QFileDialog.getExistingDirectory(self, "选择导出目录") if not export_dir: QMessageBox.warning(self, "路径无效", "未选择导出目录") return print(f"导出目录: {export_dir}") overwrite = self.overwrite_sql_radio.isChecked() for table in selected_tables: print(f"正在导出表: {table}") self.export_table_to_sqlite(connection, database, table, export_dir, overwrite=overwrite) QMessageBox.information(self, "成功", "所选表已成功导出为 SQLite 兼容 SQL 文件") except Exception as e: print("发生异常:") traceback.print_exc() # 打印完整堆栈 QMessageBox.critical(self, "错误", f"发生错误:{str(e)}\n\n详情请查看控制台输出") finally: if 'connection' in locals() and connection.open: connection.close() if __name__ == "__main__": app = QApplication(sys.argv) window = DatabaseExporter() window.show() sys.exit(app.exec_()) 所以我这里应该怎么修改
最新发布
09-08
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值