员工信息增删改查作业

需求:

 

自己写的:

 

"""
除了支持作业中要求的语法,模糊查询还支持 >= <= 。严格按照作业中的语法,如果不按照作业中的语法会提示相应的错误。
增:
电话号码强制输入11位手机号而且里面不能有字母,否则会提示电话号码格式不对
add staff_table Alex Li,25,13443534411,IT,2015-10-29
删:
del from staff_table where id=12
改:
UPDATE staff_table SET dept="Market" WHERE dept = "IT"
UPDATE staff_table SET age=26 WHERE name = "Alex Li"
UPDATE staff_table SET age=25 WHERE phone = 13888888888
查:
find name,age from staff_table where age > 22
find name,age from staff_table where age < 22
find name,age from staff_table where age >= 22
find name,age from staff_table where age <= 22
find * from staff_table where dept = "IT"
find name,age from staff_table where age > 22
find * from staff_table where enroll_date like "2013"
"""


def add_staff(sql_cmd, matched_data):
    staff_id = []
    staff_phone = []
    filename = ''.join(sql_cmd[1]) + '.txt'
    try:
        with open(filename, 'r', encoding='utf-8') as f:  # 把文件里的id写到staff_id = []里
            for line in f:
                if len(line) == 1:  # 如果有空行的话就跳过
                    continue
                staff_db_list = line.strip().split(',')
                staff_id.append(staff_db_list[0])
                staff_phone.append(staff_db_list[3])
    except FileNotFoundError:
        print('文件不存在,请查看输入顺序是否有误')
    else:
        for data in matched_data:
            if data in staff_phone:
                return print('号码已存在')
        new_id = str(int(staff_id[-1]) + 1)  # 把最后一个id加1作为新id
        with open(filename, 'a', encoding='utf-8') as f2:
            f2.write(
                '\n' + new_id + ',' + matched_data[0] + ',' + matched_data[1] + ',' + matched_data[2] + ',' +
                matched_data[
                    3] + ',' + matched_data[4])
        print('添加成功')


def search_staff(sql_cmd, matched_data):
    import re
    staff_info = {}
    filename = ''.join(matched_data[1]) + '.txt'
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            for line in f:
                if len(line) == 1:
                    continue
                staff_list = line.strip().split(',')
                staff_info[staff_list[0]] = {
                    'name': "\"" + staff_list[1] + "\"",
                    'age': int(staff_list[2]),
                    'phone': "\"" + staff_list[3] + "\"",
                    'dept': "\"" + staff_list[4] + "\"",
                    'enroll_date': "\"" + staff_list[5] + "\"",
                }
    except FileNotFoundError:
        print('文件不存在,请查看输入顺序是否有误')
    else:
        show_content = ''.join(matched_data[0]).split(',')  # 查找内容

        by_where = sql_cmd[0]  # 在哪搜索
        by_which = sql_cmd[1]  # 通过哪种方法匹配
        by_what = sql_cmd[2]  # 匹配内容是什么
        mached = {}
        tmp = 0  # 为了让by_what = by_what[1:-1]只执行一次
        for key in staff_info:
            if by_which.lower() == 'like':
                if tmp == 0:
                    by_what = by_what[1:-1]  # 去掉开头和结尾的双引号,如何用户不按要求输入双引号,就搜索不到想要的结果
                tmp += 1
                if re.findall(r'^"\w*(%s)+-\d+-\d+"$' % by_what, staff_info[key][by_where]):
                    mached[key] = staff_info[key]
            elif by_which == '=':
                if by_where == 'age':
                    if staff_info[key][by_where] == int(by_what):
                        mached[key] = staff_info[key]
                if staff_info[key][by_where] == by_what:
                    mached[key] = staff_info[key]
            else:
                if by_where != 'age':
                    return print('只有年龄可以比较大小')

                if by_which == '>':
                    if staff_info[key][by_where] > int(by_what):
                        mached[key] = staff_info[key]
                if by_which == '<':
                    if staff_info[key][by_where] < int(by_what):
                        mached[key] = staff_info[key]
                if by_which == '>=':
                    if staff_info[key][by_where] >= int(by_what):
                        mached[key] = staff_info[key]
                if by_which == '<=':
                    if staff_info[key][by_where] <= int(by_what):
                        mached[key] = staff_info[key]

        mached_num = len(mached.keys())  # 查到几条信息
        display_all_data = {}
        display_data = {}
        count = 0
        if '*' in show_content:
            display_all_data = mached
        else:
            for key in mached:
                for show in show_content:
                    if show in mached[key]:
                        count += 1
                        display_data[show + str(count)] = mached[key][show]
        print('共查询出了%s条记录' % mached_num)
        show_content_len = len(show_content)
        count2 = 0
        count3 = 0
        if display_all_data == {}:
            for key in display_data:
                if count2 % show_content_len == 0:  # 每len(show_content)个信息,打印一个分割线
                    count3 += 1
                    print('--------------第%s条---------------' % count3)
                count2 += 1
                print(display_data[key])
        if display_data == {}:
            for key in display_all_data:
                count3 += 1
                print('--------------第%s条---------------' % count3)
                print(mached[key]['name'])
                print(mached[key]['age'])
                print(mached[key]['phone'])
                print(mached[key]['dept'])
                print(mached[key]['enroll_date'])

        if display_all_data == {} and display_data == {}:
            return print('没有匹配的信息')


def delete_staff(filename, user_id):
    filename = filename + '.txt'
    staff_info = {}
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            for line in f:
                if len(line) == 1:
                    continue
                staff_list = line.strip().split(',')
                staff_info[staff_list[0]] = {
                    'name': staff_list[1],
                    'age': staff_list[2],
                    'phone': staff_list[3],
                    'dept': staff_list[4],
                    'enroll_date': staff_list[5].strip(),
                }

    except FileNotFoundError:
        print('文件不存在')
    else:
        id_exist = False
        for key in list(staff_info.keys()):
            if user_id == key:
                staff_info.pop(key)
                id_exist = True
        if id_exist == True:
            with open(filename, 'w', encoding='utf-8') as f2:
                for key in staff_info:
                    f2.write(
                        key + ',' + staff_info[key]['name'] + ',' + staff_info[key]['age'] + ',' + staff_info[key][
                            'phone'] + ',' + staff_info[key]['dept'] + ',' + staff_info[key]['enroll_date'] + '\n')
            print('删除成功')
        else:
            print('id不存在')


def update_staff(filename, alter_where, where_data, original_keyword, alter_keyword):
    filename = filename + '.txt'
    if alter_where.lower() != 'age' and alter_where.lower() != 'phone':
        alter_keyword = alter_keyword[1:-1]  # 去掉开头和结尾的双引号,如何用户不按要求输入双引号,就搜索不到想要的结果
    if where_data.lower() != 'age' and where_data.lower() != 'phone':
        original_keyword = original_keyword[1:-1]
    staff_info = {}
    with open(filename, 'r', encoding='utf-8') as f:
        for line in f:
            if len(line) == 1:
                continue
            staff_list = line.strip().split(',')
            staff_info[staff_list[0]] = {
                'name': staff_list[1],
                'age': staff_list[2],
                'phone': staff_list[3],
                'dept': staff_list[4],
                'enroll_date': staff_list[5],
            }
    count = 0
    for key in staff_info:
        if staff_info[key][where_data] == original_keyword:
            count += 1
            staff_info[key][alter_where] = alter_keyword

    with open(filename, 'w', encoding='utf-8') as f2:
        for key in staff_info:
            f2.write(
                key + ',' + staff_info[key]['name'] + ',' + staff_info[key]['age'] + ',' + staff_info[key][
                    'phone'] + ',' + staff_info[key]['dept'] + ',' + staff_info[key]['enroll_date'] + '\n')
    if count == 0:
        print('没有符合条件的数据')
    else:
        print('修改成功,你共修改了%s条记录' % count)


def staff_parse(cmd):
    cmd = cmd.split(' ')  # 先用空格分开
    if cmd[0].lower() == 'add':
        try:
            matched_data = cmd[2] + ' ' + cmd[3]  # 从姓名开始把增加的数据提取成一个字符串,名和姓之间有空格,如果只输入名,会没有cmd[3]就到异常处理了
            matched_data = matched_data.split(',')  # 在把数据转换成列表
            # 强制用户按顺序输入,否则从db拿电话号码查询是否重复的时候可能拿到别的数据
            if len(matched_data[2]) != 11 or not matched_data[2].isdigit():
                return print('没按顺序输入,或电话号码格式不对(请输入11位电话号码)\n'
                             '请按顺序输入add 文件名 名、姓、年龄、手机号、部门、入职日期,并用空格隔开')
            # 强制年龄按顺序输入,防止提取年龄数据查询的时候出现错误
            if len(matched_data[1]) != 2:
                return print('没按顺序输入,或年龄格式不对\n'
                             '请按顺序输入add 文件名 名、姓、年龄、手机号、部门、入职日期,并用空格隔开')

            print(
                '你要增加的是:{0},{1},{2},{3},{4}'.format(matched_data[0], matched_data[1], matched_data[2], matched_data[3],
                                                    matched_data[4], ))  # 如果输入的数据不够,就到异常处理了
        except IndexError:
            print('指令有误,请按顺序输入add 文件名 名、姓、年龄、手机号、部门、入职日期,并用空格隔开')
        else:

            sql_cmd = cmd[0:2]
            add_staff(sql_cmd, matched_data)

    elif cmd[0].lower() == 'find':
        keyword1 = ['from', 'where']
        keyword2 = ['=', '>', '<', '>=', '<=', 'like']
        try:
            # 强制用户按照正确的语法输入
            if cmd[2].lower() not in keyword1 or cmd[4] not in keyword1:
                return print('指令有误,请按顺序输入 find 查找内容 from 文件名 where 查找条件,并用空格隔开')
            if cmd[6].lower() not in keyword2:
                return print('指令有误,匹配关键词为like,>,<,=,>=,<=')
            if len(cmd) > 8:
                return print('指定有误,长度超出')
            if cmd[5].lower() == 'age' and not cmd[7].isdigit():  # 如果输入年龄的话,查找条件就必须是数字
                return print('年龄只接收整数')
            sql_cmd = cmd[5] + ' ' + cmd[6] + ' ' + cmd[7]  # 最后三个匹配条件
            matched_data = cmd[1] + ' ' + cmd[3]  # 查找内容和文件名
        except IndexError:
            print('指令有误,请按顺序输入 find 查找内容 from 文件名 where 查找条件,并用空格隔开')
        else:
            sql_cmd = sql_cmd.split(' ')
            matched_data = matched_data.split(' ')
            search_staff(sql_cmd, matched_data)
    elif cmd[0].lower() == 'del':
        keyword = ['from', 'where']
        str_id = cmd[4][0:2]  # 检验用户输入的是不是id这个关键字
        user_id = cmd[4][3:]  # 检验用户输入的是不是数字
        equal_sign = cmd[4][2]  # 检验是不是等号
        if cmd[1] not in keyword or cmd[3] not in keyword:
            return print('指令有误,请按顺序输入 del from 文件名 where id=整数,并用空格隔开')
        if str_id.lower() != 'id':
            return print('请输入关键字:id')
        if not user_id.isdigit():
            return print('请输入整数')
        if equal_sign != '=':
            return print('只支持等号')
        filename = ''.join(cmd[2])
        delete_staff(filename, user_id)
    elif cmd[0].lower() == 'update':
        keyword = ['set', 'where']
        try:
            if cmd[2].lower() not in keyword or cmd[4].lower() not in keyword:
                # 1.防止用户没输入关键词 2.如果用户没有用空格分开要修改的内容,cmd[4]就不是where,也会报错
                return print('指令有误,请按顺序输入UPDATE 文件名 SET 要修改的内容(中间不能有空格) WHERE 原内容(用空格分开),并用空格隔开')

            if cmd[6] != '=' or '=' not in cmd[3]:  # 1.防止输入其他符号 2. 如果用户如输入的最后三条内容没有空格也会报这个错误
                return print('只支持等号,或指令输入有误,请按顺序输入UPDATE 文件名 SET 要修改的内容(中间不能有空格) WHERE 原内容(用空格分开),并用空格隔开')
        except IndexError:
            return print('指令有误,请按顺序输入UPDATE 文件名 SET 要修改的内容(中间不能有空格) WHERE 原内容(用空格分开),并用空格隔开')
        else:
            search_keyword = ['name', 'age', 'phone', 'dept', 'enroll_date']
            where_data = cmd[5]  # 修改哪里的内容 关键词WHERE后面那个指定在哪符合什么条件,没有等号和原始内容
            where1_equal_index = cmd[3].index('=')
            alter_where = cmd[3][0:where1_equal_index]  # 关键词set后面指定要在哪里修改,去除掉等号和后面的修改内容
            if alter_where in search_keyword and where_data in search_keyword:
                filename = cmd[1]
                original_keyword = ' '.join(cmd[7:])  # 数据库里是这个的将被修改
                alter_keyword = cmd[3][where1_equal_index + 1:]  # 修改成什么
                update_staff(filename, alter_where, where_data, original_keyword, alter_keyword)
            else:
                return print('修改的内容不存在')
    else:
        print('指令不存在')


if __name__ == '__main__':
    def main():
        '''
        主程序入口
        :return:
        '''
        while True:
            cmd = input('please enter sql:').strip()
            if not cmd:
                continue
            if cmd.lower() == 'exit':
                return None
            else:
                staff_parse(cmd)

main()

 

讲解版本:

import os
import re
from tabulate import tabulate

DB_FILE = 'staff_table.txt'
COLUMNS = ['id', 'name', 'age', 'phone', 'dept', 'enrolled_date']


def load_db(db_file):
    data = {}
    for i in COLUMNS:
        data[i] = []
    with open(db_file, 'r', encoding='utf-8') as f:
        for line in f:
            staff_id, name, age, phone, dept, enrolled_date = line.split(',')
            data['id'].append(staff_id)
            data['name'].append(name)
            data['age'].append(age)
            data['phone'].append(phone)
            data['dept'].append(dept)
            data['enrolled_date'].append(enrolled_date)
        return data


STAFF_DATE = load_db(DB_FILE)


def save_db():
    with open('%s.new' % DB_FILE, 'w', encoding='utf-8') as f:
        for index, staff_id in enumerate(STAFF_DATE['id']):
            row = []
            for col in COLUMNS:
                row.append(STAFF_DATE[col][index])
            f.write(','.join(row))
    os.rename("%s.new" % DB_FILE, DB_FILE)


def print_log(msg, log_type='info'):
    if log_type == 'info':
        print('\033[32;1m%s\033[0m' % msg)
    elif log_type == 'error':
        print('\033[31;1m%s\033[0m' % msg)


def op_gt(column, condition):
    matched_date = []
    for index, val in enumerate(STAFF_DATE[column]):
        if float(val) > float(condition):
            record = []
            for col in COLUMNS:
                record.append(STAFF_DATE[col][index])
            matched_date.append(record)
    if matched_date == []:
        print_log('没有匹配到', 'error')
        return None
    else:
        return matched_date


def op_lt(column, condition):
    matched_date = []
    for index, val in enumerate(STAFF_DATE[column]):
        if float(val) < float(condition):
            record = []
            for col in COLUMNS:
                record.append(STAFF_DATE[col][index])
            matched_date.append(record)
    if matched_date == []:
        print_log('没有匹配到', 'error')
        return None
    else:
        return matched_date


def op_eq(column, condition):
    matched_date = []
    for index, val in enumerate(STAFF_DATE[column]):
        if val == condition:
            record = []
            for col in COLUMNS:
                record.append(STAFF_DATE[col][index])
            matched_date.append(record)
    if matched_date == []:
        print_log('没有匹配到', 'error')
        return None
    else:
        return matched_date


def op_like(column, condition):
    matched_date = []
    for index, val in enumerate(STAFF_DATE[column]):
        if condition in val:
            record = []
            for col in COLUMNS:
                record.append(STAFF_DATE[col][index])
            matched_date.append(record)
    if matched_date == []:
        print_log('没有匹配到', 'error')
        return None
    else:
        print(matched_date)
        return matched_date


def syntax_where(clause):
    operator = {
        '>': op_gt,
        '<': op_lt,
        '=': op_eq,
        'like': op_like,
    }
    parttern = re.compile('(?P<column>.+)(?P<operation>>|<|=|like+)(?P<condition>.+)')
    data = re.search(parttern, clause)
    try:
        column = data.groupdict()['column'].strip()
        operation = data.groupdict()['operation']
        condition = data.groupdict()['condition'].strip()
    except Exception:
        print_log('语法错误:where条件只能支持[>,<,=,like]', 'error')
    else:
        matched_data = operator[operation](column, condition)
        return matched_data


def syntax_find(data_set, query_clause):
    filter_cols = query_clause.split('from')[0][4:].split(',')
    filter_cols = [i.strip() for i in filter_cols]  # 干净的columns
    if '*' in filter_cols[0]:
        print(tabulate(data_set, headers=COLUMNS, tablefmt='grid'))
    else:
        reformat_data_set = []
        for row in data_set:
            filtered_vals = []
            for col in filter_cols:
                col_index = COLUMNS.index(col)
                filtered_vals.append(row[col_index])
            reformat_data_set.append(filtered_vals)

        print(tabulate(reformat_data_set, headers=filter_cols, tablefmt='grid'))
        print_log('匹配到%s条数据' % len(data_set))


def syntax_delete(data_set):
    staff_id = int(data_set[0][0]) - 1  # 获取id ,列表是从0开始数,所以减1

    for data in list(STAFF_DATE.keys()):
        STAFF_DATE[data].pop(staff_id)

    save_db()
    print_log('删除成功')


def syntax_update(data_set, query_clause):
    need_set_row = query_clause.split('set')
    if len(need_set_row) > 1:
        col_name, new_val = need_set_row[1].strip().split('=')  # age = 25
        col_index = COLUMNS.index(col_name)
        # 循环data_set,取到每条记录的id,拿着这个id到STAFF_DATE['id]里找对应的id的索引,找到之后,再拿这个索引,去STAFF_DATA['age']列表里,改对应索引的值

        for mached_row in data_set:
            staff_id = mached_row[0]
            staff_id_index = STAFF_DATE['id'].index(staff_id)
            STAFF_DATE[col_name][staff_id_index] = new_val
        print(STAFF_DATE)

        save_db()
        print_log('成功修改了%s条数据' % len(data_set))


    else:
        print_log('语法错误:未检测到set关键字!', 'error')


def syntax_add(query_clause):  # add staff_table Alex Bai,25,13451054622,Market,2016‐01-11
    query_clause = query_clause.split(',')  # 转成列表
    name = ' '.join(query_clause[0].split(' ')[2:])  # 提取出名字
    query_clause[0] = name  # 把 add staff_table 换成名字
    new_id = len(STAFF_DATE['id']) + 1
    query_clause.insert(0, str(new_id))  # 加上id 只剩添加内容了
    last_data = query_clause[-1]
    last_data = last_data + '\n'  # 给最后一个元素加上换行符
    query_clause[-1] = last_data

    for index, cow in enumerate(COLUMNS):
        if len(query_clause[index]) == 11 and query_clause[index] in STAFF_DATE[cow]:
            print_log('电话号码不能重复', 'error')
            return None
        STAFF_DATE[cow].append(query_clause[index])

    save_db()
    print_log('添加成功')


def syntax_parser(cmd):
    # find name,age from staff_table where age > 22

    syntax_list = {
        'find': syntax_find,
        'del': syntax_delete,
        'update': syntax_update,
        'add': syntax_add,

    }

    if cmd.split()[0].lower() in ('find', 'add', 'del', 'update'):

        if 'where' in cmd:
            query_clause, where_clause = cmd.split('where')
            matched_record = syntax_where(where_clause)
        elif 'WHERE' in cmd:
            query_clause, where_clause = cmd.split('WHERE')
            matched_record = syntax_where(where_clause)


        else:
            matched_record = []  # add staff_table Alex Li,25,134435344,IT,2015‐10‐29
            for index, staff_id in enumerate(STAFF_DATE['id']):
                record = []
                for cow in COLUMNS:
                    record.append(STAFF_DATE[cow][index])
                matched_record.append(record)
            query_clause = cmd

        cmd_action = cmd.split()[0].lower()

        if cmd_action in syntax_list:

            if cmd_action == 'add':
                syntax_list[cmd_action](query_clause)
            elif cmd_action == 'del':
                syntax_list[cmd_action](matched_record)
            else:
                syntax_list[cmd_action](matched_record, query_clause)
    else:
        print_log('语法错误:[find\\add\del\\update] [column1,...] from [staff_table] [where] [column] [>,..] [condition]',
                  'error')


def main():
    while True:
        cmd = input('[staff_db]:').strip()
        if not cmd: continue

        syntax_parser(cmd)


main()

# FIND name,age from staff_table WHERE age > 22

# find * from staff_table where age > 22

# update staff_table set dept=Market where dept = IT

# UPDATE staff_table set dept=技术部 where name=Alex Li

# UPDATE staff_table set dept=开发部 where dept=技术部

 

 

posted @ 2018-11-23 11:03  梁少华  阅读(492)  评论(0编辑  收藏  举报