How to fix syntax error with UPDATE in SQLite3 Python module - python

I'm using python module sqlite3 as per the below code:
# Enter the randomised data into the dictionary:
for square in cube:
cur.execute("UPDATE cubes SET ? = ? WHERE id = ?", (square, cube[square], session["current_cube_id"]))
con.commit()
Which results in the following error:
cur.execute("UPDATE cubes SET ? = ? WHERE id = ?", (square, cube[square], session["current_cube_id"]))
sqlite3.OperationalError: near "?": syntax error
I don't seem to have a problem with INSERT or SELECT queries, so I assume there is a specific syntax required to UPDATE. From the documentation, tutorials and other examples I can find this seems to be correct - can anyone please assist with what might be the syntax error?

You can't define table, column names, or SQL keywords, using bind variables (the SET ? =) in UPDATE cubes SET ? = ? WHERE id = ?
I am not sure why you feel you need to have a dynamic column name, rather than UPDATE cubes SET mycol = ? WHERE id = ? but you need to specify your column name differently.
You'd have the exact same problem with insert or delete if your target column names, in an insert, or your where condition column names in a delete, were getting specified with ? placeholders. I assume you did not do this so you did not get the error.
Be very careful if you decide to build your query string dynamically as in
myquery = f"UPDATE cubes SET {my_user_supplied_column_name} = ? WHERE id = ?"
cur.execute(myquery, (cube[square], session["current_cube_id"]))
That opens you to a large class of extremely serious vulnerabilities, the SQL Injections because the user may enter anything they want in my_user_supplied_column_name. Best to be very careful as it also has a reputational risk: a savvy prospective employer might for example reject your application if they saw this type of construct, unguarded, in your code because it is an extremely grave, frequent and well-known risk.

Related

Python/Pyodbc/SQL - Updating a table and setting a field to a CSV File

I am trying to use pyodbc to update an existing MS Access database table with a very long multiline string. The string is actually a csv that has been turned into a string.
The query I am trying to use to update the table is as follows:
query = """
UPDATE Stuff
SET Results = '{}'
WHERE AnalyteName =
'{}'
""".format(df, analytename)
The full printed statement looks as follows:
UPDATE Stuff
SET Results =
'col a,col b,col c,...,col z,
Row 1,a1,b1,c1,
...,...,...,...,
Row 3000,a3000,b3000,c3000'
WHERE AnalyteName = 'Serotonin'
However this does not seem to be working, and I keep getting the following error:
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC Microsoft Access Driver] Syntax error in UPDATE statement. (-3503) (SQLExecDirectW)')
Which I assume is due to the format of the csv string I am trying to use to update the table with.
I have tried using INSERT and inserting a new row with the csv string and other relevant information and that seems to work. However, I need to use UPDATE as I will eventually be adding other csv strings to these columns. This leads me to believe that there is A) Something is wrong with the syntax of my UPDATE query (I am new to SQL syntax) or B) I am missing something from the documentation regarding UPDATE queries.
Is executing an UPDATE query like this possible? If so, where am I going wrong?
It would be determined by the table's field type.
For large amounts of text you'd need a blob field in your database table.
A blob field will store binary info so using blob will not 'see' illegal characters.
Answering my own question in case anyone else wants to use this.
It turns out what I was missing was brackets around the table column fields from my UPDATE statement. My final code looked something like this.
csv = df.to_csv(index=False)
name = 'some_name'
query = """
UPDATE Stuff
SET
[Results] = ?
WHERE
[AnalyteName] = ?
"""
self.cursor.execute(query, (csv, name))
I've seen several other posts here where brackets were not around the column names. However, since this is MS Access, I believe they were required for this query, or rather this specific query since it included a very long strong in the SET statement.
I welcome anyone else here to provide a more efficient method of performing this task or someone else who can provide more insight into why this is what worked for me.

Entering data into specific field using "WHERE" in "INSERT" command in SQL? (Python)

I'm currently writing a program for a parents evening system. I have two tables, a bookings table and a teacher table - set up with the following column headings: TeacherSubject | 15:30 | 15:35 | 15:40 etc... When people make a booking, they select a teacher from a drop-down menu and also a time. Therefore, I need the bookingID added into the booking table where the teacher selected = to the same teacher in the table and where time selected = time in the database.
At the moment, my code only attempts to match the teacher, but this doesn't work as I'm getting the error of: (line 5)
TypeError: 'str' object is not callable
Am I doing the whole thing wrong and is this actually possible with the way I have set the table up?
def insert(parent_name, parent_email, student_name,student_form,teacher,app_time,comments):
conn=sqlite3.connect("parentsevening.db")
cur=conn.cursor()
cur.execute("INSERT INTO bookings VALUES (NULL,?,?,?,?,?,?,?)",(parent_name,parent_email,student_name,student_form,teacher,app_time,comments))
cur.execute("INSERT INTO teachers VALUES (?) WHERE teachers = (?)" (id,teacherName,))
conn.commit()
conn.close()
This SQL Query is invalid.
INSERT INTO teachers VALUES (?) WHERE teachers = (?)
It should be
INSERT INTO teachers (id, name) VALUES(?, ?)
Note that I'm guessing the teachers columns (id, name) WHERE on the insert isn't valid because it's used to find data (SELECT, UPDATE, DELETE)
OK, let's take out the comments and make this into an answer.
Python error
I think your error comes from WHERE teachers = (?) have you tried WHERE teachers = ? instead.
But...
bad sql syntax
Also that command as a whole doesnt make much sense, SQL syntax wise - you seem to be trying to insert where a teacher that doesn't exist (if you are inserting them) and values on an insert does not go with where and where needs a from. i.e. once you've solved your python error, sqlite is going to have a fit as well.
That's already covered by another answer.
But...
probably not what you should be doing
If you have an existing teacher, you only need to insert their teacherid into table bookings. You don't have to, and in fact, you can't insert into table teachers at this point, you'd get a duplicate data error.
So, rather than fixing your second query, just get rid of it entirely.
If you can get a command line or GUI SQL tool up, try running these queries by hardcoding them by hand before coding them in Python. the sqlite command should be able to do that for you.
(recommendation) don't use insert table values
Try being explicit with insert into table (<column list>) values .... The reason is that, as soon as the table changes in some way that affects column order (possibly an alter column) the values won't line up with the implied insert list. hard to debug, hard to know what was intended at time of writing. Been there, done that. And had to debug buncha folks' code who took this shortcut, it's never fun

Unable to see table after creation in Flask-sqlalchemy [duplicate]

When I make a MySQL table order, it is created successfully but, when I execute any query against it, it says "error 1064 , syntax error".
When I change the name to orders, it works fine.
But I don't want to change the name. How can I execute our query against the order table?
can you use something like?
select * from `order`
The word order is actually an SQL keyword. You would have the same problem if you tried to use a table called group or select. You can fix it is MySQL by using quotes around it, along the lines of:
select f1, f2 from `order` where blah blah blah ...
However, unless your table will only ever hold a single order (in which case it won't do so for long since the underlying business will soon be bankrupt), you should probably call your table orders.
That solves both your problems, the one you found and the one you didn't :-)
I got here because I was searching for similar solution for SQL CE. There using
order
'order'
"order"
doesn't work.
What worked was:
[order]
Maybe it'll help someone else also.
This should fix the problem:
e.g
mysql>
Create table order(
ID char(5),
QTY(3)
)
;

Can I use string formatting while querying a database in python

I have been learning sqlite3 in python and I was wondering if I could use string formatting to edit the database or query it.
e.g. - SELECT %s FROM (table_name) where % can be the users input stored in a variable?
I tried it but it doesn't work so can someone please give me a working example.
Any help is appreciated. Thanks
Guys i tried this:
dursor = conn.execute("SELECT id FROM books")
# this helps find the correct id for storing in the database
for i in dursor:
lis.append(i[0])
command = """INSERT INTO books VALUES ({0}, {name}, {author})""".format(lis[-1] + 1, name=client_name, author = client_author)
and then
conn.execute(command)
but it returns no such column (name)
when i tried the same query in khan academy sql it worked why not here?
You can place question mark on your query string and pass the parameters from user input while calling the .execute() as a tuple.
Though i don't believe you are using it in a production. If it is the case than first take the data from user, sanitize it and see if you really want to let the user do what he actually wants to do.
Hope this helps:
param1 = sys.argv[1]
param2 = sys.argv[2]
query = "SELECT ? FROM (table_name) where id = ?"
cursor.execute(query, (param1,param2))
I'm unsure if you can do it in sqlite3 but I'd be looking for any alternative method if I were you. Are you REALLY wanting to allow the user to be able to actually alter your SQL on the fly? That is a potentially huge security hole you'd be creating.
e.g. user can essentially alter...
select ? from innocentTable
...to...
select * from tblUser -- from innocentTable
...and trawl your entire user table, just takes a bit of guess work to come up with the object names.
I'd suggest you read up on SQL Injection Attacks then look for an alternative way to achieve what you've suggested.

Sqlite3 Updating Row Defined by a Variable

Not sure if I phrased the title correctly, but basically my question is is it possible to have sqlite update a row which is defined by a variable? For example:
db.execute('''UPDATE CUSTOMER SET ? = ? WHERE CUSTOMER_ID = ?''', (title, info.get(), k))
where 'title' (the first question mark) is the name of the 'row' I want to update within the table Customer. I have tried the above code but it doesn't work. Does anybody know if it is possible to do this with sqlite3 in any way?
SQL parameters are designed to never be interpretable as SQL objects (like column names); that is one of their major usecases. If they didn't they wouldn't prevent SQL injection attacks. Instead, the title value is either properly escaped as a value, or rejected altogether as the syntax doesn't allow a value in that location.
As such, you need to make sure that your title variable is a proper SQL object name (never take user input directly here) and use string formatting for just that value:
db.execute(
'''UPDATE CUSTOMER SET {} = ? WHERE CUSTOMER_ID = ?'''.format(title),
(info.get(), k))
You probably want to match title against a pre-defined set of possible column names first.
Can you try like this
query = "UPDATE CUSTOMER SET %s = '%s' WHERE CUSTOMER_ID = %d" %(title, info.get(), k)
db.execute(query)
May be you need to commit it.

Categories