Python腳本實(shí)現(xiàn)一鍵執(zhí)行MySQL與達(dá)夢(mèng)數(shù)據(jù)庫(kù)的SQL
在客戶現(xiàn)場(chǎng)做運(yùn)維時(shí),大家是不是經(jīng)常會(huì)遇到這種尷尬場(chǎng)景:
- 沒(méi)有圖形化的數(shù)據(jù)庫(kù)客戶端
- 自帶的數(shù)據(jù)庫(kù)終端又超級(jí)難用
這時(shí)候,如果能有一個(gè)小巧的工具,直接在命令行里執(zhí)行 SQL,是不是會(huì)方便很多?今天這篇文章,就帶大家看看如何用 Python 腳本 + PyInstaller 打包成可執(zhí)行文件,一鍵搞定 MySQL 和達(dá)夢(mèng)(DM)數(shù)據(jù)庫(kù)的 SQL 執(zhí)行。
環(huán)境準(zhǔn)備
首先你需要一個(gè) Linux 環(huán)境,并且提前安裝好 conda。本文示例在 x86 和 ARM 架構(gòu)都測(cè)試過(guò)。
創(chuàng)建 Python 環(huán)境:
conda create -n exec-sql python=3.10 conda activate exec-sql
安裝依賴(目前僅支持 MySQL 和 DM,如需擴(kuò)展可自行修改):
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pymysql dmPython pyinstaller
Python 腳本實(shí)現(xiàn)
核心思路很簡(jiǎn)單:
- 用
argparse解析命令行參數(shù) - 根據(jù)選擇的數(shù)據(jù)庫(kù)類型建立連接
- 支持執(zhí)行 單條 SQL 或 SQL 文件
- 打印結(jié)果
下面是完整的腳本(可直接使用):
# exec_sql.py
import argparse
import pymysql
import dmPython
import os
from pymysql import OperationalError as MySQLError
from dmPython import Error as DMError
def exec_and_print(cursor, sql):
cursor.execute(sql)
if cursor.description:
columns = [col[0] for col in cursor.description]
rows = cursor.fetchall()
print("執(zhí)行結(jié)果:")
print(" | ".join(columns))
print("-" * 50)
for row in rows:
print(" | ".join(str(col) for col in row))
else:
print("SQL 執(zhí)行成功,沒(méi)有返回結(jié)果。")
def execute_sql_from_file(cursor, sqlfile):
if not os.path.exists(sqlfile):
print(f"SQL 文件不存在: {sqlfile}")
return
with open(sqlfile, "r", encoding="utf-8") as f:
sql_script = f.read()
for stmt in sql_script.split(";"):
stmt = stmt.strip()
if stmt:
print(f"執(zhí)行文件中的 SQL: {stmt}")
exec_and_print(cursor, stmt)
def test_db_connection(db_type, host, port, dbname, user, password, sql=None, sqlfile=None):
try:
if db_type == "mysql":
conn_params = {"host": host, "port": port, "user": user, "password": password, "connect_timeout": 5}
if dbname:
conn_params["database"] = dbname
connection = pymysql.connect(**conn_params)
print("成功連接到 MySQL 數(shù)據(jù)庫(kù)!")
elif db_type == "dm":
connection = dmPython.connect(user=user, password=password, server=host, port=port)
if dbname:
cursor = connection.cursor()
cursor.execute(f"set schema {dbname}")
cursor.close()
print("成功連接到 達(dá)夢(mèng)(DM) 數(shù)據(jù)庫(kù)!")
else:
raise ValueError("不支持的數(shù)據(jù)庫(kù)類型")
cursor = connection.cursor()
if sql:
print(f"執(zhí)行 SQL: {sql}")
exec_and_print(cursor, sql)
if sqlfile:
execute_sql_from_file(cursor, sqlfile)
cursor.close()
connection.close()
except (MySQLError, DMError) as e:
db_name = "MySQL" if db_type == "mysql" else "達(dá)夢(mèng)(DM)"
print(f"無(wú)法連接到 {db_name} 數(shù)據(jù)庫(kù)。錯(cuò)誤信息:", e)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="測(cè)試 MySQL 或 達(dá)夢(mèng)(DM) 數(shù)據(jù)庫(kù)連接并執(zhí)行 SQL")
subparsers = parser.add_subparsers(dest="db_type", required=True, help="選擇數(shù)據(jù)庫(kù)類型:mysql 或 dm")
# MySQL
mysql_parser = subparsers.add_parser("mysql", help="測(cè)試 MySQL 連接并執(zhí)行 SQL")
mysql_parser.add_argument("--host", required=True)
mysql_parser.add_argument("--port", type=int, default=3306)
mysql_parser.add_argument("--dbname")
mysql_parser.add_argument("--user", required=True)
mysql_parser.add_argument("--password", required=True)
mysql_parser.add_argument("--sql")
mysql_parser.add_argument("--sqlfile")
# DM
dm_parser = subparsers.add_parser("dm", help="測(cè)試 達(dá)夢(mèng)(DM) 連接并執(zhí)行 SQL")
dm_parser.add_argument("--host", required=True)
dm_parser.add_argument("--port", type=int, default=5236)
dm_parser.add_argument("--dbname")
dm_parser.add_argument("--user", required=True)
dm_parser.add_argument("--password", required=True)
dm_parser.add_argument("--sql")
dm_parser.add_argument("--sqlfile")
args = parser.parse_args()
test_db_connection(args.db_type, args.host, args.port, args.dbname, args.user, args.password, args.sql, args.sqlfile)
參數(shù)說(shuō)明
| 參數(shù)名 | 是否必填 | 說(shuō)明 | 默認(rèn)值 | 示例值 |
|---|---|---|---|---|
| --host | ? | 數(shù)據(jù)庫(kù)主機(jī)名或 IP | - | 192.168.1.13 |
| --port | ? | 數(shù)據(jù)庫(kù)端口 | 3306 / 5236 | 33066 |
| --dbname | ? | MySQL 庫(kù)名 / DM Schema | - | testdb |
| --user | ? | 用戶名 | - | root / SYSDBA |
| --password | ? | 密碼 | - | 123456 |
| --sql | ? | 要執(zhí)行的 SQL | - | "show databases" |
| --sqlfile | ? | SQL 文件路徑 | - | ./init.sql |
注意事項(xiàng):
--sql與--sqlfile不能同時(shí)用。- 在 DM 數(shù)據(jù)庫(kù)中,
--dbname代表 Schema 名。 - 在 MySQL 中,
--dbname可選,不寫時(shí)可以直接查詢?nèi)謹(jǐn)?shù)據(jù)。
示例用法
# 查詢 MySQL 所有數(shù)據(jù)庫(kù) python exec_sql.py mysql --host 192.168.1.13 --port 33066 --user root --password 123456 --sql "show databases" # 執(zhí)行 SQL 文件 python exec_sql.py mysql --host 127.0.0.1 --port 3306 --dbname testdb --user root --password 123456 --sqlfile ./init.sql # 查詢達(dá)夢(mèng)數(shù)據(jù)庫(kù)表 python exec_sql.py dm --host 192.168.11.72 --port 5236 --dbname datamask_web --user SYSDBA --password SYSDBA --sql "select * from job_jdbc_datasource" # 執(zhí)行達(dá)夢(mèng) SQL 文件 python exec_sql.py dm --host 192.168.11.72 --port 5236 --dbname DATAMASK_WEB --user SYSDBA --password SYSDBA --sqlfile ./init.sql
打包成可執(zhí)行文件
安裝 staticx,把 glibc 鏈接庫(kù)也打包進(jìn)去,避免環(huán)境差異:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple staticx sudo apt-get install patchelf musl-tools -y
打包:
pyinstaller -F exec_sql.py staticx dist/exec_sql dist/exec_sql_static
這時(shí) dist/exec_sql_static 就是最終的可執(zhí)行文件。
驗(yàn)證效果
運(yùn)行:
./exec_sql_static mysql --host 192.168.1.13 --port 33066 --user root --password 123456 --sql "show databases"
只要能正常打印數(shù)據(jù)庫(kù)列表,就說(shuō)明工具搞定啦
總結(jié)
通過(guò)這樣一個(gè)小工具,我們可以:
- 無(wú)需圖形化客戶端
- 跨平臺(tái)(x86 / ARM)
- 一鍵執(zhí)行 SQL 或 SQL 文件
非常適合在客戶環(huán)境下的應(yīng)急運(yùn)維場(chǎng)景!
到此這篇關(guān)于Python腳本實(shí)現(xiàn)一鍵執(zhí)行MySQL與達(dá)夢(mèng)數(shù)據(jù)庫(kù)的SQL的文章就介紹到這了,更多相關(guān)Python執(zhí)行MySQL與達(dá)夢(mèng)數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python中快速進(jìn)行多個(gè)字符替換的方法小結(jié)
最近在用python給自己的seo工作提高效率和節(jié)省時(shí)間,發(fā)現(xiàn)python真的很不錯(cuò),可以完成很多事情。多個(gè)字符替換是大家可能都會(huì)遇到的一個(gè)問(wèn)題,昨天在工作中就碰到了這么一個(gè)問(wèn)題,所以想著記錄一下解決方案及其過(guò)程,方便以后參考。下面來(lái)一起看看吧。2016-12-12
520使用Python實(shí)現(xiàn)“我愛你”表白
這篇文章主要介紹了520使用Python實(shí)現(xiàn)“我愛你”表白,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
python實(shí)現(xiàn)監(jiān)控windows服務(wù)并自動(dòng)啟動(dòng)服務(wù)示例
這篇文章主要介紹了python實(shí)現(xiàn)監(jiān)控windows服務(wù)并自動(dòng)啟動(dòng)服務(wù)示例,需要的朋友可以參考下2014-04-04
Python深度學(xué)習(xí)理解pytorch神經(jīng)網(wǎng)絡(luò)批量歸一化
這篇文章主要是Python深度學(xué)習(xí)篇,通過(guò)示例的詳解讓大家更好的理解pytorch神經(jīng)網(wǎng)絡(luò)批量歸一化,有需要的的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
PyCharm中Matplotlib繪圖不能顯示UI效果的問(wèn)題解決
這篇文章主要介紹了PyCharm中Matplotlib繪圖不能顯示UI效果的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03

