import json
import pyodbc
import os
from datetime import datetime
class JSONToSQLServerImporter:
def __init__(self):
self.json_file_path = r"C:\sample.json"
self.connection_string = None
self.db_connection = None
def set_connection_string(self, server, database, username, password):
self.connection_string = f'DRIVER={{SQL Server}};SERVER={server};DATABASE={database};UID={username};PWD={password}'
def connect_to_database(self):
try:
self.db_connection = pyodbc.connect(self.connection_string)
print("成功连接到数据库")
return True
except pyodbc.Error as e:
print(f"数据库连接失败: {e}")
return False
def read_json_file(self, file_path=None):
"""读取JSON文件数据"""
try:
# 使用指定路径或默认路径
current_path = file_path if file_path else self.json_file_path
if not os.path.exists(current_path):
print(f"❌ JSON文件不存在: {current_path}")
print(f"📁 请将您的JSON文件放在以下位置之一:")
print(f" - Windows: C:\\sample.json")
print(f" - Mac/Linux: ~/sample.json")
print(f" - 或者在运行时指定文件路径")
# 尝试查找当前目录下的JSON文件
current_dir_files = [f for f in os.listdir('.') if f.endswith('.json')]
if current_dir_files:
print(f"\n🔍 在当前目录找到JSON文件:")
for i, json_file in enumerate(current_dir_files, 1):
print(f" {i}. {json_file}")
print(f"\n💡 提示: 您可以复制其中一个文件到指定位置,或者使用命令行参数指定文件")
return None
with open(current_path, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"✅ 成功读取JSON文件: {current_path}")
print(f"📊 共 {len(data) if isinstance(data, list) else 1} 条记录")
return data
except json.JSONDecodeError as e:
print(f"❌ JSON文件格式错误: {e}")
print(f"💡 提示: 请检查JSON格式是否正确,可以使用在线JSON验证工具")
return None
except PermissionError:
print(f"❌ 没有权限读取文件: {current_path}")
print(f"💡 提示: 请检查文件权限或使用管理员权限运行")
return None
except Exception as e:
print(f"❌ 读取JSON文件时发生错误: {e}")
return None
def create_table_if_not_exists(self, table_name, sample_data):
try:
cursor = self.db_connection.cursor()
cursor.execute(f"IF OBJECT_ID('{table_name}', 'U') IS NOT NULL SELECT 1 ELSE SELECT 0")
table_exists = cursor.fetchone()[0]
if table_exists:
print(f"表 {table_name} 已存在")
return True
columns = []
if isinstance(sample_data, dict):
for key, value in sample_data.items():
data_type = self._get_sql_data_type(value)
columns.append(f"[{key}] {data_type}")
else:
print("无法确定数据结构,需要字典类型的示例数据")
return False
columns_str = ", ".join(columns)
create_table_sql = f"CREATE TABLE {table_name} ({columns_str})"
cursor.execute(create_table_sql)
self.db_connection.commit()
print(f"成功创建表 {table_name}")
return True
except Exception as e:
print(f"创建表时发生错误: {e}")
self.db_connection.rollback()
return False
def _get_sql_data_type(self, value):
if isinstance(value, int):
return "INT"
elif isinstance(value, float):
return "FLOAT"
elif isinstance(value, str):
if self._is_datetime_string(value):
return "DATETIME"
return "NVARCHAR(MAX)"
elif isinstance(value, bool):
return "BIT"
elif isinstance(value, (list, dict)):
return "NVARCHAR(MAX)"
elif value is None:
return "NVARCHAR(MAX)"
else:
return "NVARCHAR(MAX)"
def _is_datetime_string(self, value):
if not isinstance(value, str):
return False
datetime_formats = [
"%Y-%m-%d %H:%M:%S",
"%Y-%m-%d",
"%Y/%m/%d %H:%M:%S",
"%Y/%m/%d",
"%d/%m/%Y",
"%d-%m-%Y"
]
for fmt in datetime_formats:
try:
datetime.strptime(value, fmt)
return True
except ValueError:
continue
return False
def insert_data(self, table_name, data):
try:
cursor = self.db_connection.cursor()
if isinstance(data, list):
total_records = len(data)
success_count = 0
for index, record in enumerate(data):
if self._insert_single_record(cursor, table_name, record):
success_count += 1
if (index + 1) % 10 == 0 or index + 1 == total_records:
print(f"进度: {index + 1}/{total_records} 条记录")
self.db_connection.commit()
print(f"数据插入完成,成功: {success_count}/{total_records} 条")
elif isinstance(data, dict):
if self._insert_single_record(cursor, table_name, data):
self.db_connection.commit()
print("单条记录插入成功")
else:
self.db_connection.rollback()
else:
print(f"不支持的数据格式: {type(data)}")
except Exception as e:
print(f"插入数据时发生错误: {e}")
self.db_connection.rollback()
def _insert_single_record(self, cursor, table_name, record):
try:
if not isinstance(record, dict):
return False
columns = list(record.keys())
values = list(record.values())
for i in range(len(values)):
if isinstance(values[i], (list, dict)):
values[i] = json.dumps(values[i], ensure_ascii=False)
elif values[i] is None:
values[i] = None
placeholders = ",".join(["?"] * len(values))
columns_str = ",".join([f"[{col}]" for col in columns])
sql = f"INSERT INTO {table_name} ({columns_str}) VALUES ({placeholders})"
cursor.execute(sql, values)
return True
except Exception as e:
print(f"插入单条记录时发生错误: {e}")
return False
def close_connection(self):
if self.db_connection:
self.db_connection.close()
print("数据库连接已关闭")
def run_import(self, server, database, username, password, table_name="json_data", json_file_path=None):
"""运行完整的导入流程"""
try:
print("\n🚀 开始JSON数据导入流程...")
print("-" * 60)
self.set_connection_string(server, database, username, password)
if not self.connect_to_database():
return False
# 使用指定的JSON文件路径或默认路径
data = self.read_json_file(json_file_path)
if data is None:
return False
sample_data = data[0] if isinstance(data, list) else data
if not self.create_table_if_not_exists(table_name, sample_data):
return False
self.insert_data(table_name, data)
print("JSON数据导入完成!")
return True
except Exception as e:
print(f"导入过程中发生未预期的错误: {e}")
return False
finally:
self.close_connection()
def main():
"""主函数"""
print("🚀 JSON到SQL Server数据导入工具")
print("=" * 60)
# 解析命令行参数
import sys
json_file_path = None
if len(sys.argv) > 1:
json_file_path = sys.argv[1]
print(f"📄 使用命令行指定的JSON文件: {json_file_path}")
importer = JSONToSQLServerImporter()
# 如果没有通过命令行指定文件,询问用户
if not json_file_path:
use_default = input("是否使用默认JSON文件路径?(y/n,默认y): ").lower()
if use_default != 'n':
print(f"📁 默认JSON文件路径: {importer.json_file_path}")
else:
json_file_path = input("请输入JSON文件的完整路径: ").strip()
if not json_file_path:
print("⚠️ 未指定文件路径,将使用默认路径")
print()
server = input("请输入SQL Server服务器地址: ")
database = input("请输入数据库名称: ")
username = input("请输入用户名: ")
password = input("请输入密码: ")
table_name = input("请输入表名 (默认为 json_data): ") or "json_data"
print("\n开始导入操作...")
print("=" * 50)
success = importer.run_import(server, database, username, password, table_name, json_file_path)
if success:
print("\n数据导入成功!")
else:
print("\n数据导入失败,请检查错误信息。")
if __name__ == "__main__":
main()
JSON数据一键导入SQL Server
tzjly2026-01-01 19:12