python写sql语句_python模拟SQL语句操作文件

news/2024/7/7 15:58:52

1.需求

在文本界面输入SQL语句,查询相应的数据,例如输入下面的语句

print('''支持大小写的SQL语句查询,大写或者小写都可以

1. select * from db1.emp

2. select * from db1.emp limit 4

3. select * from db1.emp where id > 24

4. select * from db1.emp where name like 李

5. select * from db1.emp where id > 10 and id <14 or name like 李

6. SELECT * from db1.emp where not id > 24

7. INSERT into db1.emp values 张国辉,30,18676575678,运维,2007-8-1

8. delete from db1.emp where id > 25

9. update db1.emp set name='sb' where id=24

10.update db1.emp set name='alex' where name like sb''')#db1.emp是一个数据库,名字随便取,只要能找到这个值就行

开始分析整个需求

1.根据输入的语句实现数据库中的增删改查,四个操作

①.语句解析select, insert ,update,delete

②.四种语句解析做的工作类似,抽取一个函数专门解析

def handle_sql_parse(sql_l,sql_dic){}

解析完成之后返回解析的语句,在分发给对应的函数

③.拿到解析的SQL语句,调起相对应的函数(insert,delete,update,select),查询语句

④.返回查询到的结果,输出打印。

2.具体业务实现

1.入口函数

if __name__ == "__main__":whileTrue:print('''支持大小写的SQL语句查询,大写或者小写都可以

1. select * from db1.emp

2. select * from db1.emp limit 4

3. select * from db1.emp where id > 24

4. select * from db1.emp where name like 李

5. select * from db1.emp where id > 10 and id <14 or name like 李

6. select * from db1.emp where not id > 24

7. insert into db1.emp values 张国辉,30,18676575678,运维,2007-8-1

8. delete from db1.emp where id > 25

9. update db1.emp set name='sb' where id=24

10.update db1.emp set name='alex' where name like sb''')

sql= input('sql>>:').strip()if sql == 'exit' or sql == 'q':break

if len(sql) == 0:continue

#开始解析sql语句

sql_dic =sql_parse(sql)print(sql_dic)#拿到处理好的sql语句开始查询

result =sql_action(sql_dic)print('*'*30 + '查询结果' + '*'*30)for value in result[-1]:print(value)print('*'*30 + '查询完毕' + '*'*30)

2.根据select,insert,update,delete,四种语句进行分发,分别处理语句

defsql_parse(sql):'''输入sql语句,根据关键字拿到处理的函数,传入sql语句解析

:param sql:

:return:'''func_dict={'insert':insert_sql_parse,'delete':delete_sql_parse,'update':update_sql_parse,'select':selete_sql_parse

}#将sql语句以空格为界转化为一个列表

sql_l = sql.split(' ')#获取列表中的第一个值即为字典对应的key,命令可能为大写,全部转化为小写去执行

sql_order =sql_l[0].lower()

sql_result= ''

if sql_order infunc_dict:

sql_result=func_dict[sql_order](sql_l)return sql_result

3.具体的select,insert,update,delete四种方式对应的函数

definsert_sql_parse(sql_l):'''insert语句,定义语法规则字典传入给语句解析函数

:param sql_l:

:return:'''

#insert_action 定义的处理insert SQL语句的函数,

sql_dic ={'func': insert_action,'insert': [],'into': [],'values': [],

}returnhandle_sql_parse(sql_l, sql_dic)defdelete_sql_parse(sql_l):'''delete语句,定义语法规则字典传入给语句解析函数

:param sql_l:

:return:'''sql_dic={'func': delete_action,'delete': [],'from': [],'where': [],

}returnhandle_sql_parse(sql_l, sql_dic)defupdate_sql_parse(sql_l):'''update语句,定义语法规则字典传入给语句解析函数

:param sql_l:

:return:'''sql_dic={'func': update_action,'update': [],'set': [],'where': [],

}returnhandle_sql_parse(sql_l, sql_dic)defselect_sql_parse(sql_l):'''select语句,定义语法规则字典传入给语句解析函数

:param sql_l:

:return:'''sql_dic={'func':select_action,'select': [],'from': [],'where': [],'limit': [],

}return handle_sql_parse(sql_l,sql_dic)

4.四种语句有共同性,用一个handle函数统一处理返回处理后的sql语句,而且考虑到where后面的运算符处理,我们把逻辑处理的部分在拿出来封装一个函数去处理

defhandle_sql_parse(sql_l,sql_dic):'''执行sql解析操作,返回sql_dic

:param sql:

:param sql_dic:

:return:

参考字典

sql_dic = {

'func':select_action,

'select': [],

'from': [],

'where': [],

'limit': [],

}'''tag=Falsefor item insql_l:#对应的key都转换为小写

item =item.lower()#如果列表中的值和key对应,并且标志位也是true ,就把标志位置反

if tag and item insql_dic:

tag=False#如果列表中的值和key对应,并且标志位也是false ,就把标志位置反,把对用的item赋值给key

if not tag and item insql_dic:

tag=True

key=itemcontinue

iftag:#标识为true 就把对应的item放到上次循环中对应的key中

#根据上一步的item 在字典中取出对应的列表添加元素

#以select为例,输入select * from db1.emp where id > 24

#返回{'func': , 'select': ['*'], 'from': ['db1.emp'], 'where': ['id', '>', '24'], 'limit': []}

sql_dic[key].append(item)if sql_dic.get('where'):#单独处理where,返回之后的字典,就是把where中的比较字符每一个条件处理成了一个数组

#{'func': < function select_action at 0x102ecf598 >, 'select': ['*'], 'from': ['db1.emp'], 'where': [['id', '>', '24']], 'limit': []}

sql_dic['where'] = sql_where_parse(sql_dic.get('where'))return sql_dic

5.单独对where语句和其中的逻辑运算语句的处理

defsql_where_parse(sql_where_l):'''处理where语句 : ['id', '>', '10', 'and', 'id', '<14', 'or', 'name', 'like', '李']

:param sql_where_l:

:return:'''result=[]

key= ['and','or','not']

char= '' #拼接字符显示

for value insql_where_l:if len(value) == 0:continue

#如果是逻辑运算

if value inkey:if len(char) !=0:

char=logic_parse(char)

result.append(char)

result.append(value)

char= '' #每次都清空

else:#先处理 and or not 这个三个特殊的逻辑运算符,例如上面的例子中,先把id>10作为一个整体放入char中,遍历到and的时候再对char处理

#调用logic_parse()函数进行处理,将id>10处理为一个列表['id','>','10'],将列表添加到外围的列表中,同时添加逻辑运算符,清空char

#再次运行

char+=valueelse:#处理最后一个char字符,变为列表

char =logic_parse(char)

result.append(char)return result

6.逻辑运算符的解析

deflogic_parse(logic_str):'''对where中的逻辑运算做处理,返回一个字典,将一个小的条件过滤

例如 age>10 转换成 ['age','>','10']

:param login_str:

:return:'''key= ['>','<','=']

result=[]

char= '' #拼接运算符

flag = False #添加的标识位

option = '' #记录是否是运算符

for value inlogic_str:#age>10,类似于这样的字符串,逐个处理,如果不是运算符,就拼接字符,直到是运算符为止,

#将字符添加到数组中,再次判断是否是运算符,拼接运算符,如果不是运算符 就将运算符也添加到数组中,依次循环

if value inkey:

flag=Trueif len(char) !=0:

result.append(char)

char= ''option+=valueif notflag:

char+=valueif flag and value not inkey:

flag=False

result.append(option)

option= ''char+=valueelse:

result.append(char)#添加对like的解析

if len(result) == 1:#以like为分割线,转化为数组,

result = result[0].split('like')#在中间位置添加like

result.insert(1,'like')return result

7.在入口函数中拿到解析后的sql语句,开始执行对应的select,update,delete,insert语句,对这个语句做一个分发的操作

defsql_action(sql_dic):'''字典中提取命令 分发给对应的具体指令去执行

:param sql_dic:

:return:

根据传入的字典,调用对用的方法,

sql_dic = {

'func':select_action,

'select': [],

'from': [],

'where': [],

'limit': [],

}'''

return sql_dic.get('func')(sql_dic)

8.编写对应的insert,select,update,insert等语句开始执行

defselect_action(sql_dic):'''执行select 语句

:param sql_dic:

:return:'''

#解析路径

if '.' in sql_dic['from'][0]:

file_path= sql_dic['from'][0].replace('.','/')else:

file_path= sql_dic['from'][0]#print(path,table)

filehandle= open(file_path,'r',encoding='utf-8')#分别去解析where limit 还要对比显示文字

where_resutl = where_action(filehandle,sql_dic['where'])

filehandle.close()#print(where_resutl)

#添加limit操作

limit_result = limit_action(where_resutl,sql_dic['limit'])#根据搜索添加结果

search_result = search_action(limit_result,sql_dic['select'])return search_result

9.根据解析后的sql语句 还需要对相应的where字符做处理,添加对应的where和limit,最后加上select的处理

defwhere_action(filehandler,whele_sql):'''解析where语句,显示where语句中的执行条件

:param filehandler: 文件句柄

:param whele_sql:

:return:'''result=[]

titles= 'id,name,age,phone,dept,enroll_data'.split(',')if len(whele_sql) !=0:for line infilehandler:#zip 转化为一个元祖,如果两个队列长度不一致,以短的返回一个元祖

#tem_dict={'id': '1', 'name': '姬建明', 'age': '25', 'phone': '15201541043', 'dept': '运维', 'enroll_data': '2013-11-01\n'}

tem_dic = dict(zip(titles,line.split(',')))#处理逻辑运算符中的数据

logic_res =logic_action(tem_dic,whele_sql)#返回为true的时候,添加数据到列表中

iflogic_res:

result.append(line.split(','))else:returnfilehandler.readlines()returnresultdeflogic_action(dic,where_sql):'''根据字典和sql语句进行匹配,匹配成功返回true 匹配失败返回false

:param dic:

:param where_sql:

:return:'''

#[['id', '>', '10'], 'and', ['id', '<', '14'], 'or', ['name', 'like', '李']]

result =[]for item inwhere_sql:#过滤掉and or not 等逻辑运算符

if type(item) islist:#print(item,dic)

prop,option,value =item#如果option为= 在后面在拼接一个=

if option == '=':

option+='='

#判断是否是数字

ifdic[prop].isdigit():

dic_v=int(dic[prop])

value=int(value)else:

dic_v= '%s' %dic[prop]if option != 'like':#将字符串str当成有效的表达式来求值并返回计算结果

flag = str(eval("%s%s%s" %(dic_v,option,value)))else:if value indic_v:

flag= 'True'

else:

flag= 'False'

#拼接每一个匹配的值,

result.append(flag)#添加and进行连接

result.append('and')#删除最后一个and

result.pop()#计算数组中的表达式的值

res = eval(' '.join(result))#将result中的bool值进行处理,并计算所有bool值的最后结果

return res

10.添加limit处理

deflimit_action(where_res,limit_l):'''根据用户输入的limit 返回limit的个数的数组

:param where_res:

:param limit_l:

:return:'''

#根据传入的limit 做一个切片处理

if len(limit_l) !=0:returnwhere_res[0:int(limit_l[0])]else:return where_res

11.处理select中除了*之外的其他字符 select id name IT from*****. 语句只返回id name IT这个三个属性

defsearch_action(limit_res,select_l):'''根据用户的输入,返回特定的数组

:param limit_res:

:param select_l:

:return:'''result=[]

fileds_l=[]

titles= 'id,name,age,phone,dept,enroll_data'.split(',')if select_l[0] == "*":

fileds_l=titles

result=limit_reselse:#循环匹配where和limit语句的执行结果

for item inlimit_res:#zip 转化为一个元祖,如果两个队列长度不一致,以短的返回一个元祖

#{'id': '25', 'name': '张国辉', 'age': '30', 'phone': '18500841678', 'dept': '运维', 'enroll_data': '2007-8-1\n'}

temp_dict =dict(zip(titles,item))

condition_l=[]

fileds_l=select_lfor i infileds_l:

condition_l.append(temp_dict[i].strip())

result.append(condition_l)#只返回搜索的字段名

return (fileds_l,result)

12.删除操作delete

defdelete_action(sql_dic):'''删除表中的元素,返回删除成功标识

:param sql_dic:

:return:'''

#'func': delete_action,

#'delete': [],

#'from': [],

#'where': [],

if '.' in sql_dic['from'][0]:

file_path= sql_dic['from'][0].replace('.','/')else:

file_path= sql_dic['from'][0]

titles= "id,name,age,phone,dept,enroll_date".split(',')#创建一个临时文件复制指定文件的内容,完成之后,删除源文件,修改临时文件的名称

with open(file_path,'r',encoding='utf-8') as r_obj,\

open("%s.txt" %file_path,'w',encoding='utf-8') as w_obj:for item inr_obj:

tem_dic= dict(zip(titles,item.split(',')))

flag= logic_action(tem_dic,sql_dic['where'])if notflag:

w_obj.write(item)

w_obj.flush()#立刻从内存刷到硬盘上

os.remove(file_path)

os.rename("%s.txt" %file_path,file_path)return [['删除成功']]

13.更新操作update

defupdate_action(sql_dic):'''更新对应的数据

'func': update_action,

'update': [],

'set': [],

'where': [],

:param sql_dic:

:return:'''

if '.' in sql_dic['update'][0]:

file_path= sql_dic['update'][0].replace('.','/')else:

file_path= sql_dic['update'][0]

set_sql= sql_dic['set'][0].split(',')

sets=[]for value inset_sql:

sets.append(value.split('='))

titles= "id,name,age,phone,dept,enroll_date".split(',')

with open(file_path,'r',encoding='utf-8') as r_obj,\

open('%s.txt' %file_path,'w',encoding='utf-8') as w_obj:#遍历文件内容

for item inr_obj:

changeline=[]#将每组数据格式化为一个字典

temp_dic = dict(zip(titles,item.split(',')))#匹配字典中的值是否和where语句中的值相同

flag = logic_action(temp_dic,sql_dic['where'])ifflag:#在数据库中存在这个数据,拿到数据修改为要设置的值

for set insets:

k=set[0]

v= set[-1].strip("'")

temp_dic[k]=vfor prop intitles:

changeline.append(temp_dic[prop])#数组转化为字符串,保存到文件中

w_obj.write(','.join(changeline))

w_obj.flush()

os.remove(file_path)

os.rename("%s.txt" %file_path, file_path)return [['修改成功']]

14.insert插入操作

definsert_action(sql_dic):''''func': insert_action,

'insert': [],

'into': [],

'values': [],

插入新的元素,先要获取最后一行的数据,获取到他的ID,自增长ID

:param sql_dic:

:return:'''

if '.' in sql_dic['into'][0]:

file_path= sql_dic['into'][0].replace('.','/')else:

file_path= sql_dic['into'][0]print(file_path)

titles= "id,name,age,phone,dept,enroll_date".split(',')

with open(file_path,'ab+') as f_obj:#查询文件的最后一行

offset = -50

whileTrue:#seek(offset,可选值) 可选值默认为0 从文件开头算 1 从当前位置开始算 2从文件末尾算

f_obj.seek(offset,2)

lines=f_obj.readlines()if len(lines) > 1:

last_line= lines[-1]breakoffset*= 2

#以二进制打开的文件,要对字符串解码

last_line = last_line.decode(encoding='utf-8')#取出最后一行的ID

temp_dict = dict(zip(titles,last_line.split(',')))

last_id= int(temp_dict['id'])#id加一 添加到数组中

add_info = sql_dic['values']

add_info.insert(0,str(last_id+1))#数组转化为字符串

new_line = ','.join(add_info) + '\n'f_obj.write(new_line.encode('utf-8'))

f_obj.flush()return [['添加成功']]

因为添加的数据库格式固定了,还可以添加不知道字段名的数据库进行操作,全局修改titles这个数组来匹配所有的字段名,也可以手动输入,在进行解析,实现一个多个字段可用的SQL查询小工具


http://www.niftyadmin.cn/n/3661356.html

相关文章

【计算机毕业设计】基于微信小程序的大学生心理测评系统

毕设帮助、源码获取、技术答疑&#xff0c;联系见文末。 一.前言 心理测评系统是通过科学、客观、标准的测量手段对人的特定素质进行测量、分析、评价的一种系统工具&#xff0c;它可以从智力、能力倾向、创造力、人格、心理健康等各方面对个体进行全面的描述&#xff0c;说明…

[领域]当Party就是PartyRole会这样

2006年05月24日 13:47:00 这是partech的blog的内容&#xff0c;我想我对这个问题应该算是小有研究&#xff0c;拿出来供大家参考。首先要说明的是PartyRole和Party到底都是什么&#xff1f;PartyRole&#xff0c;简而言之&#xff0c;就是角色&#xff08;可能是人的角色&#…

2022~2023计算机毕业设计选题篇-选题推荐

Hi&#xff0c;大家好&#xff0c;这里是一点毕设&#xff0c;一年一度的计算机专业毕业设计又要开始了&#xff0c;大四的同学们准备好选题了吗? 先介绍一下自己, 本人在大学毕业那年&#xff0c;曾经有幸协助指导老师做过毕业设计课题分类、论文初选、代码刻录等打杂的工作&…

查看数值类型python_Python数据类型完整大全,让你看的明白

计算机程序&#xff0c;就是对数据进行操作。无论你学习那种语言开发&#xff0c;都需要学习具体的数据类型&#xff0c;每种开发语言都有自己不同数据类型。 下面是针对python语言的全部数据类型详细汇总&#xff1a; Python中可以自定义数据类型,可以具有无限种数据类型。 系…

android looper_Android面试笔试总结(Android精心整理篇)

Activity中的几种启动模式activity的几种启动模式是android中常考的知识点&#xff0c;一般会考察有哪几种启动模式&#xff0c;以及每种启动模式在什么场景下使用&#xff1a;standard:这个是android默认的Activity启动模式&#xff0c;每启动一个Activity都会被实例化一个Act…

Put it into a Context!(写作中)

2004年08月19日 00:08:00 Put it into a Context&#xff01;图说用例粒度问题作为一个用例技术的使用者&#xff0c;我想强调一下&#xff0c;本文的假设前提是&#xff1a;你已经非常清晰的认识到需求工作的重要性&#xff0c;并且清楚的了解我们需求工作中存在的问题&#x…

写在周日的凌晨( 一次思维的对话)

2004年08月02日 09:19:00 写在周日的凌晨一次思维的对话sunshineormermsn.com孙向晖看看时间,已经是周日了,也就是说,作为周六,昨天已经过去了。 昨天,开例会的时候,跟人吵架了。原因很简单,因为大家都是牛人 ^*_*^。 这确实不是我的初衷,我相信也不是他的初衷。引发争吵的根本…

python地图疫情_用 Python 撸一个全国疫情地图,其实一点都不难

响应号召&#xff0c;宅在家里。修修小技术&#xff0c;水水小代码。加油&#xff01;热干面&#xff01;首先我们假设Python的基本环境已经搭建好了&#xff0c;Lets begin。一、爬取数据1)安装常用的python爬虫工具&#xff1a;beautifulsoup4、requestspip install requests…