There are several problems here.
- You can't use a placeholder for a column name. It can only be used for expressions, and the substitution will be the literal value that comes from the parameter list. If you have a variable column name you need to use ordinary string formatting; you should have a white-list to prevent SQL injection.
- Placeholders aren't replaced inside quotes.
- You have your values nested too deeply. The second argument to
c.execute() should be an iterable, and each element fills in one placeholder. search is a list of a tuple, and then you put it inside another tuple when you write (search,). So the values are nested 2 levels deep instead of being in the tuple argument.
- Default values of a function should not be calls to
input(). The default values are evaluated when the function is defined, not when it's called. So this will ask you for the inputs when you load the script, and use those same values as defaults every time the function is called.
- You call
c.fetchall() before you execute the query.
- You're missing the
for item in items: loop.
conn.commit() isn't needed after SELECT queries, only queries that modify the database. And you shouldn't call conn.close() in this function since it didn't open the connection; other functions may still need to use the connection.
def get_info(search_by=None, value=None):
valid_search_by = ['col1', 'col2', 'col3']
if search_by is None:
search_by = input("Search by: ")
if search_by not in valid_search_by:
raise ValueErr("Invalid search_by")
if value is None:
value = input("Value: ")
c.execute(f"SELECT * FROM credentials WHERE {search_by} LIKE ?", (value,))
items = c.fetchall()
for item in items:
print(f"{item[0]}", f"{item[1]}", f"{item[2]}", f"{item[3]}")
Also, there's no need to use str() in an f-string, since the formatting automatically converts the values to strings.