金天牛

导航

python获取数据库字段的2种处理思路:文件处理和SQL处理

问题:接到这样一个需求,定时查数据库表table_a,table_b,table_c中的数据,当有新增的时候,把table中的新增的数据中,所有message字段发出来

解决思路一:

1.思索后,因为3个table结构一样,都有字段:id、createTime、message

觉得可以定时查询每个table中数据的个数,对查询结果进行记录,当个数有变化时,获取message并发出来。查询的时候,个别变化了,还要获取最近createTime,以方便定位message,那么把最近的createTime也需要记录,那么每个表用一行记录2个数据,不同的表逐行记录,每个获取对应内容的sql语句用列表存储

sql_number=['SELECT count(id) FROM table_a','SELECT count(id) FROM table_b','SELECT count(id) FROM table_c']
sql_last_time=['SELECT createTime FROM table_a order by createTime desc limit 1','SELECT createTime FROM table_b order by createTime desc limit 1','SELECT createTime FROM table_c order by createTime desc limit 1',]
sql_content =["SELECT message FROM table_a where createTime > '{}'","SELECT message FROM table_b where createTime > '{}'","SELECT message FROM table_c where createTime > '{}'"]

其中sql_content 中 ">'{}'" ,是为了后续方便传入存储的时间参数,以进行字符串替换

2.对字符串替换,python支持由以下3种格式:

 ① 使用%s 替换,可以替换字符串,也可以%d等,字符串后面跟%+替换内容,如果有多个参数,可以在“字符串”里面有多个 %s,“字符串”外面的%后面跟%(变量1,变量2,变量3)
sql1="delete from t_enter where vbeln='%s'"%content

②在字符串前面加f,需要替换的内容用{变量}来代替
sql2 =f"delete from t_ente_detail where vbeln='{content}'"

③字符串中间需要替换的地方用{}代替,在字符串后面加format,例如“{}{}{}”.format(变量1,变量2,变量3)
sql3="delete from t_ente_order where vbeln='{}'".format(content)

3.建立文件test.ini,用以存放第一步中说的变量:个数和createTime,中间用“逗号”隔开

4.执行sql语句,获取每一个table的个数和创建时间,其中,query_mysql()是以前封装好的查询sql的函数

new_number=[]
new_modify_time=[]
for i in range(len(sql_number)):
new_number.append(query_mysql(sql_number[i]))
new_modify_time.append(query_mysql(sql_last_time[i]))

5.定义一个函数,用来读取和写入文件test.ini。  

#new_number,new_modify_time,sql_content对应列表1,2,3
def modify_file(inputpath,lsit1,list2,list3):
try:
with open(inputpath, 'r', encoding='utf-8') as file:
file_con=file.readlines() #获取所有文件内容
print(f'the all line is {file_con}')
j=0
file_content='' #写入文件内容
for every_line in file_con:
data_line = every_line.strip("\n").split(',') #使用strip函数去除换行符,使用sqlit函数进行内容拆分,变为list
print(f'the {j} line content is {data_line}')
if int(data_line[0]) < int(lsit1[j]):
file_content=file_content+f'{lsit1[j]},{list2[j]}'+'\n' #写入文件内容,存放当前SQL表的内容个数和最后修改时间
print(list3[j].format(data_line[1]))
need_message='this is exception message '+query_mysql(list3[j].format(data_line[1])) #通过参数传递,查询发送内容,data_line[1]存放上次最后修改时间. 目前返回的是大于查询时间的第一条内容,可以修改为返回所有。
send_msg(feishu_test, '2', need_message)
logging.info(f'the send message is {need_message}')
else:
file_content = file_content+f'{data_line[0]},{data_line[1]}'+'\n' #写入文件内容,继续以前内容
j=j+1
print(f' now the {j} line content is {file_content}')

print(f'all the content is {file_content}')
with open(inputpath, 'w', encoding='utf-8') as file:
file.write(file_content) #写文件
except Exception as e:
logging.error(f"Execution failed, please check! The error content is {e}")

6.调用此函数,获取结果

if __name__ == "__main__":
modify_file('bidb.ini',new_number,new_modify_time,sql_content)

7.使用linux自带的cron或者APScheduler进行定期执行

解决思路二:

1.再经过仔细思考,既然每个table结构一致,那可以把所有的查询message结果使用sql进行合并,获取大于等于查询时间的内容。然后定期执行sql语句即可。

那么先改造SQL语句,使用union all把结果连接起来。

sql_content = "SELECT '环境1' as environment,concat(createtime,message) as message FROM  table_a where createTime >= '{}' union all SELECT '环境2' as environment ,concat(createtime,message) as message FROM  table_b where createTime >= '{}' union all SELECT '环境3' as environment ,concat(createtime,message) as message FROM  table_c where createtime >= '{}'"

2. 定义一个查询函数,执行sql语句


def message_query():
try:
time_now=(datetime.datetime.now()-datetime.timedelta(minutes=5)).strftime('%Y-%m-%d %H:%M:%S')
message = query_mysql(sql_content.format(time_now, time_now, time_now, time_now))
        if message == 'empty':                        #查询结果为空时,query_mysql()函数返回为'empty'
logging.info('There is currently no exception information!')
else:
str_message = "\n***************\n".join(map(str, message))
            #返回可为多个结果,使用join函数将字符串串联起来,string.join(iterable),string指的是所需的分隔符,iterable -任何可迭代的-列表,元组,集合等。 map()也可以使用将python列表转换为字符串
            send_msg(feishu_test, '2', str_message)
logging.info(f'Exception Information:{str_message}')
except Exception as e:
logging.error(f"Execution failed, please check! The error content is {e}")

3.调用此函数,获取结果

if __name__ == "__main__":
bidb_query()

4.使用linux自带的cron或者APScheduler进行定期执行

总结:

以上2个思路,明显思路2更加简洁方便,使用了SQL语句对结果进行串联,一次获取所需要的结果,然后再进行处理,对服务器压力也会小很多。


posted on 2023-02-08 15:50  金天牛  阅读(878)  评论(0编辑  收藏  举报