执行view_accounts()函数时触发mysql.connector.errors.InternalError: Unread result found错误的技术求助
Let's break down why you're hitting this error and how to fix it, plus a critical security improvement you should make right away.
Why the Error Happens
The "Unread result found" error pops up because you're reusing a single global database connection across multiple functions, and the login() function leaves an unprocessed result set hanging around.
In login(), you run a SELECT query, call fetchone(), but don't fully consume the entire result set or properly close the cursor before moving on to use the same connection in view_accounts(). MySQL Connector keeps track of unread results on a connection, and it blocks new queries until those results are handled.
Fix 1: Properly Handle Cursors & Results
You have two solid options here:
- Close the cursor after use in every function to clean up the result set
- Use parameterized queries with buffered cursors (which also solves another big problem we'll talk about)
Fix 2: Eliminate SQL Injection Risks
Right now, you're using f-strings to build SQL queries, which is a huge security hole—attackers can easily inject malicious SQL to steal or delete your data. Always use parameterized queries instead, where MySQL handles escaping input safely.
Modified Working Code
Here's your code with both fixes applied:
import mysql.connector as mysql def get_db_connection(): # Create a new connection per operation (simpler to avoid cursor conflicts) return mysql.connect(host="localhost", user="root", password="", database="db_iptech2") def login(username, password): conn = get_db_connection() # Use parameterized query - %s are safe placeholders sql = "SELECT * FROM tbl_account WHERE username = %s AND password = %s" mycursor = conn.cursor() mycursor.execute(sql, (username, password)) # Pass parameters as a tuple result = mycursor.fetchone() row_count = 1 if result else 0 # Check directly for a match instead of using rowcount mycursor.close() conn.close() return row_count def register(user, pw, fname, mname, lname): conn = get_db_connection() sql = "INSERT INTO tbl_account(username, password, FirstName, MiddleName, LastName) VALUES (%s, %s, %s, %s, %s)" mycursor = conn.cursor() # Pass input values safely to avoid injection mycursor.execute(sql, (user, pw, fname, mname, lname)) conn.commit() print("Successfully Registered!") mycursor.close() conn.close() def view_accounts(): conn = get_db_connection() sql2 = "SELECT * FROM tbl_account" mycursor = conn.cursor() mycursor.execute(sql2) for row in mycursor: print(row) mycursor.close() conn.close() print("(L) Login / (R) Register") question = input("Execute: ") if question == 'L': user = input("Enter username: ") password = input("Enter Password: ") x = login(user, password) if x > 0: print("Welcome to System") view_accounts() else: print("Incorrect username or Password") elif question == 'R': user = input("Enter username: ") password = input("Enter password: ") fname = input("Enter First Name: ") mname = input("Enter Middle Name: ") lname = input("Enter Last Name: ") register(user, password, fname, mname, lname)
Key Changes Explained
- Per-function database connections: Instead of a global connection, we create a new connection in each function and close it when done. This avoids conflicts between cursors and unread results entirely.
- Parameterized queries: Replaced f-string SQL building with
%splaceholders, passing input values as a tuple toexecute(). This stops SQL injection cold. - Clean cursor/connection handling: Every cursor and connection is closed after use to free up resources and prevent leftover result sets.
Alternative: Reusing a Single Connection
If you want to keep a single global connection (for performance in larger apps), modify the login() function to either:
- Close the cursor immediately after fetching the result:
def login(username, password): sql = "SELECT * FROM tbl_account WHERE username = %s AND password = %s" mycursor = conn.cursor() mycursor.execute(sql, (username, password)) result = mycursor.fetchone() row_count = 1 if result else 0 mycursor.close() # Critical: cleans up the result set return row_count - Or use a buffered cursor to load all results into memory:
mycursor = conn.cursor(buffered=True)
Either way, never use f-strings for SQL queries—always stick to parameterized inputs.
内容的提问来源于stack exchange,提问作者NOOB14




