优化连接不上时创建表
This commit is contained in:
+22
-11
@@ -27,15 +27,26 @@ class DingAPI():
|
||||
return token
|
||||
|
||||
|
||||
def send_message(self, message):
|
||||
data = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": message
|
||||
def card_create(self, data):
|
||||
"""
|
||||
创建并投放卡片
|
||||
return: response(dict)
|
||||
"""
|
||||
url = 'https://api.dingtalk.com/v1.0/card/instances/createAndDeliver'
|
||||
|
||||
headers = {
|
||||
'x-acs-dingtalk-access-token': data["token"],
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
headers = {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
response = requests.post(self.url, json=data, headers=headers)
|
||||
return response.status_code
|
||||
|
||||
data = {
|
||||
"cardTemplateId": "cee2715f-001d-41cb-8fcd-3be18be9fbf5.schema",
|
||||
"outTrackId": "",
|
||||
"cardData":"",
|
||||
"openSpaceId":"dtv1.card//IM_GROUP.4210192048793363",# 场域id
|
||||
}
|
||||
response = requests.post(url, json=data, headers=headers)
|
||||
return response.json()
|
||||
|
||||
def get_
|
||||
|
||||
|
||||
@@ -153,6 +153,12 @@ class MySQLAgent:
|
||||
"""
|
||||
兼容旧接口的通用插入方法:保留replace参数,同时支持新的ignore_duplicates
|
||||
自动处理重复数据,对所有数据源通用,插入失败的数据会通过日志记录
|
||||
|
||||
安全性说明:
|
||||
- 使用 INSERT INTO(不是 REPLACE INTO 或 INSERT ... ON DUPLICATE KEY UPDATE)
|
||||
- 当 ignore_duplicates=True 时,重复记录会被跳过,不会覆盖或删除现有数据
|
||||
- 如果数据库连接失败,操作会抛出异常,不会部分成功
|
||||
- 所有操作都是安全的,不会导致数据丢失或覆盖
|
||||
"""
|
||||
# 【兼容性处理】如果未指定ignore_duplicates,用replace参数推导
|
||||
if ignore_duplicates is None:
|
||||
@@ -592,6 +598,114 @@ class MySQLAgent:
|
||||
exc_info=True)
|
||||
return False
|
||||
|
||||
def create_table_if_not_exists(self, table_name: str, create_sql: str) -> bool:
|
||||
"""
|
||||
创建表(如果不存在)
|
||||
使用 CREATE TABLE IF NOT EXISTS,不会删除已存在的表和数据
|
||||
|
||||
参数:
|
||||
table_name: 表名
|
||||
create_sql: 完整的 CREATE TABLE SQL 语句(必须包含 IF NOT EXISTS)
|
||||
|
||||
返回:
|
||||
bool: 是否成功(表已存在也会返回True)
|
||||
|
||||
注意:
|
||||
- 此方法使用 CREATE TABLE IF NOT EXISTS,是安全的,不会删除现有数据
|
||||
- 如果连接失败,会抛出异常
|
||||
"""
|
||||
if "IF NOT EXISTS" not in create_sql.upper():
|
||||
self.log.warning(f"CREATE TABLE 语句建议使用 IF NOT EXISTS 以保证安全性")
|
||||
|
||||
try:
|
||||
self.execute_sql(create_sql)
|
||||
self.log.info(f"成功创建/检查表(表已存在时不会删除数据): {table_name}")
|
||||
return True
|
||||
except Exception as e:
|
||||
self.log.error(f"创建/检查表失败(可能是数据库连接问题): {str(e)}",
|
||||
table=table_name, exc_info=True)
|
||||
raise
|
||||
|
||||
def add_unique_index_if_not_exists(self, table_name: str, index_name: str,
|
||||
column_name: str, column_length: int = 500,
|
||||
check_duplicates: bool = True) -> bool:
|
||||
"""
|
||||
添加唯一索引(如果不存在)
|
||||
不会删除数据,只添加索引
|
||||
|
||||
参数:
|
||||
table_name: 表名
|
||||
index_name: 索引名称
|
||||
column_name: 要添加索引的列名
|
||||
column_length: 索引长度(对于VARCHAR/TEXT类型)
|
||||
check_duplicates: 是否在添加索引前检查重复数据
|
||||
|
||||
返回:
|
||||
bool: 是否成功添加索引(索引已存在也会返回True)
|
||||
|
||||
注意:
|
||||
- 此方法是安全的,不会删除数据
|
||||
- 如果表中存在重复数据,会跳过添加索引(不会删除数据)
|
||||
- 如果连接失败,会抛出异常
|
||||
"""
|
||||
try:
|
||||
# 1. 检查索引是否已存在
|
||||
check_index_sql = f"""
|
||||
SELECT COUNT(*) as cnt
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE TABLE_SCHEMA = %s
|
||||
AND TABLE_NAME = %s
|
||||
AND INDEX_NAME = %s
|
||||
"""
|
||||
result = self.query_to_df(
|
||||
check_index_sql,
|
||||
params=(self.config['database'], table_name, index_name),
|
||||
is_print=False
|
||||
)
|
||||
|
||||
if not result.empty and result['cnt'].iloc[0] > 0:
|
||||
self.log.debug(f"唯一索引 {index_name} 已存在,跳过添加")
|
||||
return True
|
||||
|
||||
# 2. 如果启用重复检查,先检查是否有重复数据
|
||||
if check_duplicates:
|
||||
check_duplicates_sql = f"""
|
||||
SELECT {column_name}, COUNT(*) as cnt
|
||||
FROM `{table_name}`
|
||||
WHERE {column_name} IS NOT NULL AND {column_name} != ''
|
||||
GROUP BY {column_name}
|
||||
HAVING cnt > 1
|
||||
LIMIT 1
|
||||
"""
|
||||
duplicates = self.query_to_df(check_duplicates_sql, is_print=False)
|
||||
|
||||
if not duplicates.empty:
|
||||
self.log.warning(
|
||||
f"表 {table_name} 中存在重复的 {column_name} 数据,无法添加唯一索引。"
|
||||
"现有数据不会被删除。",
|
||||
duplicate_count=len(duplicates)
|
||||
)
|
||||
return False
|
||||
|
||||
# 3. 添加唯一索引
|
||||
add_index_sql = f"""
|
||||
ALTER TABLE `{table_name}`
|
||||
ADD UNIQUE KEY `{index_name}` ({column_name}({column_length}))
|
||||
"""
|
||||
self.execute_sql(add_index_sql)
|
||||
self.log.info(f"成功添加唯一索引 {index_name}(现有数据不受影响)")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
# 如果索引已存在,不报错
|
||||
if "Duplicate key name" in error_msg or "already exists" in error_msg.lower():
|
||||
self.log.debug(f"唯一索引 {index_name} 已存在,跳过添加")
|
||||
return True
|
||||
else:
|
||||
self.log.warning(f"添加唯一索引时出现问题(不影响现有数据): {error_msg}")
|
||||
raise
|
||||
|
||||
def execute_sql(self, sql: str, params: Union[tuple, dict, None] = None,
|
||||
fetch: bool = False) -> Union[int, List[Dict[str, Any]]]:
|
||||
"""执行SQL语句(原有逻辑完全保留)"""
|
||||
|
||||
Reference in New Issue
Block a user