This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Closed 5 years ago.
I'm trying to make an access control system based on pincode entry. I'm having issues on how to check if the pincode entered is present in the MySQL database.
Below snippet works, it asks for the pincode, and can successfully parse it with the database when the pincode only contains numbers.
pin_inp = raw_input("Enter PIN: ")
cursor.execute("SELECT COUNT(1) FROM members WHERE pincode = " + pin_inp + ";")
But I would like to have alphanumerical pincodes though. I thought I could just create the pincode column as VARCHAR and enter alphanumerical pincodes, but then it will not successfully parse with the database. With an alphanumerical entry I get this error:
_mysql_exceptions.OperationalError: (1054, "Unknown column '7988DB' in 'where clause'")
So I have a few rows in the members table for testing, some with numerical values in column pincode, some with alphanumerical values. When I run above code, the numerical entries are OK, but the alphanumerical values throw the 1054 error.
When you use numerical values, you just enter them like you did, but when you used alphanumerical values, you must surround them with apostrophes like this'my value'. So change your code to:
cursor.execute("SELECT COUNT(1) FROM members WHERE pincode = '" + pin_inp + "';")
However, be careful here. This code will be open to SQL injection since the pin_inp is coming from user's input. You either have to validate it, or better use a parameterized SQL statement.
Related
This question already has answers here:
SQLite: Why can't parameters be used to set an identifier?
(3 answers)
Closed 3 months ago.
I am creating a wishlist app using Tkinter and sqlite3. I want the user to be able to create tables in database by imputing names. For that I connected a button to this function:
def create_table(table_name):
connection = sql.connect(f'{directory}\main.sqlite')
cursor = connection.cursor()
cursor.execute("CREATE TABLE ? (name TEXT, price REAL, url TEXT)",(table_name,))
connection.close()
This doesn't work and I get:
cursor.execute("create table ? (name text, price real, url text)",(table_name,))
sqlite3.OperationalError: near "?": syntax error
Is it possible to do string formatting in CREATE TABLE? I'd rather create separate tables than one with additional column for id of items. I don't want to use f-string as it can be an issue if user inputs commands instead of a name.
Nope, this cannot be done. A table name cannot act as a dynamic parameter from SQLite's point of view. You will need to do something like this:
f'CREATE TABLE {table_name} (name TEXT, price REAL, url TEXT)'
But first you will need to validate the user input for table_name. Which shouldn't be a problem if you want to limit the allowed characters to (for example) only 1+ English letters and 0+ underscores. You might also want to validate the table name length and uniqueness somehow.
This question already has answers here:
sqlite3.OperationalError: no such column - but I'm not asking for a column?
(2 answers)
Closed 2 years ago.
Forgive me if this is a basic question, I'm learning on my own and having some trouble. I have built a database with SQLite and am trying to write something that can display the 'description' of an entry when the name is entered into an entry box.
record_id = call_field.get()
# Query the database
c.execute("SELECT name, abbr, description FROM TQ_QUICKTEXT WHERE name =" + record_id)
records = c.fetchall()
# Loop through results
for record in records:
display.insert(1.0, record[2])
When I type the name of the entry that has been put into the database, an error is returned saying there is no column with that name. However, when I type the actual word 'name' into the entry box and run the function every single description entry is returned. If someone wouldn't mind pointing out where I've made mistakes it would be greatly appreciated. Thank you in advance.
The SELECT statement that is executed currently looks like this:
SELECT name, abbr, description FROM TQ_QUICKTEXT WHERE name = something (where something is the value of record_id)
Because there are no quotes around the value of record_id, it thinks it is a column name, not text. This is why when you try the name of a record, you get an error because that is not a column name, but name works, because it is the name of a column.
Adding quotes will fix the problem, but the database is vulnerable to SQL injection.
It is good security practise to parameterise SQL queries to prevent this. This is done by using ? in place of parameters and then passing a tuple of parameters to the execute function. This protects you from SQL injection.
After these changes, the c.execute statment should look like this:
c.execute("SELECT name, abbr, description FROM TQ_QUICKTEXT WHERE name = ?", (record_id,))
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))
i have a table that records the attendance of students. The table have 4 columns , one for the student ID and the other are for week1 ,week2 and week3 (All the columns are integers). The attendance is recorded by entering only 1 for the certain week ( or zero if he was absent) . My problem is here , when i want to add the attendance i use the update statement as follow :
week_number=input('enter the week ( week1/week2/week3')
id=int(input('enter student ID'))
sat="UPDATE Attendance2 SET %s=1 WHERE ID=%s "
cur.execute(sat, (week_number,id,))
conn.commit()
As you can see ,I don't know what the column that the user will refer to ( it is a variable ) , so i have used %s behind the SET, but it is wrong.
Here is the error :
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''week1'=1 WHERE ID=300' at line 1
Any help please ? How do i write a variable column name in a execute statement ?
Note that i am updating only the attended students , that's why there is 1 in the UPDATE statement
AFAICT, it's supposed to be ok to surround keys with quotes. But as you say that all datatypes are integers, your values have no issues.
And because it says this is a syntax error (and not column issue, what it would yell if it was not finding week1), it leads me to believe the issues actually are your quotes, which if not expected by mysql's SQL grammar, it would indeed yell about a syntax issue.
mysql […] near ''week1'=1 WHERE ID=300' at line 1
^
What makes a python string gets surrounded by single quotes? It's the repr() version of the string, the one you get when you type a string on the REPL:
>>> x = '42'
>>> x
'42'
>>> print(repr(x))
'42'
>>> print(x)
42
I'm not sure why this issue would happen to you. A good ideais to use the python form of formatting strings, and run:
sat="UPDATE Attendance2 SET {}=1 WHERE ID={}".format(week_number, id)
if it still happens, you can try to force typing of week_number into a str(), using str(week_number).
Talking about formatting strings, you might want to enforce the typing, so you avoid surprises:
sat="UPDATE Attendance2 SET {:s}=1 WHERE ID={:d}".format(str(week_number), int(id))
which will make sure week_number is a valid string and formatted as a string, and id is a valid integer and formatted as an integer.
Nota Bene: avoid using id in your code, which is a python reserved keyword, and instead use _id, ident or idx. It's always a good idea to avoid shadowing global python keywords.
HTH
try
sat="UPDATE Attendance2 SET " + week_number + "='1' WHERE ID='" + student_id + "'"
cur.execute(sat)
...
hope this helps ^^-d
PS: It is easier to test the code if you set the variables week_number and student_id "hardwired", e.g.:
week_number = "week1"
student_id = "1"
PPS: The way you design your table is a bit redundant which may lead to update errors in the future. It might e.g. be better to have a 2 column table with the student_id and attended_week(as 1,2,3).
In my Python code when I ask the user to input a string to SELECT, it works but when I try the UPDATE using the same input doesn't allow me to execute
Here is my code after the connection has been successfully done
curs = connection.cursor()
str_input1 = str(input("Input : "))
str_input2 = str(input("Input : "))
statement = "UPDATE table SET variable1 = "+str_input1+" WHERE name = "+str_input2
curs.execute(statement)
connection.commit
In theory this following code should work and update the variable, but instead I get the error at line curs.execute(statement) saying
cx_Oracle.DatabaseError: ORA-00904: John: invalid identifier
John was the str_input2 for where clause
Maybe its the format that was giving me an error but I'm not too sure.
Can someone point out what was the problem with my code?
The error is because you're not quoting the values. You'd get the exact same error from a SELECT statement.
These statements search for rows where the name column matches the string John:
SELECT * FROM table WHERE name = "John"
UPDATE table SET variable1 = "Hi" WHERE name = "John"
These statements search for rows where the name columns matches the John column—and if there is no John column, that's an error:
SELECT * FROM table WHERE name = John
UPDATE table SET variable1 = "Hi" WHERE name = John
So, you could fix this by just putting quotes around the values.
But you really, really, really shouldn't. This opens you up to SQL injection attacks, and stupid bugs where you don't quote or escape special characters properly, and performance problems where the database engine can't tell that you're running the same query over and over, and so on.
What you want to do is to use SQL parameters, instead of trying to format the string. I don't remember which parameter style cx_Oracle uses, but you can just import cx_Oracle; print(cx_Oracle.paramstyle), and look it up in the table to find out. And then do something like:
statement = "UPDATE table SET variable1 = :v WHERE name = :n"
curs.execute(statement, {'v': str_input1, 'n': str_input2})
Also, a few side notes:
connection.commit doesn't do anything; you're just referencing the commit method, not calling it. You need parentheses: connection.commit()
str(input()) is pointless. The input function always returns a string, so there's no reason to call str on it. (Unless you're using Python 2.x, in which case you should be using raw_input(), which returns a string, instead of using input to eval the string—opening up the same kinds of security problems as the SQL injection attack above—only to convert it back to a string.)