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.
Related
This question already has answers here:
How to use variables in SQL statement in Python?
(5 answers)
Closed 2 months ago.
def update_inv_quant():
new_quant = int(input("Enter the updated quantity in stock: "))
Hello! I'm wondering how to insert a user variable into an sql statement so that a record is updated to said variable. Also, it'd be really helpful if you could also help me figure out how to print records of the database into the actual python console. Thank you!
I tried doing soemthing like ("INSERT INTO Inv(ItemName) Value {user_iname)") but i'm not surprised it didnt work
It would have been more helpful if you specified an actual database.
First method (Bad)
The usual way (which is highly discouraged as Graybeard said in the comments) is using python's f-string. You can google what it is and how to use it more in-depth.
but basically, say you have two variables user_id = 1 and user_name = 'fish', f-string turns something like f"INSERT INTO mytable(id, name) values({user_id},'{user_name}')" into the string INSERT INTO mytable(id,name) values(1,'fish').
As we mentioned before, this causes something called SQL injection. There are many good youtube videos that demonstrate what that is and why it's dangerous.
Second method
The second method is dependent on what database you are using. For example, in Psycopg2 (Driver for PostgreSQL database), the cursor.execute method uses the following syntax to pass variables cur.execute('SELECT id FROM users WHERE cookie_id = %s',(cookieid,)), notice that the variables are passed in a tuple as a second argument.
All databases use similar methods, with minor differences. For example, I believe SQLite3 uses ? instead of psycopg2's %s. That's why I said that specifying the actual database would have been more helpful.
Fetching records
I am most familiar with PostgreSQL and psycopg2, so you will have to read the docs of your database of choice.
To fetch records, you send the query with cursor.execute() like we said before, and then call cursor.fetchone() which returns a single row, or cursor.fetchall() which returns all rows in an iterable that you can directly print.
Execute didn't update the database?
Statements executing from drivers are transactional, which is a whole topic by itself that I am sure will find people on the internet who can explain it better than I can. To keep things short, for the statement to physically change the database, you call connection.commit() after cursor.execute()
So finally to answer both of your questions, read the documentation of the database's driver and look for the execute method.
This is what I do (which is for sqlite3 and would be similar for other SQL type databases):
Assuming that you have connected to the database and the table exists (otherwise you need to create the table). For the purpose of the example, i have used a table called trades.
new_quant = 1000
# insert one record (row)
command = f"""INSERT INTO trades VALUES (
'some_ticker', {new_quant}, other_values, ...
) """
cur.execute(command)
con.commit()
print('trade inserted !!')
You can then wrap the above into your function accordingly.
I have a function that executes many SQL queries with different dates.
What I want is to pass all dates and other query variables as function parameters and then just execute the function. I have figured out how to do this for datetime variables as below. But I also have a query that looks at specific campaign_names in a database and pulls those as strings. I want to be able to pass those strings as function parameters but I haven't figured out the correct syntax for this in the SQL query.
def Camp_eval(start_date,end_1M,camp1,camp2,camp3):
query1 = f"""SELECT CONTACT_NUMBER, OUTCOME_DATE
FROM DATABASE1
where OUTCOME_DATE >= (to_date('{start_date}', 'dd/mm/yyyy'))
and OUTCOME_DATE < (to_date('{end_1M}', 'dd/mm/yyyy'))"""
query2 = """SELECT CONTACT_NUMBER
FROM DATABASE2
WHERE (CAMP_NAME = {camp1} or
CAMP_NAME = {camp2} or
CAMP_NAME = {camp3})"""
Camp_eval('01/04/2022','01/05/2022','Camp_2022_04','Camp_2022_05','Camp_2022_06')
The parameters start_date and end_1M work fine with the {} brackets but the camp variables, which are strings don't return any results even though there are results in the database with those conditions if I were to write them directly in the query.
Any help would be appreciated!!
Please, do not use f-strings for creating SQL queries!
Most likely, any library you use for accessing a database already has a way of creating queries: SQLite docs (check code examples).
Another example: cur.execute("SELECT * FROM tasks WHERE priority = ?", (priority,)).
Not only this way is safer (fixes SQL Injection problem mentioned by #d-malan in comments), but it also eliminates the need to care about how data is represented in SQL - the library will automatically cast dates, strings, etc. in what they need to be casted into. Therefore, your problem can be fixed by using proper instruments.
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.
i have a hopefully simple Problem with an SQL-command
Code:
c.execute("SELECT MAX(pic_num) FROM Pictures WHERE id = "+str(user_id))
pic_num is a column in the database and user_id is an Integer in the database
I thought everything would be right but i get this
Error:
sqlite3.OperationalError: near ")": syntax error
this Information doesn't help me at all
The correct way to use python's db-api is to use placeholders in your SQL query and pass query values along, ie:
c.execute("SELECT MAX(pic_num) FROM Pictures WHERE id=?", [user_id,])
Note that this might not necessarily solve your problem but since you didn't post the schema nor the user_id value we can't try & reproduce the issue.
You should python sqlite module's substitution instead like so:
c.execute("SELECT MAX(pic_num) FROM Pictures WHERE id = ?", (user_id, ))
Thank you all for the fast answers!
c.execute("SELECT MAX(pic_num) FROM Pictures WHERE id = ?", (str(user_id), ))
this finally worked :)
I already have written some libs which should handle SQL-injection (they test the Input for quotes but you're right im very new with SQL :D)
The problem:
I am working on a bit of code that is meant to create a new record in a linking table. The linking table has a primary key that is an auto number, the other two fields are VARCHAR with a length of 10.
The issue I'm having is I cannot seem to get partID into the table. If you look at the sql output you can clearly see it write None and u'1' (the orderID) to the table. So that tells me its recieving the orderID just fine. Also you can see that I did a print to find out what is inside my variable before passing it to the new object. It has 3 in it which is the correct partId. Somewhere between creating the new object and writing to the table it passes a null.
I've tried to cast it, Ive tried different ways of pulling the partID from the database, etc and I cannot for the life of me figure out what is wrong.
The code:
def updateOrderParts_view(request):
part = None
partToOrder = None
idnum = None
part = DBSession.execute(\
"SELECT partID "+\
"FROM tblParts "+\
"WHERE partName = " + "'" +request.POST['partName'] +"'").fetchone()
print "<---DEBUG--->"
print part['partID']
partToOrder = PartsByOrder(part['partID'], request.POST['orderID'])
DBSession.add(partToOrder)
return{}
The terminal output:
<---DEBUG--->
3
2013-04-24 08:14:47,985 INFO [sqlalchemy.engine.base.Engine][Dummy-2] INSERT INTO "tblPartsByOrder" ("partID", "orderID") VALUES (?, ?)
2013-04-24 08:14:47,985 INFO [sqlalchemy.engine.base.Engine][Dummy-2] (None, u'1')
2013-04-24 08:14:47,986 INFO [sqlalchemy.engine.base.Engine][Dummy-2] COMMIT
I would appreciate any thoughts or comments on this issue
Thanks for your time
First, I would look at doing the SQL lookup a little different, if you can. (I guess it depends, do you have a model based on "tblParts"? I'm going to use an example assuming there is a model object "Part"):
part = DBSession.query(Part.partID).filter(Part.partName == request.POST['partName']).first()
From there, I'm rusty on the exact syntax but I think you could do something like
print "<---DEBUG--->"
print part
partToOrder = PartsByOrder(part, request.POST['orderID'])
DBSession.add(partToOrder)
return{}
You might need to case "part" to a string (str(part)) if it's a casting problem.
Good luck,