利用python模拟sql语句对员工表格进行增删改查
本文主要给大家介绍了关于python模拟sql语句对员工表格进行增删改查的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍:
具体需求:
员工信息表程序,实现增删改查操作:
可进行模糊查询,语法支持下面3种:
selectname,agefromstaff_datawhereage>22 多个查询参数name,age用','分割
select*fromstaff_datawheredept=人事
select*fromstaff_datawhereenroll_datelike2013
查到的信息,打印后,最后面还要显示查到的条数
可创建新员工纪录,以phone做唯一键,phone存在即提示,staff_id需自增,添加多个记录record1/record2中间用'/'分割
insertintostaff_datavaluesrecord1/record2
可删除指定员工信息纪录,输入员工id,即可删除
deletefromstaff_datawherestaff_id>=5andstaff_id<=10
可修改员工信息,语法如下:
updatestaff_tablesetdept=Market,phone=13566677787 wheredept=运维 多个set值用','分割
使用re模块,os模块,充分使用函数精简代码,熟练使用str.split()来解析格式化字符串
由于,sql命令中的几个关键字符串有一定规律,只出现一次,并且有顺序!!!
按照key_lis=['select','insert','delete','update','from','into','set','values','where','limit']的元素顺序分割sql.
分割元素作为sql_dic字典的key放进字典中.分割后的列表为b,如果len(b)>1,说明sql字符串中含有分割元素,同时b[0]对应上一个分割元素的值,b[-1]为下一次分割对象!
这样不断迭代直到把sql按出现的所有分割元素分割完毕,但注意这里每次循环都是先分割后赋值!!!当前分割元素比如'select'对应的值,需要等到下一个分割元素
比如'from'执行分割后的列表b,其中b[0]的值才会赋值给sql_dic['select'],所以最后一个分割元素的值,不能通过上述循环来完成,必须先处理可能是最后一个分割元素,再正常循环!!
在这sql语句中,有可能成为最后一个分割元素的'limit','values','where', 按优先级别,先处理'limit',再处理'values'或'where'.....
处理完得到sql_dic后,就是你按不同命令执行,对数据文件的增删改查,最后返回处理结果!!
示例代码
#_*_coding:utf-8_*_
#Author:JayeHe
importre
importos
defsql_parse(sql,key_lis):
'''
解析sql命令字符串,按照key_lis列表里的元素分割sql得到字典形式的命令sql_dic
:paramsql:
:paramkey_lis:
:return:
'''
sql_list=[]
sql_dic={}
foriinkey_lis:
b=[j.strip()forjinsql.split(i)]
iflen(b)>1:
iflen(sql.split('limit'))>1:
sql_dic['limit']=sql.split('limit')[-1]
ifi=='where'ori=='values':
sql_dic[i]=b[-1]
ifsql_list:
sql_dic[sql_list[-1]]=b[0]
sql_list.append(i)
sql=b[-1]
else:
sql=b[0]
ifsql_dic.get('select'):
ifnotsql_dic.get('from')andnotsql_dic.get('where'):
sql_dic['from']=b[-1]
ifsql_dic.get('select'):
sql_dic['select']=sql_dic.get('select').split(',')
ifsql_dic.get('where'):
sql_dic['where']=where_parse(sql_dic.get('where'))
returnsql_dic
defwhere_parse(where):
'''
格式化where字符串为列表where_list,用'and','or','not'分割字符串
:paramwhere:
:return:
'''
casual_l=[where]
logic_key=['and','or','not']
forjinlogic_key:
foriincasual_l:
ifinotinlogic_key:
iflen(i.split(j))>1:
ele=i.split(j)
index=casual_l.index(i)
casual_l.pop(index)
casual_l.insert(index,ele[0])
casual_l.insert(index+1,j)
casual_l.insert(index+2,ele[1])
casual_l=[kforkincasual_lifk]
where_list=three_parse(casual_l,logic_key)
returnwhere_list
defthree_parse(casual_l,logic_key):
'''
处理临时列表casual_l中具体的条件,'staff_id>5'-->['staff_id','>','5']
:paramcasual_l:
:paramlogic_key:
:return:
'''
where_list=[]
foriincasual_l:
ifinotinlogic_key:
b=i.split('like')
iflen(b)>1:
b.insert(1,'like')
where_list.append(b)
else:
key=['<','=','>']
new_lis=[]
opt=''
lis=[jforjinre.split('([=<>])',i)ifj]
forkinlis:
ifkinkey:
opt+=k
else:
new_lis.append(k)
new_lis.insert(1,opt)
where_list.append(new_lis)
else:
where_list.append(i)
returnwhere_list
defsql_action(sql_dic,title):
'''
把解析好的sql_dic分发给相应函数执行处理
:paramsql_dic:
:paramtitle:
:return:
'''
key={'select':select,
'insert':insert,
'delete':delete,
'update':update}
res=[]
foriinsql_dic:
ifiinkey:
res=key[i](sql_dic,title)
returnres
defselect(sql_dic,title):
'''
处理select语句命令
:paramsql_dic:
:paramtitle:
:return:
'''
withopen('staff_data','r',encoding='utf-8')asfh:
filter_res=where_action(fh,sql_dic.get('where'),title)
limit_res=limit_action(filter_res,sql_dic.get('limit'))
search_res=search_action(limit_res,sql_dic.get('select'),title)
returnsearch_res
definsert(sql_dic,title):
'''
处理insert语句命令
:paramsql_dic:
:paramtitle:
:return:
'''
withopen('staff_data','r+',encoding='utf-8')asf:
data=f.readlines()
phone_list=[i.strip().split(',')[4]foriindata]
ins_count=0
ifnotdata:
new_id=1
else:
last=data[-1]
last_id=int(last.split(',')[0])
new_id=last_id+1
record=sql_dic.get('values').split('/')
foriinrecord:
ifi.split(',')[3]inphone_list:
print('\033[1;31m%s手机号已存在\033[0m'%i)
else:
new_record='%s,%s\n'%(str(new_id),i)
f.write(new_record)
new_id+=1
ins_count+=1
f.flush()
return['insertsuccessful'],[str(ins_count)]
defdelete(sql_dic,title):
'''
处理delete语句命令
:paramsql_dic:
:paramtitle:
:return:
'''
withopen('staff_data','r',encoding='utf-8')asr_file,\
open('staff_data_bak','w',encoding='utf-8')asw_file:
del_count=0
forlineinr_file:
dic=dict(zip(title.split(','),line.split(',')))
filter_res=logic_action(dic,sql_dic.get('where'))
ifnotfilter_res:
w_file.write(line)
else:
del_count+=1
w_file.flush()
os.remove('staff_data')
os.rename('staff_data_bak','staff_data')
return['deletesuccessful'],[str(del_count)]
defupdate(sql_dic,title):
'''
处理update语句命令
:paramsql_dic:
:paramtitle:
:return:
'''
set_l=sql_dic.get('set').strip().split(',')
set_list=[i.split('=')foriinset_l]
update_count=0
withopen('staff_data','r',encoding='utf-8')asr_file,\
open('staff_data_bak','w',encoding='utf-8')asw_file:
forlineinr_file:
dic=dict(zip(title.split(','),line.strip().split(',')))
filter_res=logic_action(dic,sql_dic.get('where'))
iffilter_res:
foriinset_list:
k=i[0]
v=i[-1]
dic[k]=v
line=[dic[i]foriintitle.split(',')]
update_count+=1
line=','.join(line)+'\n'
w_file.write(line)
w_file.flush()
os.remove('staff_data')
os.rename('staff_data_bak','staff_data')
return['updatesuccessful'],[str(update_count)]
defwhere_action(fh,where_list,title):
'''
具体处理where_list里的所有条件
:paramfh:
:paramwhere_list:
:paramtitle:
:return:
'''
res=[]
iflen(where_list)!=0:
forlineinfh:
dic=dict(zip(title.split(','),line.strip().split(',')))
ifdic['name']!='name':
logic_res=logic_action(dic,where_list)
iflogic_res:
res.append(line.strip().split(','))
else:
res=[i.split(',')foriinfh.readlines()]
returnres
pass
deflogic_action(dic,where_list):
'''
判断数据文件中每一条是否符合where_list条件
:paramdic:
:paramwhere_list:
:return:
'''
logic=[]
forexpinwhere_list:
iftype(exp)islist:
exp_k,opt,exp_v=exp
ifexp[1]=='=':
opt='=='
logical_char="'%s'%s'%s'"%(dic[exp_k],opt,exp_v)
ifopt!='like':
exp=str(eval(logical_char))
else:
ifexp_vindic[exp_k]:
exp='True'
else:
exp='False'
logic.append(exp)
res=eval(''.join(logic))
returnres
deflimit_action(filter_res,limit_l):
'''
用列表切分处理显示符合条件的数量
:paramfilter_res:
:paramlimit_l:
:return:
'''
iflimit_l:
index=int(limit_l[0])
res=filter_res[:index]
else:
res=filter_res
returnres
defsearch_action(limit_res,select_list,title):
'''
处理需要查询并显示的title和相应数据
:paramlimit_res:
:paramselect_list:
:paramtitle:
:return:
'''
res=[]
fields_list=title.split(',')
ifselect_list[0]=='*':
res=limit_res
else:
fields_list=select_list
fordatainlimit_res:
dic=dict(zip(title.split(','),data))
r_l=[]
foriinfields_list:
r_l.append((dic[i].strip()))
res.append(r_l)
returnfields_list,res
if__name__=='__main__':
withopen('staff_data','r',encoding='utf-8')asf:
title=f.readline().strip()
key_lis=['select','insert','delete','update','from','into','set','values','where','limit']
whileTrue:
sql=input('请输入sql命令,退出请输入exit:').strip()
sql=re.sub('','',sql)
iflen(sql)==0:continue
ifsql=='exit':break
sql_dict=sql_parse(sql,key_lis)
fields_list,fields_data=sql_action(sql_dict,title)
print('\033[1;33m结果如下:\033[0m')
print('-'.join(fields_list))
fordatainfields_data:
print('-'.join(data))
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。