简体   繁体   中英

Python Sqlite3 - Using f strings for update database function

I have my own personal database I made for fun (so not that concerned with sql injections as its my own private database I made) and am trying to change the functions I created that use string formatting (.format()) and placeholders (?, %s, etc) and use f strings instead. I ran into a problem where one of my functions that updates a specified column into a specified row won't run now that I changed the sqlite3 query to f strings.

This is my current function using f strings:

import sqlite3
from tabulate import tabulate
conn = sqlite3.connect("Table.db")
c = conn.cursor()

def updatedb(Column, Info, IdNum):  
    with conn:
        data = c.execute(f"UPDATE Table_name SET {Column} = {Info} WHERE IdNum={IdNum}")
        c.execute(f"SELECT * FROM Table_name WHERE IdNum = {IdNum}")
    print(tabulate(data, headers="keys", tablefmt="grid", stralign='center', numalign='center'))

The function updates the table by updating a specified column of a specified row with the new info you want in that column. For example in a 3 x 3 table, instead of row 1, column 2 being 17, I can use the function to update row 1, column 2 to 18 if that column is an age or something. The select query after that is to just select that particular row that was updated and the print statement after that uses the tabulate package to print out a neat and organized table.

The error I get whenever I try to use this function is:

sqlite3.OperationalError: no such column: Info

Whatever I type in for the Info variable in the function is what the error becomes but I can't figure out how to fix the problem.

This is the update statement I had before attempting to change to f strings and it worked fine for me:

data = c.execute("UPDATE Table_name SET {} = ? WHERE IdNum=?".format(Column), (Info, IdNum))

It didn't seem like to would be that big of a change to change the above query to af string but it isn't working so any feedback would be appreciated.

The problem here is understanding parameterization - it works only for parameters, not for column names and other stuff.

in this example:

 query = 'SELECT * FROM foo WHERE bar = ? AND baz = ?'
 params = (a, b)
 cursor.execute(query, params)

Note that the query and the data are passed separately to .execute - it is the database's job to do the interpolation - that frees you from quote hell, and makes your program safer by disabling any kind of sql injection. It also could perform better - it allows the database to cache the compiled query and use it when you change parameters.

Now that only works for data . If you want to have the actual column name in a variable, you have to interpolate it yourself in the query:

 col1 = 'bar'
 col2 = 'baz'
 query = f'SELECT * FROM foo WHERE {col1} = ? AND {col2} = ?'
 cursor.execute(query, params)

Parameterization and string substitution are two very different things.

At the most basic level, your problem is that string substitution is producing a command of the form:

 . . . SET some_column = some_info . . .

where SQL requires

 . . . SET some_column = 'some_info' . . .

(that is, quotes around the string value). SQLite is interpreting the the unquoted string as an expression consisting of a column name.

You cannot solve this problem by simply adding single quotes into your format string as you may believe. What happens if the substituted value itself contains a single quote? This way lies both string-escaping madness and the danger of SQL injection.

Instead, just use parameterization.

But, note that you can't parameterize the column name ( {Column} ), you would have to use string substitution for that while taking care not to allow injection to occur.

To improve upon nosklo 's answer above concerning the use of f-strings , you just have to use escaped quotes around the variables so they are sent as a string to SQLite:

import sqlite3

conn = sqlite3.connect("somedatabase.db")
c = conn.cursor()

def updatedb(colname, colvalue, rowid):
    with conn:
        c.execute(f"UPDATE tablename SET \"{colname}\" = \"{colvalue}\" WHERE rowidentifier = \"{rowid}\"")

NOTE

For safety reasons, don't use string interpolation with a database that relies on external user input. But, if you sanitize the input string(s), I guess you can make it work.

i am using mysql.connector

query = "INSERT INTO PICS (name,image) VALUES (%s,%s)"
param = (fname, DATA)
cursor.execute(query, param)
print("DONEEEEEE" * 100)
conn.commit()
cursor.close()
conn.close()

this is for the latest version of '8.0.27' for 2021

this worked for me !!!!

I have my own personal database I made for fun (so not that concerned with sql injections as its my own private database I made) and am trying to change the functions I created that use string formatting (.format()) and placeholders (?, %s, etc) and use f strings instead. I ran into a problem where one of my functions that updates a specified column into a specified row won't run now that I changed the sqlite3 query to f strings.

This is my current function using f strings:

import sqlite3
from tabulate import tabulate
conn = sqlite3.connect("Table.db")
c = conn.cursor()

def updatedb(Column, Info, IdNum):  
    with conn:
        data = c.execute(f"UPDATE Table_name SET {Column} = {Info} WHERE IdNum={IdNum}")
        c.execute(f"SELECT * FROM Table_name WHERE IdNum = {IdNum}")
    print(tabulate(data, headers="keys", tablefmt="grid", stralign='center', numalign='center'))

The function updates the table by updating a specified column of a specified row with the new info you want in that column. For example in a 3 x 3 table, instead of row 1, column 2 being 17, I can use the function to update row 1, column 2 to 18 if that column is an age or something. The select query after that is to just select that particular row that was updated and the print statement after that uses the tabulate package to print out a neat and organized table.

The error I get whenever I try to use this function is:

sqlite3.OperationalError: no such column: Info

Whatever I type in for the Info variable in the function is what the error becomes but I can't figure out how to fix the problem.

This is the update statement I had before attempting to change to f strings and it worked fine for me:

data = c.execute("UPDATE Table_name SET {} = ? WHERE IdNum=?".format(Column), (Info, IdNum))

It didn't seem like to would be that big of a change to change the above query to af string but it isn't working so any feedback would be appreciated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM