Python程序按姓名查询SQL数据库无结果输出的问题排查求助
问题诊断与修复方案
嘿,我帮你找到了按姓名查询时程序直接终止的核心原因,还有对应的修复方案:
1. 最直接的崩溃元凶:SQL语法错误(字符串拼接坑)
你现在用字符串拼接的方式构建姓名查询的SQL语句,这会导致两个问题:
- 如果用户输入的姓名包含单引号(比如
O'Conner),拼接后的SQL会出现语法错误,数据库执行失败,而你的代码没捕获这个异常,程序直接崩了。比如输入O'Neil,拼接后的SQL会变成:
这里的单引号把语句提前闭合,剩下的SELECT ... WHERE C.Fname = '' AND C.Lname = 'O'Neil'Neil'完全是无效语法,数据库直接报错,程序就终止了。 - 这种写法还存在SQL注入风险,属于不安全的编码方式。
2. 缺少异常兜底逻辑
和按ID查询的代码不同,姓名查询的部分没有try-except块,任何执行错误(比如上面的语法错、数据库临时断开)都会直接终止程序,连错误提示都没有。
3. 可选优化:空白输入的逻辑不符合预期
你允许用户按回车留空名字,但当前的SQL会查询Fname = ''的用户,这显然不是“留空表示不限制该条件”的本意吧?
修复后的完整代码
下面是修复了所有问题的代码,同时保留了你原来的功能逻辑:
while True: # 循环验证用户输入合法性 ui = input("Would you like to lookup the customer by Customer ID (1) or Name (2)? >") try: ui = int(ui) if ui in (1, 2): break else: print("Please enter either 1 or 2 to make a selection.") except ValueError: # 精准捕获字符串转整数的错误,不用裸except print("Invalid selection. Please enter a number.") if ui == 1: while True: cid = input("What is the Customer ID? >") try: cid = int(cid) # 这里也改成参数化查询,避免潜在风险 query = """ SELECT C.CustID, C.Fname, C.Lname, C.Gender, C.CustState, U.Population FROM Customer C INNER JOIN USState U ON C.CustState = U.StateID WHERE C.CustID = %s """ cursor.execute(query, (cid,)) # 参数化传入值,避免拼接问题 results = cursor.fetchall() if not results: print("No customer found with this ID.") for x in results: print("Customer ID: %d, First Name: %s, Last Name: %s, Gender: %s, State: %s, State Population: %d." % (x[0], x[1], x[2], x[3], x[4], x[5])) break except ValueError: print("Please enter an integer for Customer ID.") except Exception as e: # 捕获数据库相关错误,给出提示 print(f"Error querying database: {str(e)}") elif ui == 2: while True: try: fname = input("What is the customer's first name? (press enter for blank) >").strip() lname = input("What is the customer's last name? (press enter for blank) >").strip() # 动态构建查询条件,处理空白输入 conditions = [] params = [] if fname: conditions.append("C.Fname = %s") params.append(fname) if lname: conditions.append("C.Lname = %s") params.append(lname) if not conditions: print("Please enter at least first name or last name.") continue query = f""" SELECT C.CustID, C.Fname, C.Lname, C.Gender, C.CustState, U.Population FROM Customer C INNER JOIN USState U ON C.CustState = U.StateID WHERE {' AND '.join(conditions)} """ cursor.execute(query, params) # 参数化查询,彻底解决语法错误和注入风险 results = cursor.fetchall() if not results: print("No customers found matching the entered name(s).") for x in results: print("Customer ID: %d, First Name: %s, Last Name: %s, Gender: %s, State: %s, State Population: %d." % (x[0], x[1], x[2], x[3], x[4], x[5])) break except Exception as e: print(f"Error querying database: {str(e)}")
关键修复点说明
- 参数化查询:所有SQL都用
cursor.execute(query, params)的方式,把查询值作为参数传入,彻底避免了字符串拼接带来的语法错误和SQL注入风险,这是数据库操作的最佳实践。 - 精准异常捕获:用
ValueError处理输入转整数的错误,用Exception捕获数据库相关错误,出错时会给出明确提示,不会直接终止程序。 - 空白输入处理:动态构建WHERE条件,如果用户留空姓名,就不会加入该条件,符合“留空表示不限制”的预期,还加了“至少输入一个姓名”的验证。
- 空结果提示:当没有查询到匹配结果时,会明确告知用户,而不是什么都不输出,提升用户体验。
内容的提问来源于stack exchange,提问作者jprism
相关产品推荐
相关产品推荐

