具體需求:
員工信息表程序,實現增刪改查操作:
可進行模糊查詢,語法支持下面3種:
select name,age from staff_data where age > 22 多個查詢參數name,age 用','分割
select * from staff_data where dept = 人事
select * from staff_data where enroll_date like 2013
查到的信息,打印后,最后面還要顯示查到的條數
可創建新員工紀錄,以phone做唯一鍵,phone存在即提示,staff_id需自增,添加多個記錄record1/record2中間用'/'分割
insert into staff_data values record1/record2
可刪除指定員工信息紀錄,輸入員工id,即可刪除
delete from staff_data where staff_id>=5andstaff_id<=10
可修改員工信息,語法如下:
update staff_table set dept=Market,phone=13566677787 where dept = 運維 多個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后,就是你按不同命令執行,對數據文件的增刪改查,最后返回處理結果!!
1 # _*_coding:utf-8_*_ 2 # Author:Jaye He 3 import re 4 import os 5 6 7 def sql_parse(sql, key_lis): 8 ''' 9 解析sql命令字符串,按照key_lis列表里的元素分割sql得到字典形式的命令sql_dic 10 :param sql: 11 :param key_lis: 12 :return: 13 ''' 14 sql_list = [] 15 sql_dic = {} 16 for i in key_lis: 17 b = [j.strip() for j in sql.split(i)] 18 if len(b) > 1: 19 if len(sql.split('limit')) > 1: 20 sql_dic['limit'] = sql.split('limit')[-1] 21 if i == 'where' or i == 'values': 22 sql_dic[i] = b[-1] 23 if sql_list: 24 sql_dic[sql_list[-1]] = b[0] 25 sql_list.append(i) 26 sql = b[-1] 27 else: 28 sql = b[0] 29 if sql_dic.get('select'): 30 if not sql_dic.get('from') and not sql_dic.get('where'): 31 sql_dic['from'] = b[-1] 32 if sql_dic.get('select'): 33 sql_dic['select'] = sql_dic.get('select').split(',') 34 if sql_dic.get('where'): 35 sql_dic['where'] = where_parse(sql_dic.get('where')) 36 return sql_dic 37 38 39 def where_parse(where): 40 ''' 41 格式化where字符串為列表where_list,用'and', 'or', 'not'分割字符串 42 :param where: 43 :return: 44 ''' 45 casual_l = [where] 46 logic_key = ['and', 'or', 'not'] 47 for j in logic_key: 48 for i in casual_l: 49 if i not in logic_key: 50 if len(i.split(j)) > 1: 51 ele = i.split(j) 52 index = casual_l.index(i) 53 casual_l.pop(index) 54 casual_l.insert(index, ele[0]) 55 casual_l.insert(index+1, j) 56 casual_l.insert(index+2, ele[1]) 57 casual_l = [k for k in casual_l if k] 58 where_list = three_parse(casual_l, logic_key) 59 return where_list 60 61 62 def three_parse(casual_l, logic_key): 63 ''' 64 處理臨時列表casual_l中具體的條件,'staff_id>5'-->['staff_id','>','5'] 65 :param casual_l: 66 :param logic_key: 67 :return: 68 ''' 69 where_list = [] 70 for i in casual_l: 71 if i not in logic_key: 72 b = i.split('like') 73 if len(b) > 1: 74 b.insert(1, 'like') 75 where_list.append(b) 76 else: 77 key = ['<', '=', '>'] 78 new_lis = [] 79 opt = '' 80 lis = [j for j in re.split('([=<>])', i) if j] 81 for k in lis: 82 if k in key: 83 opt += k 84 else: 85 new_lis.append(k) 86 new_lis.insert(1, opt) 87 where_list.append(new_lis) 88 else: 89 where_list.append(i) 90 return where_list 91 92 93 def sql_action(sql_dic, title): 94 ''' 95 把解析好的sql_dic分發給相應函數執行處理 96 :param sql_dic: 97 :param title: 98 :return: 99 ''' 100 key = {'select': select, 101 'insert': insert, 102 'delete': delete, 103 'update': update} 104 res = [] 105 for i in sql_dic: 106 if i in key: 107 res = key[i](sql_dic, title) 108 return res 109 110 111 def select(sql_dic, title): 112 ''' 113 處理select語句命令 114 :param sql_dic: 115 :param title: 116 :return: 117 ''' 118 with open('staff_data', 'r', encoding='utf-8') as fh: 119 filter_res = where_action(fh, sql_dic.get('where'), title) 120 limit_res = limit_action(filter_res, sql_dic.get('limit')) 121 search_res = search_action(limit_res, sql_dic.get('select'), title) 122 return search_res 123 124 125 def insert(sql_dic, title): 126 ''' 127 處理insert語句命令 128 :param sql_dic: 129 :param title: 130 :return: 131 ''' 132 with open('staff_data', 'r+', encoding='utf-8') as f: 133 data = f.readlines() 134 phone_list = [i.strip().split(',')[4] for i in data] 135 ins_count = 0 136 if not data: 137 new_id = 1 138 else: 139 last = data[-1] 140 last_id = int(last.split(',')[0]) 141 new_id = last_id+1 142 record = sql_dic.get('values').split('/') 143 for i in record: 144 if i.split(',')[3] in phone_list: 145 print('\033[1;31m%s 手機號已存在\033[0m' % i) 146 else: 147 new_record = '%s,%s\n' % (str(new_id), i) 148 f.write(new_record) 149 new_id += 1 150 ins_count += 1 151 f.flush() 152 return ['insert successful'], [str(ins_count)] 153 154 155 def delete(sql_dic, title): 156 ''' 157 處理delete語句命令 158 :param sql_dic: 159 :param title: 160 :return: 161 ''' 162 with open('staff_data', 'r', encoding='utf-8') as r_file,\ 163 open('staff_data_bak', 'w', encoding='utf-8') as w_file: 164 del_count = 0 165 for line in r_file: 166 dic = dict(zip(title.split(','), line.split(','))) 167 filter_res = logic_action(dic, sql_dic.get('where')) 168 if not filter_res: 169 w_file.write(line) 170 else: 171 del_count += 1 172 w_file.flush() 173 os.remove('staff_data') 174 os.rename('staff_data_bak', 'staff_data') 175 return ['delete successful'], [str(del_count)] 176 177 178 def update(sql_dic, title): 179 ''' 180 處理update語句命令 181 :param sql_dic: 182 :param title: 183 :return: 184 ''' 185 set_l = sql_dic.get('set').strip().split(',') 186 set_list = [i.split('=') for i in set_l] 187 update_count = 0 188 with open('staff_data', 'r', encoding='utf-8') as r_file,\ 189 open('staff_data_bak', 'w', encoding='utf-8') as w_file: 190 for line in r_file: 191 dic = dict(zip(title.split(','), line.strip().split(','))) 192 filter_res = logic_action(dic, sql_dic.get('where')) 193 if filter_res: 194 for i in set_list: 195 k = i[0] 196 v = i[-1] 197 dic[k] = v 198 line = [dic[i] for i in title.split(',')] 199 update_count += 1 200 line = ','.join(line)+'\n' 201 w_file.write(line) 202 w_file.flush() 203 os.remove('staff_data') 204 os.rename('staff_data_bak', 'staff_data') 205 return ['update successful'], [str(update_count)] 206 207 208 def where_action(fh, where_list, title): 209 ''' 210 具體處理where_list里的所有條件 211 :param fh: 212 :param where_list: 213 :param title: 214 :return: 215 ''' 216 res = [] 217 if len(where_list) != 0: 218 for line in fh: 219 dic = dict(zip(title.split(','), line.strip().split(','))) 220 if dic['name'] != 'name': 221 logic_res = logic_action(dic, where_list) 222 if logic_res: 223 res.append(line.strip().split(',')) 224 else: 225 res = [i.split(',') for i in fh.readlines()] 226 return res 227 pass 228 229 230 def logic_action(dic, where_list): 231 ''' 232 判斷數據文件中每一條是否符合where_list條件 233 :param dic: 234 :param where_list: 235 :return: 236 ''' 237 logic = [] 238 for exp in where_list: 239 if type(exp) is list: 240 exp_k, opt, exp_v = exp 241 if exp[1] == '=': 242 opt = '==' 243 logical_char = "'%s'%s'%s'" % (dic[exp_k], opt, exp_v) 244 if opt != 'like': 245 exp = str(eval(logical_char)) 246 else: 247 if exp_v in dic[exp_k]: 248 exp = 'True' 249 else: 250 exp = 'False' 251 logic.append(exp) 252 res = eval(' '.join(logic)) 253 return res 254 255 256 def limit_action(filter_res, limit_l): 257 ''' 258 用列表切分處理顯示符合條件的數量 259 :param filter_res: 260 :param limit_l: 261 :return: 262 ''' 263 if limit_l: 264 index = int(limit_l[0]) 265 res = filter_res[:index] 266 else: 267 res = filter_res 268 return res 269 270 271 def search_action(limit_res, select_list, title): 272 ''' 273 處理需要查詢並顯示的title和相應數據 274 :param limit_res: 275 :param select_list: 276 :param title: 277 :return: 278 ''' 279 res = [] 280 fields_list = title.split(',') 281 if select_list[0] == '*': 282 res = limit_res 283 else: 284 fields_list = select_list 285 for data in limit_res: 286 dic = dict(zip(title.split(','), data)) 287 r_l = [] 288 for i in fields_list: 289 r_l.append((dic[i].strip())) 290 res.append(r_l) 291 return fields_list, res 292 293 294 if __name__ == '__main__': 295 with open('staff_data', 'r', encoding='utf-8') as f: 296 title = f.readline().strip() 297 key_lis = ['select', 'insert', 'delete', 'update', 'from', 'into', 'set', 'values', 'where', 'limit'] 298 while True: 299 sql = input('請輸入sql命令,退出請輸入exit:').strip() 300 sql = re.sub(' ', '', sql) 301 if len(sql) == 0:continue 302 if sql == 'exit':break 303 sql_dict = sql_parse(sql, key_lis) 304 fields_list, fields_data = sql_action(sql_dict, title) 305 print('\033[1;33m結果如下:\033[0m') 306 print('-'.join(fields_list)) 307 for data in fields_data: 308 print('-'.join(data))