This question already has an answer here:
How to get variable length placeholders in a Python call to SQLite3
(1 answer)
Closed 7 years ago.
When there are only a few parameters I can do this
cur.execute(INSERT INTO table (col1,col2) VALUES (?,?), (1,2))
but what if I have like 50 parameters? I don't want to write 50 question marks in that case. Is there a way to do something like the following?
cur.execute(INSERT INTO table (listOfColumns) VALUES tuple(['?']*len(listOfColumns)), (listOfValues))
Yes, you just build the SQL statement dynamically:
sql = ('INSERT INTO table ({}) VALUES ({})'.format(','.join(listOfColumns),
','.join('?'*len(listOfColumns))))
cur.execute(sql, listOfValues)
Note that this assumes the list of columns was generated locally and not tainted by user input. If the list of columns could be tainted you need to check it pretty carefully to ensure that it only contains valid column names before inserting it into SQL code.
Related
This question already has answers here:
Variable table name in sqlite
(9 answers)
Closed 2 years ago.
So, I am new to Stackoverflow and I hope I'm writing this question well. So I'm trying to choose a table from my database (that contains 5 tables) based on user input in python. However I'm not quite sure how to do it. Here is the code:
user_input = "table1"
db.execute("SELECT number FROM (?) WHERE person = 1;")
I'm searching for a way if it is possible. Anyway any help would be appreciated.
Well, after some verifications in order to forbid SQL injections, the easiest way is to format the query string with the user input.
db.execute ("SELECT * FROM MyTable WHERE person = {};".format(user_input))
And the content of user_input would be placed on the curly brackets.
It's not very clear on how you're getting user input, though.
This question already has answers here:
How to create a "singleton" tuple with only one element
(4 answers)
Closed 3 years ago.
I have the following code and it works, but I need to understand why there is a comma after the variable id_to_remove, can someone explain to me why that has to be there? (I bolded the part I don't understand)
def delete_user(id_to_remove):
sql = "DELETE FROM USERS WHERE ID = ?"
conn = create_connection()
cursor = conn.cursor()
**cursor.execute(sql, (id_to_remove, ))**
conn.commit()
conn.close()
So I don't know why its id_to_remove, and not just cursor.execute(sql,(id_to_remove))
Because it will replace all the ? values with the ones in the tuple. If you don't put a comma then it is a single value, you need to add it to construct a single value tuple.
This question already has answers here:
Dynamic SQL WHERE clause generation
(3 answers)
How to use variables in SQL statement in Python?
(5 answers)
Python sqlite3 parameterized drop table
(1 answer)
Closed 4 years ago.
From my Python code (Flask application, actually), I need to execute sqlite query, of the following structure
SELECT some_column FROM My_table WHERE some_column=some_value;
Now, some_column recurs twice in the query, one way to execute it is:
cursor.execute('SELECT ? FROM Users WHERE ?=?;', (some_column, some_column, some_value))
Which is not very nice/Pythonic. Then I came up with:
cursor.execute('SELECT {0} FROM Users WHERE {0}=?;'.format(some_column), (some_value,))
Finally, I ended up using .format() all the way:
cursor.execute('SELECT {0} FROM Users WHERE {0}={1};'.format(some_column, some_value), ())
I am wondering if there is prettier and/or more Pythonic way to pass recurring arguments into sqlite's cursor.execute()?
First syntax is incorrect. In SQL parameterized queries can use parameters for values, not for table or column names.
Third form is bad because it hard codes a value in a query which is forbidden per best practices. It used to be common some times ago and was the cause for SQL injection security problems.
So the only possibility is second form: use string construction for table and column names, and parameters for values.
But anyway, your query is close to non sense: you ask the value of one single column when you fix that column value. For each selected row, the value will be some_value!
So, I assume that this was a simplified example of a more complex question, but without more context, I simply cannot imagine why you are asking this question and what is your real problem.
It's not a big improvement, but since you tagged Python 3, consider the f-string:
f"SELECT {col} FROM Users WHERE {col}={val}"
As Klaus D. points out in a comment, however, it's not best practice to allow values to be format strings, as in some cases it makes your code vulnerable to SQL injection.
It's a little less compact, but you can use a mix of f-string (for column names) and sqlite ? syntax to input values (basically a mashup of your first two examples):
params = (val,)
q = f"SELECT {col} FROM Users WHERE {col} = ?"
cursor.execute(q, params)
This question already has answers here:
imploding a list for use in a python MySQLDB IN clause
(8 answers)
Closed 1 year ago.
I want to insert a list in my database but I can't.
Here is an example of what I need:
variable_1 = "HELLO"
variable_2 = "ADIOS"
list = [variable_1,variable_2]
INSERT INTO table VALUES ('%s') % list
Can something like this be done? Can I insert a list as a value?
When I try it, an error says that is because of an error in MySQL syntax
The answer to your original question is: No, you can't insert a list like that.
However, with some tweaking, you could make that code work by using %r and passing in a tuple:
variable_1 = "HELLO"
variable_2 = "ADIOS"
varlist = [variable_1, variable_2]
print "INSERT INTO table VALUES %r;" % (tuple(varlist),)
Unfortunately, that style of variable insertion leaves your code vulnerable to SQL injection attacks.
Instead, we recommend using Python's DB API and building a customized query string with multiple question marks for the data to be inserted:
variable_1 = "HELLO"
variable_2 = "ADIOS"
varlist = [variable_1,variable_2]
var_string = ', '.join('?' * len(varlist))
query_string = 'INSERT INTO table VALUES (%s);' % var_string
cursor.execute(query_string, varlist)
The example at the beginning of the SQLite3 docs shows how to pass arguments using the question marks and it explains why they are necessary (essentially, it assures correct quoting of your variables).
Your question is not clear.
Do you want to insert the list as a comma-delimited text string into a single column in the database? Or do you want to insert each element into a separate column? Either is possible, but the technique is different.
Insert comma-delimited list into one column:
conn.execute('INSERT INTO table (ColName) VALUES (?);', [','.join(list)])
Insert into separate columns:
params = ['?' for item in list]
sql = 'INSERT INTO table (Col1, Col2. . .) VALUES (%s);' % ','.join(params)
conn.execute(sql, list)
both assuming you have established a connection name conn.
A few other suggestions:
Try to avoid INSERT statements that do not list the names and order of the columns you're inserting into. That kind of statement leads to very fragile code; it breaks if you add, delete, or move columns around in your table.
If you're inserting a comma-separted list into a single-field, that generally violates principals of database design and you should use a separate table with one value per record.
If you're inserting into separate fields and they have names like Word1 and Word2, that is likewise an indication that you should be using a separate table instead.
Never use direct string substitution to create SQL statements. It will break if one of the values is, for example o'clock. It also opens you to attacks by people using SQL injection techniques.
You can use json.dumps to convert a list to json and write the json to db.
For example:
insert table example_table(column_name) values(json.dumps(your_list))
This question already has answers here:
How to print a list of tuples with no brackets in Python
(5 answers)
Closed 5 years ago.
Currently doing some selecting exercises using SQLite 3 on Python 3. This all works fine, however I want to format the output onto the shell. At the moment, when I run this program:
def select_all_products2(tech):
with sqlite3.connect('movie.db') as db:
cursor = db.cursor()
cursor.execute("select * from User where userOccupation=?",(tech,))
products2 = cursor.fetchall()
return products2
products2 = select_all_products2("technician")
print(products2)
It just prints all the matching fields out in a long, ugly list. Is there a way I can format the output onto the shell, say, with a \n after each field so it's much more easier to read?
Well yes, an SQL result set is an iterable so you can start with
for product in select_all_products2("technician"):
print (product)
Then you realize that a row is also an iterable which makes it quite possible to format the output into nice looking columns.