写一个简单的员工信息增删改查程序,需求如下:
当然此表你在文件存储时可以这样表示
1,Alex Li,22,13651054608,IT,2013-04-01 2,Jack Wang,28,13451024608,HR,2015-01-07 3,Rain Wang,21,13451054608,IT,2017-04-01 4,Mack Qiao,44,15653354208,Sales,2016-02-01 5,Rachel Chen,23,13351024606,IT,2013-03-16 6,Eric Liu,19,18531054602,Marketing,2012-12-01 7,Chao Zhang,21,13235324334,Administration,2011-08-08 8,Kevin Chen,22,13151054603,Sales,2013-04-01 9,Shit Wen,20,13351024602,IT,2017-07-03 10,Shanshan Du,26,13698424612,Operation,2017-07-02
1.可进行模糊查询,语法至少支持下面3种查询语法:
find name,age from staff_table where age > 22 find * from staff_table where dept = "IT" find * from staff_table where enroll_date like "2013"
2.可创建新员工纪录,以phone做唯一键(即不允许表里有手机号重复的情况),staff_id需自增
语法: add staff_table Alex Li,25,134435344,IT,2015-10-29
3.可删除指定员工信息纪录,输入员工id,即可删除
语法: del from staff_table where id=3
4.可修改员工信息,语法如下:
UPDATE staff_table SET dept="Market" WHERE dept = "IT" 把所有dept=IT的纪录的dept改成Market UPDATE staff_table SET age=25 WHERE name = "Alex Li" 把name=Alex Li的纪录的年龄改成25
5.以上每条语名执行完毕后,要显示这条语句影响了多少条纪录。 比如查询语句 就显示 查询出了多少条、修改语句就显示修改了多少条等。
----------------------------------------------------------------
----------------------------------------------------------------
标准答案:
1 # _*_coding:utf-8_*_ 2 # created by Alex Li on 10/15/17 3 from tabulate import tabulate 4 import os 5 6 STAFF_DB = "staff.db" #因为不会变,所以是常量 7 COLUMN_ORDERS = ['id','name','age','phone','dept','enrolled_date'] 8 9 10 11 def load_db(): 12 """ 13 打开db文件,把文件里的数据的每列转换成一个列表 14 1,Alex Li,22,13651054608,IT,2013-04-01 15 16 :return: 17 """ 18 staff_data = { #把文件里的每列添加到下面这些列表里 19 'id':[], 20 'name':[], 21 'age':[], 22 'phone':[], 23 'dept':[], 24 'enrolled_date':[] 25 } 26 27 28 f = open(STAFF_DB,"r",encoding="utf-8") 29 30 for line in f: 31 staff_id,name,age,phone,dept,enrolled_date = line.strip().split(',') 32 staff_data['id'].append(staff_id) 33 staff_data['name'].append(name) 34 staff_data['age'].append(age) 35 staff_data['phone'].append(phone) 36 staff_data['dept'].append(dept) 37 staff_data['enrolled_date'].append(enrolled_date) 38 39 #print(staff_data) 40 f.close() 41 return staff_data 42 43 44 def save_db(): 45 """sync data back to db each time after editing""" 46 f = open("%s_tmp"%STAFF_DB, "w", encoding="utf-8") 47 48 for index,val in enumerate(STAFF_DATA[COLUMN_ORDERS[0]]): 49 row = [str(val)] 50 for col in COLUMN_ORDERS[1:]: 51 row.append(str(STAFF_DATA[col][index]) ) 52 53 raw_row = ",".join(row) 54 f.write(raw_row+"\n") 55 f.close() 56 os.rename("%s_tmp"%STAFF_DB,STAFF_DB) 57 58 59 def print_log(msg,msg_type='info'): 60 if msg_type == 'error': 61 print("\033[31;1mError:%s\033[0m"%msg) 62 else: 63 print("\033[32;1mInfo:%s\033[0m"%msg) 64 65 66 def syntax_find(query_clause, matched_data): 67 """ 68 69 :param query_clause: eg. find age,name from staff_table 70 :param matched_data: where方法匹配到的数据 71 :return: 72 """ 73 74 filter_keys = query_clause.split('find')[1].split('from')[0] 75 columns = [i.strip() for i in filter_keys.split(',')] #要过滤出来的字段 76 if "*" in columns: 77 if len(columns) == 1: #只有find * from ...成立,*不能与其它字段同时出现 78 columns = COLUMN_ORDERS 79 else: 80 print_log("*不能同时与其它字段出现","error") 81 return False 82 if len(columns) == 1: 83 if not columns[0]: 84 print_log("语法错误,find和from之间必须跟字段名或*","error") 85 return False 86 filtered_data = [] 87 for index,val in enumerate(matched_data[columns[0]]): #拿要查找的多列的第一个元素,[name,age,dept],拿到name,到数据库匹配,然后按这一列的每个值 的索引到其它列表里依次找 88 row = [val,] 89 #if columns[1:]: #代表是多列过滤 90 for col in columns[1:]: 91 row.append(matched_data[col][index]) 92 #print("row",row) 93 filtered_data.append(row) 94 95 print(tabulate(filtered_data,headers=columns,tablefmt="grid")) 96 print_log("匹配到%s条纪录"%len(filtered_data)) 97 98 99 def syntax_add(query_clause, matched_data): 100 """ 101 sample: add staff Alex Li,25,134435344,IT,2015-10-29 102 :param query_clause: add staff Alex Li,25,134435344,IT,2015-10-29 103 :param matched_data: 104 :return: 105 """ 106 column_vals = [ col.strip() for col in query_clause.split("values")[1].split(',')] 107 #print('cols',column_vals) 108 if len(column_vals) == len(COLUMN_ORDERS[1:]): #不包含id,id是自增 109 110 #find max id first , and then plus one , becomes the id of this new record 111 init_staff_id = 0 112 for i in STAFF_DATA['id']: 113 if int(i) > init_staff_id: 114 init_staff_id = int(i) 115 116 init_staff_id += 1 #当前最大id再+1 117 STAFF_DATA['id'].append(init_staff_id) 118 for index,col in enumerate(COLUMN_ORDERS[1:]): 119 STAFF_DATA[col].append( column_vals[index] ) 120 121 else: 122 print_log("提供的字段数据不足,必须字段%s"%COLUMN_ORDERS[1:],'error') 123 124 print(tabulate(STAFF_DATA,headers=COLUMN_ORDERS)) 125 save_db() 126 print_log("成功添加1条纪录到staff_table表") 127 128 129 def syntax_update(query_clause, matched_data): 130 pass 131 132 133 def syntax_delete(query_clause, matched_data): 134 pass 135 136 def op_gt(q_name,q_condtion): 137 """ 138 find records q_name great than q_condtion 139 :param q_name: 查找条件key 140 :param q_condtion: 查找条件value 141 :return: 142 """ 143 matched_data = {} #把符合条件的数据都放这 144 for k in STAFF_DATA: 145 matched_data[k] = [] 146 147 q_condtion = float(q_condtion) 148 for index,i in enumerate(STAFF_DATA[q_name]): 149 if float(i) > q_condtion : 150 for k in matched_data: 151 matched_data[k].append( STAFF_DATA[k][index] ) #把匹配的数据都 添加到matched_data里 152 153 #print("matched:",matched_data) 154 155 return matched_data 156 157 def op_lt(): 158 """ 159 less than 160 :return: 161 """ 162 163 def op_eq(): 164 """ 165 equal 166 :return: 167 """ 168 169 def op_like(q_name,q_condtion): 170 """ 171 find records where q_name like q_condition 172 :param q_name: 查找条件key 173 :param q_condtion: 查找条件value 174 :return: 175 """ 176 matched_data = {} #把符合条件的数据都放这 177 for k in STAFF_DATA: 178 matched_data[k] = [] 179 180 for index,i in enumerate(STAFF_DATA[q_name]): 181 if q_condtion in i : 182 for k in matched_data: 183 matched_data[k].append( STAFF_DATA[k][index] ) #把匹配的数据都 添加到matched_data里 184 185 #print("matched:",matched_data) 186 187 return matched_data 188 189 def syntax_where(clause): 190 """ 191 解析where条件,并查询数据 192 :param clause: where条件 , eg. name=alex 193 :return: False or matched data dict 194 """ 195 196 query_data = {} #存储查询出来的结果 197 operators = {'>':op_gt, 198 '<':op_lt, 199 '=':op_eq, 200 'like':op_like} 201 query_condtion_matched = False #如果匹配语句都没匹配上 202 for op_key,op_func in operators.items(): 203 if op_key in clause: 204 q_name,q_condition = clause.split(op_key) 205 #print("query:",q_name,q_condition) 206 if q_name.strip() in STAFF_DATA: 207 matched_data = op_func(q_name.strip(),q_condition.strip()) #调用对应的方法 208 return matched_data 209 else: 210 print_log("字段'%s' 不存在!"%q_name,'error') 211 return False 212 213 if not query_condtion_matched: 214 print("\033[31;1mError:语句条件%s不支持\033[0m"%clause) 215 return False 216 217 218 219 220 221 222 223 def syntax_parser(cmd): 224 """ 225 解析语句 226 :return: 227 """ 228 syntax_list = { 229 'find':syntax_find, 230 'add':syntax_add, 231 'update':syntax_update, 232 'delete':syntax_delete, 233 } 234 if cmd.split()[0] in ['find','add','update','delete'] and "staff_table" in cmd : 235 236 if 'where' in cmd: 237 query_cmd,where_clause = cmd.split("where") 238 239 matched_data = syntax_where(where_clause.strip()) 240 if matched_data: #有匹配结果 241 action_name = cmd.split()[0] 242 syntax_list[action_name](query_cmd,matched_data) #调用对应的action方法 243 else: 244 syntax_list[cmd.split()[0]](cmd, STAFF_DATA) #没where,使用所有数据 245 246 247 else: 248 print_log('''语法错误!\nsample:[find/add/update/delete] name,age from [staff_table] where [id][>/</=/like][2]''','error') 249 250 251 def main(): 252 """ 253 程序主入口 254 :return: 255 """ 256 257 while True: 258 cmd = input("[staff db]:").strip() 259 if not cmd:continue 260 261 syntax_parser(cmd) 262 263 264 265 STAFF_DATA = load_db() 266 267 main()