初始化提交
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
__pycache__
|
||||||
|
test
|
||||||
214
README.md
Normal file
214
README.md
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
# 多数据库交互脚本
|
||||||
|
|
||||||
|
一个支持多种数据库的 Python 交互式命令行工具,可以方便地连接和操作各种数据库。
|
||||||
|
|
||||||
|
## 支持的数据库
|
||||||
|
|
||||||
|
- ✅ MySQL
|
||||||
|
- ✅ MongoDB
|
||||||
|
- ✅ Redis
|
||||||
|
- ✅ SQLite
|
||||||
|
- ✅ PostgreSQL
|
||||||
|
|
||||||
|
## 系统支持
|
||||||
|
|
||||||
|
- ✅ Windows
|
||||||
|
- ✅ Linux
|
||||||
|
- ✅ macOS
|
||||||
|
- ✅ Termux (Android)
|
||||||
|
|
||||||
|
## 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装所有依赖
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# 或者单独安装需要的数据库驱动
|
||||||
|
pip install pymysql # MySQL
|
||||||
|
pip install pymongo # MongoDB
|
||||||
|
pip install redis # Redis
|
||||||
|
pip install psycopg2-binary # PostgreSQL
|
||||||
|
# SQLite 是 Python 内置模块,无需安装
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
### 1. 启动脚本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 选择数据库类型
|
||||||
|
|
||||||
|
启动后会提示选择数据库类型:
|
||||||
|
|
||||||
|
```
|
||||||
|
请选择数据库类型:
|
||||||
|
1. MySQL
|
||||||
|
2. MongoDB
|
||||||
|
3. Redis
|
||||||
|
4. SQLite
|
||||||
|
5. PostgreSQL
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 输入连接信息
|
||||||
|
|
||||||
|
根据提示输入数据库的连接信息(主机、端口、用户名、密码等)。
|
||||||
|
|
||||||
|
### 4. 执行命令
|
||||||
|
|
||||||
|
连接成功后,就可以输入相应的命令进行数据库操作。
|
||||||
|
|
||||||
|
## 命令示例
|
||||||
|
|
||||||
|
### MySQL / PostgreSQL / SQLite
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 查询
|
||||||
|
SELECT * FROM users;
|
||||||
|
SELECT name, age FROM users WHERE age > 18;
|
||||||
|
|
||||||
|
-- 插入
|
||||||
|
INSERT INTO users (name, age) VALUES ('张三', 25);
|
||||||
|
|
||||||
|
-- 更新
|
||||||
|
UPDATE users SET age = 26 WHERE name = '张三';
|
||||||
|
|
||||||
|
-- 删除
|
||||||
|
DELETE FROM users WHERE name = '张三';
|
||||||
|
|
||||||
|
-- 创建表
|
||||||
|
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER);
|
||||||
|
```
|
||||||
|
|
||||||
|
### MongoDB
|
||||||
|
|
||||||
|
MongoDB 使用 JSON 格式的命令:
|
||||||
|
|
||||||
|
```json
|
||||||
|
// 查询所有文档
|
||||||
|
{"collection": "users", "operation": "find", "query": {}}
|
||||||
|
|
||||||
|
// 条件查询
|
||||||
|
{"collection": "users", "operation": "find", "query": {"age": {"$gt": 18}}}
|
||||||
|
|
||||||
|
// 插入文档
|
||||||
|
{"collection": "users", "operation": "insert", "document": {"name": "张三", "age": 25}}
|
||||||
|
|
||||||
|
// 更新文档
|
||||||
|
{"collection": "users", "operation": "update", "query": {"name": "张三"}, "update": {"$set": {"age": 26}}}
|
||||||
|
|
||||||
|
// 删除文档
|
||||||
|
{"collection": "users", "operation": "delete", "query": {"name": "张三"}}
|
||||||
|
|
||||||
|
// 统计数量
|
||||||
|
{"collection": "users", "operation": "count", "query": {}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Redis
|
||||||
|
|
||||||
|
```
|
||||||
|
# 字符串操作
|
||||||
|
SET name 张三
|
||||||
|
GET name
|
||||||
|
DEL name
|
||||||
|
|
||||||
|
# 哈希操作
|
||||||
|
HSET user:1 name 张三
|
||||||
|
HSET user:1 age 25
|
||||||
|
HGET user:1 name
|
||||||
|
HGETALL user:1
|
||||||
|
|
||||||
|
# 列表操作
|
||||||
|
LPUSH mylist item1 item2 item3
|
||||||
|
LRANGE mylist 0 -1
|
||||||
|
|
||||||
|
# 集合操作
|
||||||
|
SADD myset member1 member2
|
||||||
|
SMEMBERS myset
|
||||||
|
|
||||||
|
# 查询所有键
|
||||||
|
KEYS *
|
||||||
|
|
||||||
|
# 测试连接
|
||||||
|
PING
|
||||||
|
```
|
||||||
|
|
||||||
|
## 内置命令
|
||||||
|
|
||||||
|
- `help` - 显示帮助信息
|
||||||
|
- `connect` - 连接到数据库
|
||||||
|
- `disconnect` - 断开数据库连接
|
||||||
|
- `status` - 查看连接状态
|
||||||
|
- `switch <db>` - 切换数据库类型 (mysql/mongodb/redis/sqlite/postgres)
|
||||||
|
- `quit` 或 `exit` - 退出程序
|
||||||
|
|
||||||
|
## 文件说明
|
||||||
|
|
||||||
|
- `main.py` - 主程序入口
|
||||||
|
- `mysql.py` - MySQL 数据库操作模块
|
||||||
|
- `mongodb.py` - MongoDB 数据库操作模块
|
||||||
|
- `redis.py` - Redis 数据库操作模块
|
||||||
|
- `sqlite.py` - SQLite 数据库操作模块
|
||||||
|
- `postgres.py` - PostgreSQL 数据库操作模块
|
||||||
|
- `requirements.txt` - 依赖包列表
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 首次使用前请确保已安装相应的数据库驱动
|
||||||
|
2. SQLite 会在当前目录创建数据库文件
|
||||||
|
3. 确保数据库服务已启动并可以访问
|
||||||
|
4. 使用完毕后建议执行 `disconnect` 命令断开连接
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q: 连接失败怎么办?
|
||||||
|
|
||||||
|
A: 请检查:
|
||||||
|
- 数据库服务是否已启动
|
||||||
|
- 主机地址和端口是否正确
|
||||||
|
- 用户名和密码是否正确
|
||||||
|
- 防火墙是否允许连接
|
||||||
|
|
||||||
|
### Q: Redis 连接时提示 "module 'redis' has no attribute 'Redis'" 怎么办?
|
||||||
|
|
||||||
|
A: 这个问题已经修复。如果仍然遇到,请:
|
||||||
|
1. 确保安装了正确的 redis 包:`pip install redis`
|
||||||
|
2. 检查是否有其他名为 redis.py 的文件冲突
|
||||||
|
3. 运行测试脚本检查依赖:`python test_import.py`
|
||||||
|
|
||||||
|
### Q: 如何检查依赖是否正确安装?
|
||||||
|
|
||||||
|
A: 运行测试脚本:
|
||||||
|
```bash
|
||||||
|
python test_import.py
|
||||||
|
```
|
||||||
|
这将检查所有必需的数据库驱动是否正确安装。
|
||||||
|
|
||||||
|
### Q: 如何在 Termux 中使用?
|
||||||
|
|
||||||
|
A: 在 Termux 中需要先安装 Python 和必要的依赖:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pkg install python
|
||||||
|
pkg install build-essential # 编译某些包需要
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q: 如何切换数据库?
|
||||||
|
|
||||||
|
A: 使用 `switch <数据库类型>` 命令,例如:
|
||||||
|
|
||||||
|
```
|
||||||
|
switch mysql
|
||||||
|
switch mongodb
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q: MongoDB 需要用户认证怎么办?
|
||||||
|
|
||||||
|
A: 在配置时会询问是否需要认证,选择 y 后输入用户名和密码即可。
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT License
|
||||||
447
main.py
Normal file
447
main.py
Normal file
@@ -0,0 +1,447 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
多数据库交互脚本
|
||||||
|
支持 MySQL, MongoDB, Redis, SQLite, PostgreSQL
|
||||||
|
跨平台支持: Windows, Linux, Termux 等
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
# 导入数据库模块(处理可能的导入错误)
|
||||||
|
try:
|
||||||
|
from mysql_db import MySQLDatabase
|
||||||
|
from mongodb_db import MongoDatabase
|
||||||
|
from redis_db import RedisDatabase
|
||||||
|
from sqlite_db import SQLiteDatabase
|
||||||
|
from postgres_db import PostgreSQLDatabase
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"错误: 导入数据库模块失败")
|
||||||
|
print(f"详细信息: {e}")
|
||||||
|
print("\n请确保已安装所需的依赖包:")
|
||||||
|
print(" pip install -r requirements.txt")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def print_banner():
|
||||||
|
"""打印欢迎信息"""
|
||||||
|
banner = """
|
||||||
|
╔══════════════════════════════════════════╗
|
||||||
|
║ 多数据库交互工具 v1.0 ║
|
||||||
|
║ 支持: MySQL, MongoDB, Redis, ║
|
||||||
|
║ SQLite, PostgreSQL ║
|
||||||
|
╚══════════════════════════════════════════╝
|
||||||
|
"""
|
||||||
|
print(banner)
|
||||||
|
|
||||||
|
|
||||||
|
def print_help():
|
||||||
|
"""打印帮助信息"""
|
||||||
|
help_text = """
|
||||||
|
========================================================================
|
||||||
|
脚本通用命令:
|
||||||
|
- help : 显示帮助信息
|
||||||
|
- connect : 连接到数据库
|
||||||
|
- disconnect : 断开数据库连接
|
||||||
|
- status : 查看连接状态
|
||||||
|
- switch <db> : 切换数据库类型 (mysql/mongodb/redis/sqlite/postgres)
|
||||||
|
- show databases: 列出所有数据库 (仅MySQL/PostgreSQL)
|
||||||
|
- use <database>: 切换到指定数据库 (仅MySQL/PostgreSQL)
|
||||||
|
- quit/exit : 退出程序
|
||||||
|
========================================================================
|
||||||
|
MySQL/PostgreSQL/SQLite 通用SQL语句:
|
||||||
|
SELECT * FROM users;
|
||||||
|
INSERT INTO users (name, age) VALUES ('张三', 25);
|
||||||
|
UPDATE users SET age = 26 WHERE name = '张三';
|
||||||
|
DELETE FROM users WHERE name = '张三';
|
||||||
|
========================================================================
|
||||||
|
SQLite 点命令:
|
||||||
|
.tables - 列出所有表
|
||||||
|
.schema - 显示所有表的结构
|
||||||
|
.schema <table> - 显示特定表的结构
|
||||||
|
.databases - 列出数据库信息
|
||||||
|
.indexes - 列出所有索引
|
||||||
|
.indexes <table> - 列出特定表的索引
|
||||||
|
========================================================================
|
||||||
|
MongoDB Shell 命令:
|
||||||
|
show dbs - 列出所有数据库
|
||||||
|
show collections - 列出当前数据库的集合
|
||||||
|
use <database> - 切换数据库
|
||||||
|
========================================================================
|
||||||
|
MongoDB JSON 命令:
|
||||||
|
{"collection": "users", "operation": "find", "query": {}}
|
||||||
|
{"collection": "users", "operation": "insert", "document": {"name": "张三", "age": 25}}
|
||||||
|
{"collection": "users", "operation": "update", "query": {"name": "张三"}, "update": {"$set": {"age": 26}}}
|
||||||
|
{"collection": "users", "operation": "delete", "query": {"name": "张三"}}
|
||||||
|
========================================================================
|
||||||
|
Redis 键值命令:
|
||||||
|
SET name 张三
|
||||||
|
GET name
|
||||||
|
HSET user:1 name 张三 age 25
|
||||||
|
HGETALL user:1
|
||||||
|
KEYS *
|
||||||
|
========================================================================
|
||||||
|
"""
|
||||||
|
print(help_text)
|
||||||
|
|
||||||
|
|
||||||
|
def get_database_config(db_type):
|
||||||
|
"""
|
||||||
|
获取数据库配置
|
||||||
|
:param db_type: 数据库类型
|
||||||
|
:return: 配置字典
|
||||||
|
"""
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
if db_type == 'mysql':
|
||||||
|
print("\n请输入 MySQL 配置信息:")
|
||||||
|
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
|
||||||
|
config['port'] = int(input("端口 [3306]: ").strip() or '3306')
|
||||||
|
config['user'] = input("用户名 [root]: ").strip() or 'root'
|
||||||
|
config['password'] = input("密码: ").strip()
|
||||||
|
|
||||||
|
# 默认先列出数据库,然后让用户选择
|
||||||
|
config['database'] = None # 先不指定数据库
|
||||||
|
config['_list_databases'] = True # 标记需要列出数据库
|
||||||
|
|
||||||
|
elif db_type == 'mongodb':
|
||||||
|
print("\n请输入 MongoDB 配置信息:")
|
||||||
|
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
|
||||||
|
config['port'] = int(input("端口 [27017]: ").strip() or '27017')
|
||||||
|
config['database'] = input("数据库名 [test]: ").strip() or 'test'
|
||||||
|
|
||||||
|
# 询问是否需要认证
|
||||||
|
need_auth = input("是否需要用户认证? (y/n) [n]: ").strip().lower()
|
||||||
|
if need_auth == 'y':
|
||||||
|
config['username'] = input("用户名: ").strip()
|
||||||
|
config['password'] = input("密码: ").strip()
|
||||||
|
else:
|
||||||
|
config['username'] = None
|
||||||
|
config['password'] = None
|
||||||
|
|
||||||
|
elif db_type == 'redis':
|
||||||
|
print("\n请输入 Redis 配置信息:")
|
||||||
|
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
|
||||||
|
config['port'] = int(input("端口 [6379]: ").strip() or '6379')
|
||||||
|
config['db'] = int(input("数据库编号 [0]: ").strip() or '0')
|
||||||
|
password = input("密码 (留空表示无密码): ").strip()
|
||||||
|
config['password'] = password if password else None
|
||||||
|
|
||||||
|
elif db_type == 'sqlite':
|
||||||
|
print("\n请输入 SQLite 配置信息:")
|
||||||
|
config['database'] = input("数据库文件路径 [database.db]: ").strip() or 'database.db'
|
||||||
|
|
||||||
|
elif db_type == 'postgres':
|
||||||
|
print("\n请输入 PostgreSQL 配置信息:")
|
||||||
|
config['host'] = input("主机地址 [localhost]: ").strip() or 'localhost'
|
||||||
|
config['port'] = int(input("端口 [5432]: ").strip() or '5432')
|
||||||
|
config['user'] = input("用户名 [postgres]: ").strip() or 'postgres'
|
||||||
|
config['password'] = input("密码: ").strip()
|
||||||
|
|
||||||
|
# 默认先列出数据库,然后让用户选择
|
||||||
|
config['database'] = 'postgres' # 先连接到默认数据库
|
||||||
|
config['_list_databases'] = True # 标记需要列出数据库
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def create_database_instance(db_type, config):
|
||||||
|
"""
|
||||||
|
创建数据库实例
|
||||||
|
:param db_type: 数据库类型
|
||||||
|
:param config: 配置字典
|
||||||
|
:return: 数据库实例
|
||||||
|
"""
|
||||||
|
if db_type == 'mysql':
|
||||||
|
return MySQLDatabase(**config)
|
||||||
|
elif db_type == 'mongodb':
|
||||||
|
return MongoDatabase(**config)
|
||||||
|
elif db_type == 'redis':
|
||||||
|
return RedisDatabase(**config)
|
||||||
|
elif db_type == 'sqlite':
|
||||||
|
return SQLiteDatabase(**config)
|
||||||
|
elif db_type == 'postgres':
|
||||||
|
return PostgreSQLDatabase(**config)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def format_output(data):
|
||||||
|
"""
|
||||||
|
格式化输出结果
|
||||||
|
:param data: 数据
|
||||||
|
:return: 格式化后的字符串
|
||||||
|
"""
|
||||||
|
if isinstance(data, list):
|
||||||
|
# 检查是否是字符串列表(如 .schema 的输出)
|
||||||
|
if data and all(isinstance(item, str) for item in data):
|
||||||
|
# 直接输出,保留换行符
|
||||||
|
return '\n\n'.join(data)
|
||||||
|
else:
|
||||||
|
# JSON 格式化
|
||||||
|
return json.dumps(data, ensure_ascii=False, indent=2)
|
||||||
|
elif isinstance(data, dict):
|
||||||
|
return json.dumps(data, ensure_ascii=False, indent=2)
|
||||||
|
else:
|
||||||
|
return str(data)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""主函数"""
|
||||||
|
print_banner()
|
||||||
|
|
||||||
|
# 选择数据库类型
|
||||||
|
print("请选择数据库类型:")
|
||||||
|
print("1. MySQL")
|
||||||
|
print("2. MongoDB")
|
||||||
|
print("3. Redis")
|
||||||
|
print("4. SQLite")
|
||||||
|
print("5. PostgreSQL")
|
||||||
|
|
||||||
|
choice = input("\n请输入选项 (1-5): ").strip()
|
||||||
|
|
||||||
|
db_types = {
|
||||||
|
'1': 'mysql',
|
||||||
|
'2': 'mongodb',
|
||||||
|
'3': 'redis',
|
||||||
|
'4': 'sqlite',
|
||||||
|
'5': 'postgres'
|
||||||
|
}
|
||||||
|
|
||||||
|
if choice not in db_types:
|
||||||
|
print("无效的选项!")
|
||||||
|
return
|
||||||
|
|
||||||
|
current_db_type = db_types[choice]
|
||||||
|
print(f"\n已选择: {current_db_type.upper()}")
|
||||||
|
|
||||||
|
# 获取配置并创建数据库实例
|
||||||
|
config = get_database_config(current_db_type)
|
||||||
|
list_databases = config.pop('_list_databases', False)
|
||||||
|
db = create_database_instance(current_db_type, config)
|
||||||
|
|
||||||
|
if not db:
|
||||||
|
print("创建数据库实例失败!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 是否自动连接
|
||||||
|
#auto_connect = input("\n是否立即连接? (y/n) [y]: ").strip().lower()
|
||||||
|
#if auto_connect != 'n':
|
||||||
|
success, message = db.connect()
|
||||||
|
print(f"\n{message}")
|
||||||
|
connected = success
|
||||||
|
|
||||||
|
# 如果需要列出数据库
|
||||||
|
if connected and list_databases and hasattr(db, 'list_databases'):
|
||||||
|
success_list, result = db.list_databases()
|
||||||
|
if success_list:
|
||||||
|
print("\n可用的数据库:")
|
||||||
|
for i, db_name in enumerate(result, 1):
|
||||||
|
print(f" {i}. {db_name}")
|
||||||
|
|
||||||
|
# 让用户选择数据库
|
||||||
|
if current_db_type in ['mysql', 'postgres']:
|
||||||
|
while True:
|
||||||
|
db_choice = input("\n请输入数据库名或编号 (直接回车跳过): ").strip()
|
||||||
|
if not db_choice:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 判断是数字还是数据库名
|
||||||
|
selected_db = None
|
||||||
|
if db_choice.isdigit():
|
||||||
|
index = int(db_choice) - 1
|
||||||
|
if 0 <= index < len(result):
|
||||||
|
selected_db = result[index]
|
||||||
|
else:
|
||||||
|
print(f"错误: 编号超出范围,请输入 1-{len(result)} 之间的数字")
|
||||||
|
retry = input("是否重新输入? (y/n) [y]: ").strip().lower()
|
||||||
|
if retry == 'n':
|
||||||
|
break
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
selected_db = db_choice
|
||||||
|
|
||||||
|
# 尝试切换数据库
|
||||||
|
use_success, use_msg = db.use_database(selected_db)
|
||||||
|
print(use_msg)
|
||||||
|
|
||||||
|
if use_success:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
retry = input("是否重新输入? (y/n) [y]: ").strip().lower()
|
||||||
|
if retry == 'n':
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print(f"\n{result}")
|
||||||
|
|
||||||
|
|
||||||
|
print("\n输入 'help' 查看帮助信息")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# 主循环
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# 显示提示符
|
||||||
|
prompt = f"\n[{current_db_type.upper()}{'*' if connected else ''}]> "
|
||||||
|
command = input(prompt).strip()
|
||||||
|
|
||||||
|
if not command:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 处理特殊命令
|
||||||
|
cmd_lower = command.lower()
|
||||||
|
|
||||||
|
if cmd_lower in ['quit', 'exit']:
|
||||||
|
if connected:
|
||||||
|
print(db.close())
|
||||||
|
print("\n再见!")
|
||||||
|
break
|
||||||
|
|
||||||
|
elif cmd_lower == 'help':
|
||||||
|
print_help()
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif cmd_lower == 'connect':
|
||||||
|
if connected:
|
||||||
|
print("已经连接到数据库")
|
||||||
|
else:
|
||||||
|
success, message = db.connect()
|
||||||
|
print(message)
|
||||||
|
connected = success
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif cmd_lower == 'disconnect':
|
||||||
|
if not connected:
|
||||||
|
print("未连接到数据库")
|
||||||
|
else:
|
||||||
|
print(db.close())
|
||||||
|
connected = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif cmd_lower == 'status':
|
||||||
|
status = "已连接" if connected else "未连接"
|
||||||
|
print(f"数据库类型: {current_db_type.upper()}")
|
||||||
|
print(f"连接状态: {status}")
|
||||||
|
if connected and hasattr(db, 'database') and db.database:
|
||||||
|
print(f"当前数据库: {db.database}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif cmd_lower == 'show databases':
|
||||||
|
if not connected:
|
||||||
|
print("请先连接到数据库 (使用 'connect' 命令)")
|
||||||
|
elif not hasattr(db, 'list_databases'):
|
||||||
|
print("当前数据库类型不支持此命令")
|
||||||
|
else:
|
||||||
|
success, result = db.list_databases()
|
||||||
|
if success:
|
||||||
|
print("\n可用的数据库:")
|
||||||
|
for i, db_name in enumerate(result, 1):
|
||||||
|
print(f" {i}. {db_name}")
|
||||||
|
else:
|
||||||
|
print(f"\n{result}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif cmd_lower.startswith('use '):
|
||||||
|
if not connected:
|
||||||
|
print("请先连接到数据库 (使用 'connect' 命令)")
|
||||||
|
elif not hasattr(db, 'use_database'):
|
||||||
|
print("当前数据库类型不支持此命令")
|
||||||
|
else:
|
||||||
|
db_input = command.split(maxsplit=1)[1].strip()
|
||||||
|
|
||||||
|
# 先获取数据库列表
|
||||||
|
list_success, db_list = db.list_databases()
|
||||||
|
|
||||||
|
# 判断是数字还是数据库名
|
||||||
|
selected_db = None
|
||||||
|
if db_input.isdigit() and list_success:
|
||||||
|
index = int(db_input) - 1
|
||||||
|
if 0 <= index < len(db_list):
|
||||||
|
selected_db = db_list[index]
|
||||||
|
else:
|
||||||
|
print(f"错误: 编号超出范围,请使用 'show databases' 查看可用数据库")
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
selected_db = db_input
|
||||||
|
|
||||||
|
# 尝试切换数据库
|
||||||
|
success, message = db.use_database(selected_db)
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
# 如果失败,询问是否重试
|
||||||
|
if not success:
|
||||||
|
retry = input("是否重新输入数据库名? (y/n) [y]: ").strip().lower()
|
||||||
|
if retry != 'n':
|
||||||
|
while True:
|
||||||
|
new_db = input("请输入数据库名或编号: ").strip()
|
||||||
|
if not new_db:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 再次判断数字或名称
|
||||||
|
if new_db.isdigit() and list_success:
|
||||||
|
idx = int(new_db) - 1
|
||||||
|
if 0 <= idx < len(db_list):
|
||||||
|
new_db = db_list[idx]
|
||||||
|
else:
|
||||||
|
print(f"错误: 编号超出范围")
|
||||||
|
continue
|
||||||
|
|
||||||
|
success2, message2 = db.use_database(new_db)
|
||||||
|
print(message2)
|
||||||
|
if success2:
|
||||||
|
break
|
||||||
|
|
||||||
|
retry_again = input("是否继续重试? (y/n) [y]: ").strip().lower()
|
||||||
|
if retry_again == 'n':
|
||||||
|
break
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif cmd_lower.startswith('switch '):
|
||||||
|
new_type = cmd_lower.split()[1]
|
||||||
|
if new_type not in ['mysql', 'mongodb', 'redis', 'sqlite', 'postgres']:
|
||||||
|
print("无效的数据库类型!")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 关闭当前连接
|
||||||
|
if connected:
|
||||||
|
print(db.close())
|
||||||
|
connected = False
|
||||||
|
|
||||||
|
# 切换数据库
|
||||||
|
current_db_type = new_type
|
||||||
|
config = get_database_config(current_db_type)
|
||||||
|
db = create_database_instance(current_db_type, config)
|
||||||
|
print(f"已切换到 {current_db_type.upper()}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 执行数据库命令
|
||||||
|
if not connected:
|
||||||
|
print("请先连接到数据库 (使用 'connect' 命令)")
|
||||||
|
continue
|
||||||
|
|
||||||
|
success, result = db.execute(command)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print(f"\n执行成功:")
|
||||||
|
print(format_output(result))
|
||||||
|
else:
|
||||||
|
print(f"\n执行失败:")
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n\n操作已取消")
|
||||||
|
continue
|
||||||
|
except EOFError:
|
||||||
|
print("\n\n再见!")
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n发生错误: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n\n程序已退出")
|
||||||
|
sys.exit(0)
|
||||||
178
mongodb_db.py
Normal file
178
mongodb_db.py
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
MongoDB 数据库操作模块
|
||||||
|
支持基本的文档操作
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pymongo import MongoClient
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"错误: 无法导入 pymongo 库,请确保已安装: pip install pymongo")
|
||||||
|
print(f"详细错误: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
class MongoDatabase:
|
||||||
|
"""MongoDB 数据库连接和操作类"""
|
||||||
|
|
||||||
|
def __init__(self, host='localhost', port=27017, database='test', username=None, password=None):
|
||||||
|
"""
|
||||||
|
初始化 MongoDB 连接参数
|
||||||
|
:param host: 数据库主机地址
|
||||||
|
:param port: 数据库端口
|
||||||
|
:param database: 数据库名
|
||||||
|
:param username: 用户名(可选)
|
||||||
|
:param password: 密码(可选)
|
||||||
|
"""
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.database_name = database
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.client = None
|
||||||
|
self.db = None
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
"""建立数据库连接"""
|
||||||
|
try:
|
||||||
|
# 构建连接参数
|
||||||
|
if self.username and self.password:
|
||||||
|
# 使用用户名密码认证
|
||||||
|
self.client = MongoClient(
|
||||||
|
host=self.host,
|
||||||
|
port=self.port,
|
||||||
|
username=self.username,
|
||||||
|
password=self.password,
|
||||||
|
authSource=self.database_name, # 认证数据库
|
||||||
|
serverSelectionTimeoutMS=5000
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 无需认证
|
||||||
|
self.client = MongoClient(
|
||||||
|
host=self.host,
|
||||||
|
port=self.port,
|
||||||
|
serverSelectionTimeoutMS=5000
|
||||||
|
)
|
||||||
|
|
||||||
|
# 测试连接
|
||||||
|
self.client.admin.command('ping')
|
||||||
|
self.db = self.client[self.database_name]
|
||||||
|
return True, f"MongoDB 连接成功 (数据库: {self.database_name})"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"MongoDB 连接失败: {str(e)}"
|
||||||
|
|
||||||
|
def execute(self, command):
|
||||||
|
"""
|
||||||
|
执行 MongoDB 命令
|
||||||
|
:param command: MongoDB 命令字符串(JSON 格式或 shell 命令)
|
||||||
|
示例: {"collection": "users", "operation": "find", "query": {}}
|
||||||
|
或: show dbs, show collections, use <database>
|
||||||
|
"""
|
||||||
|
if self.db is None:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
|
||||||
|
# 处理 MongoDB shell 命令
|
||||||
|
cmd_lower = command.strip().lower()
|
||||||
|
|
||||||
|
# show dbs - 列出所有数据库
|
||||||
|
if cmd_lower in ['show dbs', 'show databases']:
|
||||||
|
try:
|
||||||
|
db_list = self.client.list_database_names()
|
||||||
|
result = []
|
||||||
|
for db_name in db_list:
|
||||||
|
db_stats = self.client[db_name].command('dbstats')
|
||||||
|
size_mb = db_stats.get('dataSize', 0) / (1024 * 1024)
|
||||||
|
result.append(f"{db_name}: {size_mb:.2f} MB")
|
||||||
|
return True, result
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
# show collections - 列出当前数据库的所有集合
|
||||||
|
elif cmd_lower in ['show collections', 'show tables']:
|
||||||
|
try:
|
||||||
|
collections = self.db.list_collection_names()
|
||||||
|
return True, collections
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
# use <database> - 切换数据库
|
||||||
|
elif cmd_lower.startswith('use '):
|
||||||
|
try:
|
||||||
|
db_name = command.strip().split(maxsplit=1)[1]
|
||||||
|
self.db = self.client[db_name]
|
||||||
|
self.database_name = db_name
|
||||||
|
return True, f"已切换到数据库: {db_name}"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"切换数据库失败: {str(e)}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 解析命令
|
||||||
|
if isinstance(command, str):
|
||||||
|
cmd = json.loads(command)
|
||||||
|
else:
|
||||||
|
cmd = command
|
||||||
|
|
||||||
|
collection_name = cmd.get('collection')
|
||||||
|
operation = cmd.get('operation')
|
||||||
|
|
||||||
|
if not collection_name or not operation:
|
||||||
|
return False, "命令必须包含 collection 和 operation 字段"
|
||||||
|
|
||||||
|
collection = self.db[collection_name]
|
||||||
|
|
||||||
|
# 根据操作类型执行不同的命令
|
||||||
|
if operation == 'find':
|
||||||
|
query = cmd.get('query', {})
|
||||||
|
limit = cmd.get('limit', 0)
|
||||||
|
result = list(collection.find(query).limit(limit))
|
||||||
|
# 转换 ObjectId 为字符串
|
||||||
|
for doc in result:
|
||||||
|
if '_id' in doc:
|
||||||
|
doc['_id'] = str(doc['_id'])
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
elif operation == 'insert':
|
||||||
|
document = cmd.get('document')
|
||||||
|
if not document:
|
||||||
|
return False, "插入操作需要 document 字段"
|
||||||
|
result = collection.insert_one(document)
|
||||||
|
return True, f"插入成功, ID: {result.inserted_id}"
|
||||||
|
|
||||||
|
elif operation == 'update':
|
||||||
|
query = cmd.get('query', {})
|
||||||
|
update = cmd.get('update')
|
||||||
|
if not update:
|
||||||
|
return False, "更新操作需要 update 字段"
|
||||||
|
result = collection.update_many(query, update)
|
||||||
|
return True, f"更新了 {result.modified_count} 条记录"
|
||||||
|
|
||||||
|
elif operation == 'delete':
|
||||||
|
query = cmd.get('query', {})
|
||||||
|
result = collection.delete_many(query)
|
||||||
|
return True, f"删除了 {result.deleted_count} 条记录"
|
||||||
|
|
||||||
|
elif operation == 'count':
|
||||||
|
query = cmd.get('query', {})
|
||||||
|
count = collection.count_documents(query)
|
||||||
|
return True, f"共有 {count} 条记录"
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False, f"不支持的操作: {operation}"
|
||||||
|
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return False, "命令格式错误,请使用 JSON 格式"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""关闭数据库连接"""
|
||||||
|
if self.client:
|
||||||
|
self.client.close()
|
||||||
|
self.client = None
|
||||||
|
self.db = None
|
||||||
|
return "MongoDB 连接已关闭"
|
||||||
|
return "连接已经关闭"
|
||||||
113
mysql_db.py
Normal file
113
mysql_db.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
MySQL 数据库操作模块
|
||||||
|
支持基本的增删改查操作
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
import pymysql
|
||||||
|
from pymysql.cursors import DictCursor
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"错误: 无法导入 pymysql 库,请确保已安装: pip install pymysql")
|
||||||
|
print(f"详细错误: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
class MySQLDatabase:
|
||||||
|
"""MySQL 数据库连接和操作类"""
|
||||||
|
|
||||||
|
def __init__(self, host='localhost', port=3306, user='root', password='', database=None):
|
||||||
|
"""
|
||||||
|
初始化 MySQL 连接参数
|
||||||
|
:param host: 数据库主机地址
|
||||||
|
:param port: 数据库端口
|
||||||
|
:param user: 用户名
|
||||||
|
:param password: 密码
|
||||||
|
:param database: 数据库名(可选,不指定则只连接到服务器)
|
||||||
|
"""
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.user = user
|
||||||
|
self.password = password
|
||||||
|
self.database = database
|
||||||
|
self.connection = None
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
"""建立数据库连接"""
|
||||||
|
try:
|
||||||
|
conn_params = {
|
||||||
|
'host': self.host,
|
||||||
|
'port': self.port,
|
||||||
|
'user': self.user,
|
||||||
|
'password': self.password,
|
||||||
|
'charset': 'utf8mb4',
|
||||||
|
'cursorclass': DictCursor
|
||||||
|
}
|
||||||
|
# 如果指定了数据库,则连接到该数据库
|
||||||
|
if self.database:
|
||||||
|
conn_params['database'] = self.database
|
||||||
|
|
||||||
|
self.connection = pymysql.connect(**conn_params)
|
||||||
|
msg = f"MySQL 连接成功" + (f" (数据库: {self.database})" if self.database else " (未选择数据库)")
|
||||||
|
return True, msg
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"MySQL 连接失败: {str(e)}"
|
||||||
|
|
||||||
|
def execute(self, sql, params=None):
|
||||||
|
"""
|
||||||
|
执行 SQL 语句
|
||||||
|
:param sql: SQL 语句
|
||||||
|
:param params: 参数(可选)
|
||||||
|
:return: 执行结果
|
||||||
|
"""
|
||||||
|
if not self.connection:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with self.connection.cursor() as cursor:
|
||||||
|
cursor.execute(sql, params)
|
||||||
|
|
||||||
|
# 判断是查询还是修改操作
|
||||||
|
if sql.strip().upper().startswith(('SELECT', 'SHOW', 'DESC', 'DESCRIBE')):
|
||||||
|
result = cursor.fetchall()
|
||||||
|
return True, result
|
||||||
|
else:
|
||||||
|
self.connection.commit()
|
||||||
|
return True, f"影响行数: {cursor.rowcount}"
|
||||||
|
except Exception as e:
|
||||||
|
self.connection.rollback()
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
def list_databases(self):
|
||||||
|
"""列出所有数据库"""
|
||||||
|
if not self.connection:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
try:
|
||||||
|
with self.connection.cursor() as cursor:
|
||||||
|
cursor.execute("SHOW DATABASES")
|
||||||
|
result = cursor.fetchall()
|
||||||
|
databases = [db['Database'] for db in result]
|
||||||
|
return True, databases
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"获取数据库列表失败: {str(e)}"
|
||||||
|
|
||||||
|
def use_database(self, database):
|
||||||
|
"""切换到指定数据库"""
|
||||||
|
if not self.connection:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
try:
|
||||||
|
self.connection.select_db(database)
|
||||||
|
self.database = database
|
||||||
|
return True, f"已切换到数据库: {database}"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"切换数据库失败: {str(e)}"
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""关闭数据库连接"""
|
||||||
|
if self.connection:
|
||||||
|
self.connection.close()
|
||||||
|
self.connection = None
|
||||||
|
return "MySQL 连接已关闭"
|
||||||
|
return "连接已经关闭"
|
||||||
110
postgres_db.py
Normal file
110
postgres_db.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
PostgreSQL 数据库操作模块
|
||||||
|
支持基本的增删改查操作
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
import psycopg2
|
||||||
|
from psycopg2.extras import RealDictCursor
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"错误: 无法导入 psycopg2 库,请确保已安装: pip install psycopg2-binary")
|
||||||
|
print(f"详细错误: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
class PostgreSQLDatabase:
|
||||||
|
"""PostgreSQL 数据库连接和操作类"""
|
||||||
|
|
||||||
|
def __init__(self, host='localhost', port=5432, user='postgres', password='', database='postgres'):
|
||||||
|
"""
|
||||||
|
初始化 PostgreSQL 连接参数
|
||||||
|
:param host: 数据库主机地址
|
||||||
|
:param port: 数据库端口
|
||||||
|
:param user: 用户名
|
||||||
|
:param password: 密码
|
||||||
|
:param database: 数据库名(默认postgres系统数据库)
|
||||||
|
"""
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.user = user
|
||||||
|
self.password = password
|
||||||
|
self.database = database
|
||||||
|
self.connection = None
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
"""建立数据库连接"""
|
||||||
|
try:
|
||||||
|
self.connection = psycopg2.connect(
|
||||||
|
host=self.host,
|
||||||
|
port=self.port,
|
||||||
|
user=self.user,
|
||||||
|
password=self.password,
|
||||||
|
database=self.database,
|
||||||
|
cursor_factory=RealDictCursor,
|
||||||
|
connect_timeout=5
|
||||||
|
)
|
||||||
|
return True, "PostgreSQL 连接成功"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"PostgreSQL 连接失败: {str(e)}"
|
||||||
|
|
||||||
|
def execute(self, sql, params=None):
|
||||||
|
"""
|
||||||
|
执行 SQL 语句
|
||||||
|
:param sql: SQL 语句
|
||||||
|
:param params: 参数(可选)
|
||||||
|
:return: 执行结果
|
||||||
|
"""
|
||||||
|
if not self.connection:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with self.connection.cursor() as cursor:
|
||||||
|
cursor.execute(sql, params)
|
||||||
|
|
||||||
|
# 判断是查询还是修改操作
|
||||||
|
if sql.strip().upper().startswith(('SELECT', 'SHOW', 'WITH')):
|
||||||
|
result = cursor.fetchall()
|
||||||
|
# 转换为字典列表
|
||||||
|
return True, [dict(row) for row in result]
|
||||||
|
else:
|
||||||
|
self.connection.commit()
|
||||||
|
return True, f"影响行数: {cursor.rowcount}"
|
||||||
|
except Exception as e:
|
||||||
|
self.connection.rollback()
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
def list_databases(self):
|
||||||
|
"""列出所有数据库"""
|
||||||
|
if not self.connection:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
try:
|
||||||
|
with self.connection.cursor() as cursor:
|
||||||
|
cursor.execute("SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname")
|
||||||
|
result = cursor.fetchall()
|
||||||
|
databases = [db['datname'] for db in result]
|
||||||
|
return True, databases
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"获取数据库列表失败: {str(e)}"
|
||||||
|
|
||||||
|
def use_database(self, database):
|
||||||
|
"""切换到指定数据库(需要重新连接)"""
|
||||||
|
if not self.connection:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
try:
|
||||||
|
# PostgreSQL 需要重新连接来切换数据库
|
||||||
|
self.connection.close()
|
||||||
|
self.database = database
|
||||||
|
return self.connect()
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"切换数据库失败: {str(e)}"
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""关闭数据库连接"""
|
||||||
|
if self.connection:
|
||||||
|
self.connection.close()
|
||||||
|
self.connection = None
|
||||||
|
return "PostgreSQL 连接已关闭"
|
||||||
|
return "连接已经关闭"
|
||||||
167
redis_db.py
Normal file
167
redis_db.py
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Redis 数据库操作模块
|
||||||
|
支持基本的键值操作
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
# 避免文件名冲突,确保导入正确的redis库
|
||||||
|
try:
|
||||||
|
from redis import Redis as RedisClient
|
||||||
|
from redis import ConnectionError as RedisConnectionError
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"错误: 无法导入 redis 库,请确保已安装: pip install redis")
|
||||||
|
print(f"详细错误: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
class RedisDatabase:
|
||||||
|
"""Redis 数据库连接和操作类"""
|
||||||
|
|
||||||
|
def __init__(self, host='localhost', port=6379, db=0, password=None):
|
||||||
|
"""
|
||||||
|
初始化 Redis 连接参数
|
||||||
|
:param host: Redis 主机地址
|
||||||
|
:param port: Redis 端口
|
||||||
|
:param db: 数据库编号(0-15)
|
||||||
|
:param password: 密码(可选)
|
||||||
|
"""
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.db = db
|
||||||
|
self.password = password
|
||||||
|
self.client = None
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
"""建立数据库连接"""
|
||||||
|
try:
|
||||||
|
self.client = RedisClient(
|
||||||
|
host=self.host,
|
||||||
|
port=self.port,
|
||||||
|
db=self.db,
|
||||||
|
password=self.password,
|
||||||
|
decode_responses=True,
|
||||||
|
socket_connect_timeout=5
|
||||||
|
)
|
||||||
|
# 测试连接
|
||||||
|
self.client.ping()
|
||||||
|
return True, "Redis 连接成功"
|
||||||
|
except RedisConnectionError as e:
|
||||||
|
return False, f"Redis 连接失败: 无法连接到 Redis 服务器 - {str(e)}"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"Redis 连接失败: {str(e)}"
|
||||||
|
|
||||||
|
def execute(self, command):
|
||||||
|
"""
|
||||||
|
执行 Redis 命令
|
||||||
|
:param command: Redis 命令字符串
|
||||||
|
示例: "SET key value" 或 "GET key"
|
||||||
|
"""
|
||||||
|
if not self.client:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 解析命令
|
||||||
|
parts = command.strip().split()
|
||||||
|
if not parts:
|
||||||
|
return False, "命令不能为空"
|
||||||
|
|
||||||
|
cmd = parts[0].upper()
|
||||||
|
args = parts[1:]
|
||||||
|
|
||||||
|
# 执行常用命令
|
||||||
|
if cmd == 'SET' and len(args) >= 2:
|
||||||
|
key = args[0]
|
||||||
|
value = ' '.join(args[1:])
|
||||||
|
result = self.client.set(key, value)
|
||||||
|
return True, "OK" if result else "FAIL"
|
||||||
|
|
||||||
|
elif cmd == 'GET' and len(args) >= 1:
|
||||||
|
key = args[0]
|
||||||
|
result = self.client.get(key)
|
||||||
|
return True, result if result is not None else "(nil)"
|
||||||
|
|
||||||
|
elif cmd == 'DEL' and len(args) >= 1:
|
||||||
|
result = self.client.delete(*args)
|
||||||
|
return True, f"删除了 {result} 个键"
|
||||||
|
|
||||||
|
elif cmd == 'EXISTS' and len(args) >= 1:
|
||||||
|
result = self.client.exists(*args)
|
||||||
|
return True, f"存在 {result} 个键"
|
||||||
|
|
||||||
|
elif cmd == 'KEYS' and len(args) >= 1:
|
||||||
|
pattern = args[0]
|
||||||
|
result = self.client.keys(pattern)
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
elif cmd == 'HSET' and len(args) >= 3:
|
||||||
|
key = args[0]
|
||||||
|
field = args[1]
|
||||||
|
value = ' '.join(args[2:])
|
||||||
|
result = self.client.hset(key, field, value)
|
||||||
|
return True, f"设置字段成功: {result}"
|
||||||
|
|
||||||
|
elif cmd == 'HGET' and len(args) >= 2:
|
||||||
|
key = args[0]
|
||||||
|
field = args[1]
|
||||||
|
result = self.client.hget(key, field)
|
||||||
|
return True, result if result is not None else "(nil)"
|
||||||
|
|
||||||
|
elif cmd == 'HGETALL' and len(args) >= 1:
|
||||||
|
key = args[0]
|
||||||
|
result = self.client.hgetall(key)
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
elif cmd == 'LPUSH' and len(args) >= 2:
|
||||||
|
key = args[0]
|
||||||
|
result = self.client.lpush(key, *args[1:])
|
||||||
|
return True, f"列表长度: {result}"
|
||||||
|
|
||||||
|
elif cmd == 'LRANGE' and len(args) >= 3:
|
||||||
|
key = args[0]
|
||||||
|
start = int(args[1])
|
||||||
|
stop = int(args[2])
|
||||||
|
result = self.client.lrange(key, start, stop)
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
elif cmd == 'SADD' and len(args) >= 2:
|
||||||
|
key = args[0]
|
||||||
|
result = self.client.sadd(key, *args[1:])
|
||||||
|
return True, f"添加了 {result} 个元素"
|
||||||
|
|
||||||
|
elif cmd == 'SMEMBERS' and len(args) >= 1:
|
||||||
|
key = args[0]
|
||||||
|
result = self.client.smembers(key)
|
||||||
|
return True, list(result)
|
||||||
|
|
||||||
|
elif cmd == 'PING':
|
||||||
|
result = self.client.ping()
|
||||||
|
return True, "PONG" if result else "FAIL"
|
||||||
|
|
||||||
|
elif cmd == 'FLUSHDB':
|
||||||
|
result = self.client.flushdb()
|
||||||
|
return True, "OK" if result else "FAIL"
|
||||||
|
|
||||||
|
elif cmd == 'DBSIZE':
|
||||||
|
result = self.client.dbsize()
|
||||||
|
return True, f"数据库键数量: {result}"
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 尝试执行原始命令
|
||||||
|
result = self.client.execute_command(*parts)
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""关闭数据库连接"""
|
||||||
|
if self.client:
|
||||||
|
self.client.close()
|
||||||
|
self.client = None
|
||||||
|
return "Redis 连接已关闭"
|
||||||
|
return "连接已经关闭"
|
||||||
16
requirements.txt
Normal file
16
requirements.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# 数据库交互脚本依赖包
|
||||||
|
# 安装命令: pip install -r requirements.txt
|
||||||
|
|
||||||
|
# MySQL 数据库
|
||||||
|
pymysql>=1.0.2
|
||||||
|
|
||||||
|
# MongoDB 数据库
|
||||||
|
pymongo>=4.0.0
|
||||||
|
|
||||||
|
# Redis 数据库
|
||||||
|
redis>=4.0.0
|
||||||
|
|
||||||
|
# PostgreSQL 数据库
|
||||||
|
psycopg2-binary>=2.9.0
|
||||||
|
|
||||||
|
# SQLite 是 Python 内置模块,无需额外安装
|
||||||
120
sqlite_db.py
Normal file
120
sqlite_db.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
SQLite 数据库操作模块
|
||||||
|
支持基本的增删改查操作
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
|
|
||||||
|
class SQLiteDatabase:
|
||||||
|
"""SQLite 数据库连接和操作类"""
|
||||||
|
|
||||||
|
def __init__(self, database='database.db'):
|
||||||
|
"""
|
||||||
|
初始化 SQLite 连接参数
|
||||||
|
:param database: 数据库文件路径
|
||||||
|
"""
|
||||||
|
self.database = database
|
||||||
|
self.connection = None
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
"""建立数据库连接"""
|
||||||
|
try:
|
||||||
|
self.connection = sqlite3.connect(self.database)
|
||||||
|
# 设置行工厂,使查询结果以字典形式返回
|
||||||
|
self.connection.row_factory = sqlite3.Row
|
||||||
|
return True, f"SQLite 连接成功 (数据库: {self.database})"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"SQLite 连接失败: {str(e)}"
|
||||||
|
|
||||||
|
def execute(self, sql, params=None):
|
||||||
|
"""
|
||||||
|
执行 SQL 语句或 SQLite 点命令
|
||||||
|
:param sql: SQL 语句或点命令(如 .tables, .schema)
|
||||||
|
:param params: 参数(可选)
|
||||||
|
:return: 执行结果
|
||||||
|
"""
|
||||||
|
if not self.connection:
|
||||||
|
return False, "未连接到数据库"
|
||||||
|
|
||||||
|
# 处理 SQLite 点命令
|
||||||
|
cmd = sql.strip()
|
||||||
|
if cmd.startswith('.'):
|
||||||
|
try:
|
||||||
|
# .tables - 列出所有表
|
||||||
|
if cmd in ['.tables', '.table']:
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
|
||||||
|
tables = [row[0] for row in cursor.fetchall()]
|
||||||
|
return True, tables
|
||||||
|
|
||||||
|
# .schema - 显示所有表的结构
|
||||||
|
elif cmd == '.schema':
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute("SELECT sql FROM sqlite_master WHERE type='table' AND sql IS NOT NULL ORDER BY name")
|
||||||
|
schemas = [row[0] for row in cursor.fetchall()]
|
||||||
|
return True, schemas
|
||||||
|
|
||||||
|
# .schema <table> - 显示特定表的结构
|
||||||
|
elif cmd.startswith('.schema '):
|
||||||
|
table_name = cmd.split(maxsplit=1)[1]
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name=?", (table_name,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
if result:
|
||||||
|
return True, result[0]
|
||||||
|
else:
|
||||||
|
return False, f"表 '{table_name}' 不存在"
|
||||||
|
|
||||||
|
# .databases - 列出数据库信息
|
||||||
|
elif cmd in ['.databases', '.database']:
|
||||||
|
return True, [f"main: {self.database}"]
|
||||||
|
|
||||||
|
# .indexes - 列出所有索引
|
||||||
|
elif cmd in ['.indexes', '.index']:
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='index' ORDER BY name")
|
||||||
|
indexes = [row[0] for row in cursor.fetchall()]
|
||||||
|
return True, indexes
|
||||||
|
|
||||||
|
# .indexes <table> - 列出特定表的索引
|
||||||
|
elif cmd.startswith('.indexes ') or cmd.startswith('.index '):
|
||||||
|
table_name = cmd.split(maxsplit=1)[1]
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name=? ORDER BY name", (table_name,))
|
||||||
|
indexes = [row[0] for row in cursor.fetchall()]
|
||||||
|
return True, indexes
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False, f"不支持的点命令: {cmd.split()[0]}"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
# 执行标准 SQL 语句
|
||||||
|
try:
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute(sql, params or ())
|
||||||
|
|
||||||
|
# 判断是查询还是修改操作
|
||||||
|
if sql.strip().upper().startswith(('SELECT', 'PRAGMA')):
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
# 转换为字典列表
|
||||||
|
result = [dict(row) for row in rows]
|
||||||
|
return True, result
|
||||||
|
else:
|
||||||
|
self.connection.commit()
|
||||||
|
return True, f"影响行数: {cursor.rowcount}"
|
||||||
|
except Exception as e:
|
||||||
|
self.connection.rollback()
|
||||||
|
return False, f"执行失败: {str(e)}"
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""关闭数据库连接"""
|
||||||
|
if self.connection:
|
||||||
|
self.connection.close()
|
||||||
|
self.connection = None
|
||||||
|
return "SQLite 连接已关闭"
|
||||||
|
return "连接已经关闭"
|
||||||
Reference in New Issue
Block a user